109 lines
2.8 KiB
Go
109 lines
2.8 KiB
Go
package assets
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
func DocumentReferences(raw string, resourceIDs map[string]struct{}) bool {
|
|
return len(DocumentReferencedIDs(raw, resourceIDs)) > 0
|
|
}
|
|
|
|
func DocumentReferencedIDs(raw string, resourceIDs map[string]struct{}) map[string]struct{} {
|
|
matched := map[string]struct{}{}
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" || len(resourceIDs) == 0 {
|
|
return matched
|
|
}
|
|
found := map[string]struct{}{}
|
|
var value any
|
|
if err := json.Unmarshal([]byte(raw), &value); err == nil {
|
|
if scalar, ok := value.(string); ok {
|
|
if resourceID := ResourceID(scalar); resourceID != "" {
|
|
found[resourceID] = struct{}{}
|
|
}
|
|
} else {
|
|
walkReferenceDocument(value, "", found)
|
|
}
|
|
} else if resourceID := ResourceID(raw); resourceID != "" {
|
|
found[resourceID] = struct{}{}
|
|
}
|
|
for resourceID := range found {
|
|
if _, exists := resourceIDs[resourceID]; exists {
|
|
matched[resourceID] = struct{}{}
|
|
}
|
|
}
|
|
return matched
|
|
}
|
|
|
|
func CollectOwnedDocumentReferences(raw string, resourceIDs map[string]struct{}) error {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
var value any
|
|
if err := json.Unmarshal([]byte(raw), &value); err != nil {
|
|
return err
|
|
}
|
|
if scalar, ok := value.(string); ok {
|
|
if resourceID := ResourceID(scalar); resourceID != "" {
|
|
resourceIDs[resourceID] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
walkReferenceDocument(value, "", resourceIDs)
|
|
return nil
|
|
}
|
|
|
|
func SortedIDs(values map[string]struct{}) []string {
|
|
result := make([]string, 0, len(values))
|
|
for value := range values {
|
|
result = append(result, value)
|
|
}
|
|
sort.Strings(result)
|
|
return result
|
|
}
|
|
|
|
func walkReferenceDocument(value any, parentKey string, resourceIDs map[string]struct{}) {
|
|
switch item := value.(type) {
|
|
case map[string]any:
|
|
for key, child := range item {
|
|
walkReferenceDocument(child, key, resourceIDs)
|
|
}
|
|
case []any:
|
|
for _, child := range item {
|
|
walkReferenceDocument(child, parentKey, resourceIDs)
|
|
}
|
|
case string:
|
|
if isResourceLocatorField(parentKey) {
|
|
if resourceID := ResourceID(item); resourceID != "" {
|
|
resourceIDs[resourceID] = struct{}{}
|
|
}
|
|
}
|
|
if isBareResourceIDField(parentKey) {
|
|
if resourceID := ValidID(item); resourceID != "" {
|
|
resourceIDs[resourceID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func isBareResourceIDField(field string) bool {
|
|
switch field {
|
|
case "resourceId", "resourceIds", "sampleResourceId", "referenceResourceId", "referenceResourceIds":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func isResourceLocatorField(field string) bool {
|
|
switch field {
|
|
case "storageKey", "content", "previewContent", "drawingPreviewStorageKey", "drawingPreviewUrl", "url", "dataUrl", "coverUrl", "imageUrl", "videoUrl", "audioUrl", "referenceUrl", "referenceUrls", "artifactRef", "providerArtifactRef":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|