package entities /** * The ephemeralvariablemap is used "only" for variable substitution in config * titles, shell arguments, etc, in the foorm of {{ key }}, like Jinja2. * * OliveTin itself really only ever "writes" to this map, mostly by loading * EntityFiles, and the only form of "reading" is for the variable substitution * in configs. */ import ( "strings" "sync" "github.com/OliveTin/OliveTin/internal/installationinfo" ) type entityInstancesByKey map[string]*Entity type entitiesByClass map[string]entityInstancesByKey type variableBase struct { OliveTin installationInfo Entities entitiesByClass CurrentEntity interface{} Arguments map[string]string } type installationInfo struct { Build *installationinfo.BuildInfo Runtime *installationinfo.RuntimeInfo } var ( contents *variableBase rwmutex = sync.RWMutex{} ) func init() { rwmutex.Lock() contents = &variableBase{ OliveTin: installationInfo{ Build: installationinfo.Build, Runtime: installationinfo.Runtime, }, Entities: make(entitiesByClass, 0), } rwmutex.Unlock() } func GetAll() *variableBase { rwmutex.RLock() defer rwmutex.RUnlock() return contents } func GetEntities() entitiesByClass { rwmutex.RLock() copiedEntities := make(entitiesByClass, len(contents.Entities)) for entityName, entityInstances := range contents.Entities { copiedInstances := make(entityInstancesByKey, len(entityInstances)) for key, entity := range entityInstances { copiedInstances[key] = entity } copiedEntities[entityName] = copiedInstances } rwmutex.RUnlock() return copiedEntities } func GetEntityInstances(entityName string) entityInstancesByKey { rwmutex.RLock() defer rwmutex.RUnlock() if entities, ok := contents.Entities[entityName]; ok { copiedInstances := make(entityInstancesByKey, len(entities)) for key, entity := range entities { copiedInstances[key] = entity } return copiedInstances } return make(entityInstancesByKey, 0) } func AddEntity(entityName string, entityKey string, data any) { rwmutex.Lock() if _, ok := contents.Entities[entityName]; !ok { contents.Entities[entityName] = make(entityInstancesByKey, 0) } contents.Entities[entityName][entityKey] = &Entity{ Data: data, UniqueKey: entityKey, Title: findEntityTitle(data), } rwmutex.Unlock() } //gocyclo:ignore func findEntityTitle(data any) string { if mapData, ok := data.(map[string]any); ok { keys := make(map[string]string) for k := range mapData { lookupKey := strings.ToLower(k) keys[lookupKey] = k } for _, key := range []string{"title", "name", "id"} { if lookupKey, exists := keys[strings.ToLower(key)]; exists { if value, ok := mapData[lookupKey]; ok { if valueStr, ok := value.(string); ok { return valueStr } } } } } return "Untitled Entity" }