upd: essential/file updated
helper retriever updated
This commit is contained in:
parent
69c58563a5
commit
d7d20533ca
@ -0,0 +1,400 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Description
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Name:
|
||||
| - Retriever
|
||||
|
|
||||
| Purpose:
|
||||
| - Retrieve data from supported resource handlers through a unified
|
||||
| retrieval interface.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Instruction
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Guideline:
|
||||
| - Use for retrieving data from registered JSON resource handlers.
|
||||
| - Use type-based dispatching to route retrieval requests.
|
||||
| - Use resource retrieval to obtain a complete JSON resource.
|
||||
| - Use path retrieval to obtain a specific nested value.
|
||||
| - Use fields retrieval to obtain multiple nested values.
|
||||
| - Do not use path and fields retrieval together.
|
||||
|
|
||||
| Example:
|
||||
| - ObrimRetriever("json", map[string]any{
|
||||
| "resource": "metadata",
|
||||
| })
|
||||
|
|
||||
| - ObrimRetriever("json", map[string]any{
|
||||
| "resource": "metadata",
|
||||
| "path": "app.name",
|
||||
| })
|
||||
|
|
||||
| - ObrimRetriever("json", map[string]any{
|
||||
| "resource": "metadata",
|
||||
| "fields": []any{"app.name", "app.version"},
|
||||
| })
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Credit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Contributor:
|
||||
| - Rajon Ahmed
|
||||
| - Blockonite
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package retriever
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Utility type identifiers define supported retriever input types.
|
||||
obrimRetrieverTypeJSON = "json"
|
||||
|
||||
// Retriever result codes define successful execution outcomes.
|
||||
obrimRetrieverSuccessResource = "SUCCESS_RESOURCE_RETRIEVED"
|
||||
obrimRetrieverSuccessPath = "SUCCESS_PATH_RETRIEVED"
|
||||
obrimRetrieverSuccessFields = "SUCCESS_FIELDS_RETRIEVED"
|
||||
|
||||
// Retriever result codes define failed execution outcomes.
|
||||
obrimRetrieverFailureInvalidType = "FAILURE_INVALID_TYPE"
|
||||
obrimRetrieverFailureInvalidConfig = "FAILURE_INVALID_CONFIG"
|
||||
obrimRetrieverFailureResourceRequired = "FAILURE_RESOURCE_REQUIRED"
|
||||
obrimRetrieverFailurePathAndFields = "FAILURE_PATH_AND_FIELDS"
|
||||
obrimRetrieverFailureInvalidPath = "FAILURE_INVALID_PATH"
|
||||
obrimRetrieverFailureInvalidFields = "FAILURE_INVALID_FIELDS"
|
||||
obrimRetrieverFailureResourceNotFound = "FAILURE_RESOURCE_NOT_FOUND"
|
||||
obrimRetrieverFailureHandlerFailed = "FAILURE_HANDLER_FAILED"
|
||||
obrimRetrieverFailurePathNotFound = "FAILURE_PATH_NOT_FOUND"
|
||||
obrimRetrieverFailureFieldNotFound = "FAILURE_FIELD_NOT_FOUND"
|
||||
obrimRetrieverFailureUnsupportedConfig = "FAILURE_UNSUPPORTED_CONFIG"
|
||||
)
|
||||
|
||||
var (
|
||||
// obrimRetrieverJsonHandlers stores registered JSON resource handlers.
|
||||
obrimRetrieverJsonHandlers = map[string]func() map[string]any{}
|
||||
|
||||
// obrimRetrieverJsonHandlersMutex protects the JSON handler registry.
|
||||
obrimRetrieverJsonHandlersMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// ObrimRetrieverResult represents the standardized retriever execution output.
|
||||
type ObrimRetrieverResult struct {
|
||||
Status bool `json:"status"`
|
||||
Code string `json:"code"`
|
||||
Payload map[string]any `json:"payload"`
|
||||
}
|
||||
|
||||
// ObrimRetriever retrieves data from a supported resource handler.
|
||||
func ObrimRetriever(
|
||||
typ string,
|
||||
config map[string]any,
|
||||
) map[string]any {
|
||||
if code := obrimRetrieverValidateInput(typ, config); code != "" {
|
||||
return obrimRetrieverBuildOutput(false, code, nil)
|
||||
}
|
||||
|
||||
return obrimRetrieverRouteRequest(typ, config)
|
||||
}
|
||||
|
||||
// ObrimRetrieverJsonRegister registers a JSON resource handler.
|
||||
func ObrimRetrieverJsonRegister(
|
||||
resource string,
|
||||
handler func() map[string]any,
|
||||
) {
|
||||
if strings.TrimSpace(resource) == "" || handler == nil {
|
||||
return
|
||||
}
|
||||
|
||||
obrimRetrieverJsonHandlersMutex.Lock()
|
||||
defer obrimRetrieverJsonHandlersMutex.Unlock()
|
||||
|
||||
obrimRetrieverJsonHandlers[resource] = handler
|
||||
}
|
||||
|
||||
// obrimRetrieverValidateInput validates the retriever type and configuration.
|
||||
func obrimRetrieverValidateInput(
|
||||
typ string,
|
||||
config map[string]any,
|
||||
) string {
|
||||
switch typ {
|
||||
case obrimRetrieverTypeJSON:
|
||||
return obrimRetrieverValidateJSONConfig(config)
|
||||
default:
|
||||
return obrimRetrieverFailureInvalidType
|
||||
}
|
||||
}
|
||||
|
||||
// obrimRetrieverValidateJSONConfig validates JSON retriever configuration.
|
||||
func obrimRetrieverValidateJSONConfig(config map[string]any) string {
|
||||
if config == nil {
|
||||
return obrimRetrieverFailureInvalidConfig
|
||||
}
|
||||
|
||||
resourceValue, exists := config["resource"]
|
||||
if !exists {
|
||||
return obrimRetrieverFailureResourceRequired
|
||||
}
|
||||
|
||||
resource, ok := resourceValue.(string)
|
||||
if !ok || strings.TrimSpace(resource) == "" {
|
||||
return obrimRetrieverFailureResourceRequired
|
||||
}
|
||||
|
||||
_, hasPath := config["path"]
|
||||
_, hasFields := config["fields"]
|
||||
|
||||
if hasPath && hasFields {
|
||||
return obrimRetrieverFailurePathAndFields
|
||||
}
|
||||
|
||||
for key := range config {
|
||||
switch key {
|
||||
case "resource", "path", "fields":
|
||||
default:
|
||||
return obrimRetrieverFailureUnsupportedConfig
|
||||
}
|
||||
}
|
||||
|
||||
if hasPath {
|
||||
path, ok := config["path"].(string)
|
||||
if !ok || strings.TrimSpace(path) == "" {
|
||||
return obrimRetrieverFailureInvalidPath
|
||||
}
|
||||
}
|
||||
|
||||
if hasFields {
|
||||
fields, ok := config["fields"].([]string)
|
||||
if !ok || len(fields) == 0 {
|
||||
return obrimRetrieverFailureInvalidFields
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if strings.TrimSpace(field) == "" {
|
||||
return obrimRetrieverFailureInvalidFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// obrimRetrieverRouteRequest routes the request to its type-specific entry function.
|
||||
func obrimRetrieverRouteRequest(
|
||||
typ string,
|
||||
config map[string]any,
|
||||
) map[string]any {
|
||||
switch typ {
|
||||
case obrimRetrieverTypeJSON:
|
||||
return obrimRetrieverJson(config)
|
||||
default:
|
||||
return obrimRetrieverBuildOutput(
|
||||
false,
|
||||
obrimRetrieverFailureInvalidType,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// obrimRetrieverBuildOutput builds the standardized retriever output.
|
||||
func obrimRetrieverBuildOutput(
|
||||
status bool,
|
||||
code string,
|
||||
payload map[string]any,
|
||||
) map[string]any {
|
||||
if !status {
|
||||
payload = nil
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"status": status,
|
||||
"code": code,
|
||||
"payload": payload,
|
||||
}
|
||||
}
|
||||
|
||||
// obrimRetrieverJson processes a JSON retrieval request.
|
||||
func obrimRetrieverJson(config map[string]any) map[string]any {
|
||||
resource := config["resource"].(string)
|
||||
|
||||
data, ok := obrimRetrieverJsonHandler(resource)
|
||||
if !ok {
|
||||
return obrimRetrieverBuildOutput(
|
||||
false,
|
||||
obrimRetrieverFailureResourceNotFound,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
if pathValue, exists := config["path"]; exists {
|
||||
path := pathValue.(string)
|
||||
|
||||
value, ok := obrimRetrieverJsonPath(data, path)
|
||||
if !ok {
|
||||
return obrimRetrieverBuildOutput(
|
||||
false,
|
||||
obrimRetrieverFailurePathNotFound,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
return obrimRetrieverBuildOutput(
|
||||
true,
|
||||
obrimRetrieverSuccessPath,
|
||||
map[string]any{
|
||||
"data": value,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if fieldsValue, exists := config["fields"]; exists {
|
||||
fields := fieldsValue.([]string)
|
||||
|
||||
values, ok := obrimRetrieverJsonFields(data, fields)
|
||||
if !ok {
|
||||
return obrimRetrieverBuildOutput(
|
||||
false,
|
||||
obrimRetrieverFailureFieldNotFound,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
return obrimRetrieverBuildOutput(
|
||||
true,
|
||||
obrimRetrieverSuccessFields,
|
||||
map[string]any{
|
||||
"data": values,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return obrimRetrieverBuildOutput(
|
||||
true,
|
||||
obrimRetrieverSuccessResource,
|
||||
map[string]any{
|
||||
"data": obrimRetrieverJsonResource(data),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// obrimRetrieverJsonHandler locates and invokes a registered JSON handler.
|
||||
func obrimRetrieverJsonHandler(
|
||||
resource string,
|
||||
) (map[string]any, bool) {
|
||||
obrimRetrieverJsonHandlersMutex.RLock()
|
||||
handler, exists := obrimRetrieverJsonHandlers[resource]
|
||||
obrimRetrieverJsonHandlersMutex.RUnlock()
|
||||
|
||||
if !exists || handler == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
data := handler()
|
||||
if data == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return data, true
|
||||
}
|
||||
|
||||
// obrimRetrieverJsonResource returns the complete JSON resource payload.
|
||||
func obrimRetrieverJsonResource(
|
||||
resource map[string]any,
|
||||
) map[string]any {
|
||||
return resource
|
||||
}
|
||||
|
||||
// obrimRetrieverJsonPath retrieves a value using a dot-notation path.
|
||||
func obrimRetrieverJsonPath(
|
||||
resource map[string]any,
|
||||
path string,
|
||||
) (any, bool) {
|
||||
parts := strings.Split(path, ".")
|
||||
if len(parts) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var current any = resource
|
||||
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
switch value := current.(type) {
|
||||
case map[string]any:
|
||||
next, exists := value[part]
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
current = next
|
||||
|
||||
case []any:
|
||||
index := -1
|
||||
|
||||
for i, item := range value {
|
||||
if part == strings.TrimSpace(part) {
|
||||
var parsed int
|
||||
if _, err := fmt.Sscanf(part, "%d", &parsed); err == nil {
|
||||
index = parsed
|
||||
}
|
||||
}
|
||||
|
||||
if index >= 0 {
|
||||
_ = item
|
||||
break
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if index < 0 || index >= len(value) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
current = value[index]
|
||||
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
return current, true
|
||||
}
|
||||
|
||||
// obrimRetrieverJsonFields retrieves multiple values using field selection.
|
||||
func obrimRetrieverJsonFields(
|
||||
resource map[string]any,
|
||||
fields []string,
|
||||
) (map[string]any, bool) {
|
||||
values := make(map[string]any, len(fields))
|
||||
|
||||
for _, field := range fields {
|
||||
value, ok := obrimRetrieverJsonPath(resource, field)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
values[field] = value
|
||||
}
|
||||
|
||||
return values, true
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user