martiLQ/source/golang/client/src/martilq/marti.go

276 lines
5.8 KiB
Go

package martilq
import (
"fmt"
"os"
"path/filepath"
"encoding/json"
"io/ioutil"
"github.com/google/uuid"
"math"
"time"
"errors"
"strings"
"strconv"
"bufio"
"log"
"reflect"
"regexp"
)
type Marti struct {
Content_type string `json:"content-type"`
Title string `json:"title"`
Uid string `json:"uid"`
Description string `json:"description"`
Modified time.Time `json:"modified"`
Publisher string `json:"publisher"`
ContactPoint string `json:"contactPoint"`
AccessLevel string `json:"accessLevel"`
Rights string `json:"rights"`
Tags []string `json:"tags"`
License string `json:"license"`
State string `json:"state"`
Batch float64 `json:"batch"`
DescribedBy string `json:"describedBy"`
LandingPage string `json:"landingPage"`
Theme string `json:"theme"`
Resources []Resource `json:"resources"`
Custom []interface{} `json:"custom"`
config configuration
}
func NewMarti() Marti {
m := Marti {}
m.Content_type = "application/vnd.martilq.json"
u := uuid.New()
m.Uid = u.String()
software := GetSoftware()
m.Custom = append(m.Custom, software)
m.config = NewConfiguration()
return m
}
func Load(c configuration, pathFile string) (Marti, error) {
m := Marti {}
data, err := ioutil.ReadFile(pathFile)
if err != nil {
return m, err
}
err = json.Unmarshal(data, &m)
if err != nil {
fmt.Println("error:", err)
return m, err
}
if reflect.TypeOf(c) == reflect.TypeOf(m.config) {
m.config = c
}
return m, nil
}
func (m *Marti) LoadConfig(ConfigPath string) {
m.config.LoadConfig(ConfigPath)
m.Publisher = m.config.publisher
m.ContactPoint = m.config.contactPoint
m.AccessLevel = m.config.accessLevel
m.State = m.config.state
m.Rights = m.config.rights
if m.config.tags != "" {
m.Tags = strings.Split(m.config.tags, ",")
}
m.Theme = m.config.theme
m.License = m.config.license
if m.config.batch != "" {
if m.config.batch[0] == '@' {
_, err := os.Stat(m.config.batch[1:])
if os.IsNotExist(err) {
// See if we can locate it in Config INI directory
_, fileb := filepath.Split(m.config.batch[1:])
dirc, _ := filepath.Split(ConfigPath)
_, err := os.Stat(dirc + fileb)
if err == nil {
m.config.batch = "@" + dirc + fileb
}
}
_, err = os.Stat(m.config.batch[1:])
if os.IsNotExist(err) {
WriteLog(fmt.Sprintf("Batch file '%v' does not exist" , m.config.batch))
} else {
readFile, err := os.Open(m.config.batch[1:])
if err != nil {
log.Fatalf("failed to open file: %s", err)
}
reader := bufio.NewReader(readFile)
var line string
line, _ = reader.ReadString('\n')
m.Batch, _ = strconv.ParseFloat(line, 10)
readFile.Close()
}
} else {
m.Batch, _ = strconv.ParseFloat(m.config.batch, 10)
}
}
if m.config.spatial.enabled == true {
spatial := m.config.spatial
m.Custom = append(m.Custom, spatial)
}
if m.config.temporal.enabled == true {
temporal := m.config.temporal
m.Custom = append(m.Custom, temporal)
}
}
func (m *Marti) AddResource(SourcePath string, Url string) (Resource, error) {
r, err := NewMartiLQResource(m.config, SourcePath, Url, false, true)
if err != nil {
return r, errors.New("Error in adding resource: "+SourcePath)
}
// Find if we already have the resource
// This can occur if we are reloading
matched := false
for ix := 0; ix < len(m.Resources); ix++ {
if m.Resources[ix].DocumentName == r.DocumentName && m.Resources[ix].Url == r.Url {
m.Resources[ix] = r
matched = true
break
}
}
if !matched {
m.Resources = append(m.Resources, r)
}
return r, nil
}
func (m *Marti) Save(pathFile string) bool {
if pathFile == "" {
return false
}
j, err := json.MarshalIndent(m, ""," ")
if err != nil {
fmt.Println(err)
return false
} else {
_ = ioutil.WriteFile(pathFile, j, 0644)
}
return true
}
func ProcessFilePath(ConfigPath string, SourcePath string, Filter string, Recursive bool, UrlPrefix string, DefinitionPath string) Marti {
m := NewMarti()
if DefinitionPath != "" {
_, err := os.Stat(DefinitionPath)
if err == nil {
m, err = Load(m.config, DefinitionPath)
if err != nil {
panic("Unable to load existing MartiLQ definition: " + DefinitionPath)
}
// Update the batch number, minor version
m.Batch = math.Round((m.Batch + m.config.batchInc)/m.config.batchInc)*m.config.batchInc
m.config.LoadConfig(ConfigPath)
} else {
if ConfigPath != "" {
m.LoadConfig(ConfigPath)
}
}
} else {
if ConfigPath != "" {
m.LoadConfig(ConfigPath)
}
}
fileStat, err := os.Stat(SourcePath)
fileAbs, err :=filepath.Abs(SourcePath)
if err != nil {
panic("Source path does not exist or is inaccessible: " + SourcePath)
} else {
if UrlPrefix == "" {
UrlPrefix = m.config.urlPrefix
}
if UrlPrefix == "" {
UrlPrefix = "file://"
}
if fileStat.IsDir() {
diffCheck := fileAbs+string(os.PathSeparator)
filepath.Walk(fileAbs, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Fatalf(err.Error())
return nil
}
if info.IsDir() == false {
diff := strings.Replace(path, diffCheck, "", -1)
if Recursive || diff == info.Name() {
found := true
if Filter != "" {
found, err = regexp.MatchString(Filter, info.Name())
if err != nil {
log.Fatal(err)
}
}
if found {
url := UrlPrefix+strings.Replace(diff, "\\", "/", -1)
if UrlPrefix[0:6] == "file://" || UrlPrefix[0:1] == "\\\\" {
url = UrlPrefix+diff
}
m.AddResource(path, url)
}
} else {
return filepath.SkipDir
}
}
return nil
})
} else {
url := UrlPrefix+fileStat.Name()
m.AddResource(fileAbs, url)
}
}
return m
}
func ReconcileFilePath(ConfigPath string, SourcePath string, Recursive bool, DefinitionPath string, OutputPath string) Marti {
m := NewMarti()
return m
}