aviortui/essential/visible/service/helper/retriever/retriever.go
2026-08-28 12:58:14 +08:00

400 lines
9.2 KiB
Go

/*
|--------------------------------------------------------------------------
| 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
}