Added project schema feature
This commit is contained in:
@@ -114,11 +114,32 @@
|
||||
"BaseLib2GAM": { "fields": [] },
|
||||
"ConversionGAM": { "fields": [] },
|
||||
"DoubleHandshakeGAM": { "fields": [] },
|
||||
"FilterGAM": { "fields": [] },
|
||||
"HistogramGAM": { "fields": [] },
|
||||
"FilterGAM": {
|
||||
"fields": [
|
||||
{"name": "Num", "type": "array", "mandatory": true},
|
||||
{"name": "Den", "type": "array", "mandatory": true},
|
||||
{"name": "ResetInEachState", "type": "any", "mandatory": false},
|
||||
{"name": "InputSignals", "type": "node", "mandatory": false},
|
||||
{"name": "OutputSignals", "type": "node", "mandatory": false}
|
||||
]
|
||||
},
|
||||
"HistogramGAM": {
|
||||
"fields": [
|
||||
{"name": "BeginCycleNumber", "type": "int", "mandatory": false},
|
||||
{"name": "StateChangeResetName", "type": "string", "mandatory": false},
|
||||
{"name": "InputSignals", "type": "node", "mandatory": false},
|
||||
{"name": "OutputSignals", "type": "node", "mandatory": false}
|
||||
]
|
||||
},
|
||||
"Interleaved2FlatGAM": { "fields": [] },
|
||||
"FlattenedStructIOGAM": { "fields": [] },
|
||||
"MathExpressionGAM": { "fields": [] },
|
||||
"MathExpressionGAM": {
|
||||
"fields": [
|
||||
{"name": "Expression", "type": "string", "mandatory": true},
|
||||
{"name": "InputSignals", "type": "node", "mandatory": false},
|
||||
{"name": "OutputSignals", "type": "node", "mandatory": false}
|
||||
]
|
||||
},
|
||||
"MessageGAM": { "fields": [] },
|
||||
"MuxGAM": { "fields": [] },
|
||||
"SimulinkWrapperGAM": { "fields": [] },
|
||||
@@ -128,10 +149,42 @@
|
||||
"TriggeredIOGAM": { "fields": [] },
|
||||
"WaveformGAM": { "fields": [] },
|
||||
"DAN": { "fields": [] },
|
||||
"LinuxTimer": { "fields": [] },
|
||||
"LinuxTimer": {
|
||||
"fields": [
|
||||
{"name": "ExecutionMode", "type": "string", "mandatory": false},
|
||||
{"name": "SleepNature", "type": "string", "mandatory": false},
|
||||
{"name": "SleepPercentage", "type": "any", "mandatory": false},
|
||||
{"name": "Phase", "type": "int", "mandatory": false},
|
||||
{"name": "CPUMask", "type": "int", "mandatory": false},
|
||||
{"name": "TimeProvider", "type": "node", "mandatory": false},
|
||||
{"name": "Signals", "type": "node", "mandatory": true}
|
||||
]
|
||||
},
|
||||
"LinkDataSource": { "fields": [] },
|
||||
"MDSReader": { "fields": [] },
|
||||
"MDSWriter": { "fields": [] },
|
||||
"MDSReader": {
|
||||
"fields": [
|
||||
{"name": "TreeName", "type": "string", "mandatory": true},
|
||||
{"name": "ShotNumber", "type": "int", "mandatory": true},
|
||||
{"name": "Frequency", "type": "float", "mandatory": true},
|
||||
{"name": "Signals", "type": "node", "mandatory": true}
|
||||
]
|
||||
},
|
||||
"MDSWriter": {
|
||||
"fields": [
|
||||
{"name": "NumberOfBuffers", "type": "int", "mandatory": true},
|
||||
{"name": "CPUMask", "type": "int", "mandatory": true},
|
||||
{"name": "StackSize", "type": "int", "mandatory": true},
|
||||
{"name": "TreeName", "type": "string", "mandatory": true},
|
||||
{"name": "PulseNumber", "type": "int", "mandatory": false},
|
||||
{"name": "StoreOnTrigger", "type": "int", "mandatory": true},
|
||||
{"name": "EventName", "type": "string", "mandatory": true},
|
||||
{"name": "TimeRefresh", "type": "float", "mandatory": true},
|
||||
{"name": "NumberOfPreTriggers", "type": "int", "mandatory": false},
|
||||
{"name": "NumberOfPostTriggers", "type": "int", "mandatory": false},
|
||||
{"name": "Signals", "type": "node", "mandatory": true},
|
||||
{"name": "Messages", "type": "node", "mandatory": false}
|
||||
]
|
||||
},
|
||||
"NI1588TimeStamp": { "fields": [] },
|
||||
"NI6259ADC": { "fields": [] },
|
||||
"NI6259DAC": { "fields": [] },
|
||||
@@ -153,4 +206,4 @@
|
||||
"OPCUA": { "fields": [] },
|
||||
"SysLogger": { "fields": [] }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//go:embed marte.json
|
||||
@@ -45,11 +46,89 @@ func LoadSchema(path string) (*Schema, error) {
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
// DefaultSchema returns a built-in schema with core MARTe classes
|
||||
// DefaultSchema returns the built-in embedded schema
|
||||
func DefaultSchema() *Schema {
|
||||
var s Schema
|
||||
if err := json.Unmarshal(defaultSchemaJSON, &s); err != nil {
|
||||
panic(fmt.Sprintf("failed to parse default embedded schema: %v", err))
|
||||
}
|
||||
if s.Classes == nil {
|
||||
s.Classes = make(map[string]ClassDefinition)
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
// Merge adds rules from 'other' to 's'.
|
||||
// Rules for the same class are merged (new fields added, existing fields updated).
|
||||
func (s *Schema) Merge(other *Schema) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
for className, classDef := range other.Classes {
|
||||
if existingClass, ok := s.Classes[className]; ok {
|
||||
// Merge fields
|
||||
fieldMap := make(map[string]FieldDefinition)
|
||||
for _, f := range classDef.Fields {
|
||||
fieldMap[f.Name] = f
|
||||
}
|
||||
|
||||
var mergedFields []FieldDefinition
|
||||
seen := make(map[string]bool)
|
||||
|
||||
// Keep existing fields, update if present in other
|
||||
for _, f := range existingClass.Fields {
|
||||
if newF, ok := fieldMap[f.Name]; ok {
|
||||
mergedFields = append(mergedFields, newF)
|
||||
} else {
|
||||
mergedFields = append(mergedFields, f)
|
||||
}
|
||||
seen[f.Name] = true
|
||||
}
|
||||
|
||||
// Append new fields
|
||||
for _, f := range classDef.Fields {
|
||||
if !seen[f.Name] {
|
||||
mergedFields = append(mergedFields, f)
|
||||
}
|
||||
}
|
||||
|
||||
existingClass.Fields = mergedFields
|
||||
if classDef.Ordered {
|
||||
existingClass.Ordered = true
|
||||
}
|
||||
s.Classes[className] = existingClass
|
||||
} else {
|
||||
s.Classes[className] = classDef
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func LoadFullSchema(projectRoot string) *Schema {
|
||||
s := DefaultSchema()
|
||||
|
||||
// 1. System Paths
|
||||
sysPaths := []string{
|
||||
"/usr/share/mdt/marte_schema.json",
|
||||
}
|
||||
|
||||
home, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
sysPaths = append(sysPaths, filepath.Join(home, ".local/share/mdt/marte_schema.json"))
|
||||
}
|
||||
|
||||
for _, path := range sysPaths {
|
||||
if sysSchema, err := LoadSchema(path); err == nil {
|
||||
s.Merge(sysSchema)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Project Path
|
||||
if projectRoot != "" {
|
||||
projectSchemaPath := filepath.Join(projectRoot, ".marte_schema.json")
|
||||
if projSchema, err := LoadSchema(projectSchemaPath); err == nil {
|
||||
s.Merge(projSchema)
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user