| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- package entities
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "strings"
- config "github.com/OliveTin/OliveTin/internal/config"
- "github.com/OliveTin/OliveTin/internal/filehelper"
- log "github.com/sirupsen/logrus"
- "gopkg.in/yaml.v3"
- )
- var (
- EntityChangedSender chan bool
- listeners []func()
- )
- type Entity struct {
- Data any
- UniqueKey string
- Title string
- }
- func AddListener(l func()) {
- listeners = append(listeners, l)
- }
- func SetupEntityFileWatchers(cfg *config.Config) {
- baseDir := resolveEntitiesBaseDir(cfg.GetDir())
- for i := range cfg.Entities { // #337 - iterate by key, not by value
- ef := cfg.Entities[i]
- watchAndLoadEntity(baseDir, ef)
- }
- }
- //gocyclo:ignore
- func resolveEntitiesBaseDir(configDir string) string {
- absConfigDir, err := filepath.Abs(configDir)
- if err != nil {
- log.Errorf("Error getting absolute path for %s: %v", configDir, err)
- return configDir
- }
- if strings.Contains(absConfigDir, "integration-tests") {
- return configDir
- }
- devVar := filepath.Join(configDir, "var")
- if _, err := os.Stat(devVar); err == nil {
- return devVar
- }
- return absConfigDir
- }
- func watchAndLoadEntity(baseDir string, ef *config.EntityFile) {
- p := ef.File
- if !filepath.IsAbs(p) {
- p = filepath.Join(baseDir, p)
- log.WithFields(log.Fields{"entityFile": p}).Debugf("Adding config dir to entity file path")
- }
- go filehelper.WatchFileWrite(p, func(filename string) { loadEntityFile(p, ef.Name) })
- loadEntityFile(p, ef.Name)
- }
- func loadEntityFile(filename string, entityname string) {
- if strings.HasSuffix(filename, ".json") {
- loadEntityFileJson(filename, entityname)
- } else {
- loadEntityFileYaml(filename, entityname)
- }
- }
- func loadEntityFileJson(filename string, entityname string) {
- log.WithFields(log.Fields{
- "file": filename,
- "name": entityname,
- }).Infof("Loading entity file with JSON format")
- jfile, err := os.ReadFile(filename)
- if err != nil {
- log.Errorf("ReadIn: %v", err)
- return
- }
- data := make([]map[string]any, 0)
- decoder := json.NewDecoder(bytes.NewReader(jfile))
- for decoder.More() {
- d := make(map[string]any)
- err := decoder.Decode(&d)
- if err != nil {
- log.Errorf("%v", err)
- return
- }
- data = append(data, d)
- }
- updateSvFromFile(entityname, data)
- }
- func loadEntityFileYaml(filename string, entityname string) {
- log.WithFields(log.Fields{
- "file": filename,
- "name": entityname,
- }).Infof("Loading entity file with YAML format")
- yfile, err := os.ReadFile(filename)
- if err != nil {
- log.Errorf("ReadIn: %v", err)
- return
- }
- var data []map[string]any
- err = yaml.Unmarshal(yfile, &data)
- if err != nil {
- log.Errorf("Unmarshal: %v", err)
- return
- }
- updateSvFromFile(entityname, data)
- }
- func updateSvFromFile(entityname string, data []map[string]any) {
- ClearEntitiesOfType(entityname)
- for i, mapp := range data {
- AddEntity(entityname, fmt.Sprintf("%d", i), mapp)
- }
- for _, l := range listeners {
- l()
- }
- }
- /*
- //gocyclo:ignore
- func serializeValueToSv(prefix string, value any) {
- if m, ok := value.(map[string]any); ok { // if value is a map we need to flatten it
- serializeMapToSv(prefix, m)
- } else if s, ok := value.([]any); ok { // if value is a slice we need to flatten it
- serializeSliceToSv(prefix, s)
- } else if f, ok := value.(float64); ok {
- if canConvertToInt64(f) {
- s := int64(f)
- sv.Set(prefix, fmt.Sprintf("%d", s))
- } else {
- sv.Set(prefix, fmt.Sprintf("%f", f))
- }
- } else {
- sv.Set(prefix, fmt.Sprintf("%v", value))
- }
- }
- func canConvertToInt64(f float64) bool {
- return f >= math.MinInt64 && f <= math.MaxInt64 && f == math.Trunc(f)
- }
- func serializeMapToSv(prefix string, m map[string]any) {
- for k, v := range m {
- serializeValueToSv(prefix+"."+k, v)
- }
- }
- func serializeSliceToSv(prefix string, s []any) {
- sv.Set(prefix+".count", fmt.Sprintf("%v", len(s)))
- for i, v := range s {
- serializeValueToSv(prefix+"."+fmt.Sprintf("%v", i), v)
- }
- }
- */
|