397 lines
8.8 KiB
Go
397 lines
8.8 KiB
Go
package retriever
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
obrimRetrieverTypeJson = "json"
|
|
obrimRetrieverTypeDb = "db"
|
|
|
|
ObrimRetrieverCodeSuccessResource = "SUCCESS_RESOURCE_RETRIEVED"
|
|
ObrimRetrieverCodeSuccessPath = "SUCCESS_PATH_RETRIEVED"
|
|
ObrimRetrieverCodeSuccessFields = "SUCCESS_FIELDS_RETRIEVED"
|
|
|
|
ObrimRetrieverCodeFailedUnsupportedType = "FAILED_UNSUPPORTED_TYPE"
|
|
ObrimRetrieverCodeFailedMissingConfig = "FAILED_MISSING_CONFIGURATION"
|
|
ObrimRetrieverCodeFailedInvalidConfig = "FAILED_INVALID_CONFIGURATION"
|
|
ObrimRetrieverCodeFailedResourceNotFound = "FAILED_RESOURCE_NOT_FOUND"
|
|
ObrimRetrieverCodeFailedPathNotFound = "FAILED_PATH_NOT_FOUND"
|
|
ObrimRetrieverCodeFailedFieldNotFound = "FAILED_FIELD_NOT_FOUND"
|
|
ObrimRetrieverCodeFailedNotImplemented = "FAILED_NOT_IMPLEMENTED"
|
|
ObrimRetrieverCodeFailedProviderUnavailable = "FAILED_PROVIDER_UNAVAILABLE"
|
|
)
|
|
|
|
// ObrimRetrieverJsonProvider defines a JSON retrieval provider.
|
|
type ObrimRetrieverJsonProvider interface {
|
|
Retrieve() (any, error)
|
|
}
|
|
|
|
// ObrimRetrieverResponse defines the standardized utility response.
|
|
type ObrimRetrieverResponse struct {
|
|
Status bool `json:"status"`
|
|
Code string `json:"code"`
|
|
Payload map[string]any `json:"payload"`
|
|
}
|
|
|
|
// obrimRetrieverJsonRegistry stores registered JSON providers.
|
|
var obrimRetrieverJsonRegistry = map[string]ObrimRetrieverJsonProvider{}
|
|
|
|
// obrimRetrieverDbRegistry stores registered DB providers.
|
|
var obrimRetrieverDbRegistry = map[string]any{}
|
|
|
|
// ObrimRetriever retrieves data using the configured retrieval type.
|
|
func ObrimRetriever(retrievalType string, config map[string]any) map[string]any {
|
|
if !obrimRetrieverValidateType(retrievalType) {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedUnsupportedType,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
if errCode := obrimRetrieverValidateConfig(retrievalType, config); errCode != "" {
|
|
return obrimRetrieverBuildResponse(false, errCode, nil)
|
|
}
|
|
|
|
switch retrievalType {
|
|
case obrimRetrieverTypeJson:
|
|
return obrimRetrieverJson(config)
|
|
|
|
case obrimRetrieverTypeDb:
|
|
return obrimRetrieverDb(config)
|
|
|
|
default:
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedUnsupportedType,
|
|
nil,
|
|
)
|
|
}
|
|
}
|
|
|
|
// ObrimRetrieverJsonRegister registers a JSON provider.
|
|
func ObrimRetrieverJsonRegister(resource string, provider any) {
|
|
jsonProvider, ok := provider.(ObrimRetrieverJsonProvider)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
obrimRetrieverJsonRegistry[resource] = jsonProvider
|
|
}
|
|
|
|
// ObrimRetrieverDbRegister registers a DB provider.
|
|
func ObrimRetrieverDbRegister(resource string, provider any) {
|
|
obrimRetrieverDbRegistry[resource] = provider
|
|
}
|
|
|
|
// obrimRetrieverValidateType validates the retrieval type.
|
|
func obrimRetrieverValidateType(retrievalType string) bool {
|
|
switch retrievalType {
|
|
case obrimRetrieverTypeJson:
|
|
return true
|
|
|
|
case obrimRetrieverTypeDb:
|
|
return true
|
|
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// obrimRetrieverValidateConfig validates configuration.
|
|
func obrimRetrieverValidateConfig(
|
|
retrievalType string,
|
|
config map[string]any,
|
|
) string {
|
|
if config == nil {
|
|
return ObrimRetrieverCodeFailedMissingConfig
|
|
}
|
|
|
|
switch retrievalType {
|
|
case obrimRetrieverTypeJson:
|
|
return obrimRetrieverJsonValidate(config)
|
|
|
|
case obrimRetrieverTypeDb:
|
|
return obrimRetrieverDbValidate(config)
|
|
|
|
default:
|
|
return ObrimRetrieverCodeFailedUnsupportedType
|
|
}
|
|
}
|
|
|
|
// obrimRetrieverResolveProvider resolves a provider.
|
|
func obrimRetrieverResolveProvider(
|
|
retrievalType string,
|
|
resource string,
|
|
) (any, bool) {
|
|
switch retrievalType {
|
|
case obrimRetrieverTypeJson:
|
|
provider, ok := obrimRetrieverJsonRegistry[resource]
|
|
return provider, ok
|
|
|
|
case obrimRetrieverTypeDb:
|
|
provider, ok := obrimRetrieverDbRegistry[resource]
|
|
return provider, ok
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
// obrimRetrieverBuildResponse builds a standard response.
|
|
func obrimRetrieverBuildResponse(
|
|
status bool,
|
|
code string,
|
|
payload map[string]any,
|
|
) map[string]any {
|
|
return map[string]any{
|
|
"status": status,
|
|
"code": code,
|
|
"payload": payload,
|
|
}
|
|
}
|
|
|
|
// obrimRetrieverJson processes JSON retrieval requests.
|
|
func obrimRetrieverJson(config map[string]any) map[string]any {
|
|
resource := config["resource"].(string)
|
|
|
|
providerAny, ok := obrimRetrieverResolveProvider(
|
|
obrimRetrieverTypeJson,
|
|
resource,
|
|
)
|
|
if !ok {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedResourceNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
provider, ok := providerAny.(ObrimRetrieverJsonProvider)
|
|
if !ok {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedProviderUnavailable,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
if fieldsValue, exists := config["fields"]; exists {
|
|
return obrimRetrieverJsonFields(provider, fieldsValue)
|
|
}
|
|
|
|
if pathValue, exists := config["path"]; exists {
|
|
return obrimRetrieverJsonPath(provider, pathValue.(string))
|
|
}
|
|
|
|
return obrimRetrieverJsonResource(provider)
|
|
}
|
|
|
|
// obrimRetrieverJsonResource retrieves an entire resource.
|
|
func obrimRetrieverJsonResource(
|
|
provider ObrimRetrieverJsonProvider,
|
|
) map[string]any {
|
|
data, err := provider.Retrieve()
|
|
if err != nil {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedResourceNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
return obrimRetrieverBuildResponse(
|
|
true,
|
|
ObrimRetrieverCodeSuccessResource,
|
|
map[string]any{
|
|
"data": data,
|
|
},
|
|
)
|
|
}
|
|
|
|
// obrimRetrieverJsonPath retrieves a path value.
|
|
func obrimRetrieverJsonPath(
|
|
provider ObrimRetrieverJsonProvider,
|
|
path string,
|
|
) map[string]any {
|
|
data, err := provider.Retrieve()
|
|
if err != nil {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedResourceNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
value, found := obrimRetrieverJsonResolvePath(data, path)
|
|
if !found {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedPathNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
return obrimRetrieverBuildResponse(
|
|
true,
|
|
ObrimRetrieverCodeSuccessPath,
|
|
map[string]any{
|
|
"data": value,
|
|
},
|
|
)
|
|
}
|
|
|
|
// obrimRetrieverJsonFields retrieves multiple field values.
|
|
func obrimRetrieverJsonFields(
|
|
provider ObrimRetrieverJsonProvider,
|
|
fieldsValue any,
|
|
) map[string]any {
|
|
data, err := provider.Retrieve()
|
|
if err != nil {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedResourceNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
fields, ok := obrimRetrieverNormalizeFields(fieldsValue)
|
|
if !ok {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedInvalidConfig,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
result := map[string]any{}
|
|
|
|
for _, field := range fields {
|
|
value, found := obrimRetrieverJsonResolvePath(data, field)
|
|
if !found {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedFieldNotFound,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
result[field] = value
|
|
}
|
|
|
|
return obrimRetrieverBuildResponse(
|
|
true,
|
|
ObrimRetrieverCodeSuccessFields,
|
|
map[string]any{
|
|
"data": result,
|
|
},
|
|
)
|
|
}
|
|
|
|
// obrimRetrieverJsonValidate validates JSON configuration.
|
|
func obrimRetrieverJsonValidate(config map[string]any) string {
|
|
resourceValue, exists := config["resource"]
|
|
if !exists {
|
|
return ObrimRetrieverCodeFailedMissingConfig
|
|
}
|
|
|
|
resource, ok := resourceValue.(string)
|
|
if !ok || strings.TrimSpace(resource) == "" {
|
|
return ObrimRetrieverCodeFailedInvalidConfig
|
|
}
|
|
|
|
_, hasPath := config["path"]
|
|
_, hasFields := config["fields"]
|
|
|
|
if hasPath && hasFields {
|
|
return ObrimRetrieverCodeFailedInvalidConfig
|
|
}
|
|
|
|
if hasPath {
|
|
path, ok := config["path"].(string)
|
|
if !ok || strings.TrimSpace(path) == "" {
|
|
return ObrimRetrieverCodeFailedInvalidConfig
|
|
}
|
|
}
|
|
|
|
if hasFields {
|
|
fields, ok := obrimRetrieverNormalizeFields(config["fields"])
|
|
if !ok || len(fields) == 0 {
|
|
return ObrimRetrieverCodeFailedInvalidConfig
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// obrimRetrieverDb processes DB retrieval requests.
|
|
func obrimRetrieverDb(config map[string]any) map[string]any {
|
|
return obrimRetrieverBuildResponse(
|
|
false,
|
|
ObrimRetrieverCodeFailedNotImplemented,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// obrimRetrieverDbValidate validates DB configuration.
|
|
func obrimRetrieverDbValidate(config map[string]any) string {
|
|
return ""
|
|
}
|
|
|
|
// obrimRetrieverJsonResolvePath resolves a dot path.
|
|
func obrimRetrieverJsonResolvePath(
|
|
data any,
|
|
path string,
|
|
) (any, bool) {
|
|
current := data
|
|
|
|
for _, segment := range strings.Split(path, ".") {
|
|
object, ok := current.(map[string]any)
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
value, exists := object[segment]
|
|
if !exists {
|
|
return nil, false
|
|
}
|
|
|
|
current = value
|
|
}
|
|
|
|
return current, true
|
|
}
|
|
|
|
// obrimRetrieverNormalizeFields normalizes field inputs.
|
|
func obrimRetrieverNormalizeFields(
|
|
value any,
|
|
) ([]string, bool) {
|
|
switch fields := value.(type) {
|
|
case []string:
|
|
return fields, true
|
|
|
|
case []any:
|
|
result := make([]string, 0, len(fields))
|
|
|
|
for _, field := range fields {
|
|
text, ok := field.(string)
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
result = append(result, text)
|
|
}
|
|
|
|
return result, true
|
|
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
// obrimRetrieverError formats internal errors.
|
|
func obrimRetrieverError(message string) error {
|
|
return fmt.Errorf("%s", message)
|
|
}
|