2018-12-09 07:05:02 +09:00
|
|
|
package convert
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/cjslep/activity/tools/exp/props"
|
|
|
|
"github.com/cjslep/activity/tools/exp/rdf"
|
2018-12-09 19:40:59 +09:00
|
|
|
"github.com/dave/jennifer/jen"
|
2018-12-09 07:05:02 +09:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2018-12-10 05:23:32 +09:00
|
|
|
type File struct {
|
|
|
|
F *jen.File
|
|
|
|
FileName string
|
|
|
|
Directory string
|
|
|
|
}
|
|
|
|
|
2018-12-09 07:05:02 +09:00
|
|
|
type vocabulary struct {
|
|
|
|
Kinds map[string]*props.Kind
|
|
|
|
FProps map[string]*props.FunctionalPropertyGenerator
|
|
|
|
NFProps map[string]*props.NonFunctionalPropertyGenerator
|
2018-12-18 07:11:55 +09:00
|
|
|
Types map[string]*props.TypeGenerator
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
func newVocabulary() vocabulary {
|
|
|
|
return vocabulary{
|
|
|
|
Kinds: make(map[string]*props.Kind, 0),
|
|
|
|
FProps: make(map[string]*props.FunctionalPropertyGenerator, 0),
|
|
|
|
NFProps: make(map[string]*props.NonFunctionalPropertyGenerator, 0),
|
2018-12-18 07:11:55 +09:00
|
|
|
Types: make(map[string]*props.TypeGenerator, 0),
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type PropertyPackagePolicy int
|
|
|
|
|
|
|
|
const (
|
2018-12-09 19:40:59 +09:00
|
|
|
PropertyFlatUnderRoot PropertyPackagePolicy = iota
|
|
|
|
PropertyIndividualUnderRoot
|
|
|
|
PropertyFlatUnderVocabularyRoot
|
|
|
|
)
|
|
|
|
|
|
|
|
type TypePackagePolicy int
|
|
|
|
|
|
|
|
const (
|
|
|
|
TypeFlatUnderRoot TypePackagePolicy = iota
|
|
|
|
TypeIndividualUnderRoot
|
|
|
|
TypeFlatUnderVocabularyRoot
|
2018-12-09 07:05:02 +09:00
|
|
|
)
|
|
|
|
|
|
|
|
type Converter struct {
|
|
|
|
Registry *rdf.RDFRegistry
|
|
|
|
VocabularyRoot string
|
|
|
|
PropertyPackagePolicy PropertyPackagePolicy
|
|
|
|
PropertyPackageRoot string
|
2018-12-09 19:40:59 +09:00
|
|
|
TypePackagePolicy TypePackagePolicy
|
2018-12-10 05:23:32 +09:00
|
|
|
TypePackageRoot string
|
2018-12-09 19:40:59 +09:00
|
|
|
}
|
|
|
|
|
2018-12-10 05:23:32 +09:00
|
|
|
func (c Converter) Convert(p *rdf.ParsedVocabulary) (f []*File, e error) {
|
|
|
|
var v vocabulary
|
|
|
|
v, e = c.convertVocabulary(p)
|
2018-12-09 19:40:59 +09:00
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
2018-12-10 05:23:32 +09:00
|
|
|
f, e = c.convertToFiles(v)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
|
|
|
|
for _, _ = range v.Kinds {
|
2018-12-18 07:11:55 +09:00
|
|
|
// TODO: Implement
|
2018-12-10 05:23:32 +09:00
|
|
|
}
|
|
|
|
for _, i := range v.FProps {
|
|
|
|
var pkg string
|
|
|
|
pkg, e = c.propertyPackageFile(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var dir string
|
|
|
|
dir, e = c.propertyPackageDirectory(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
file := jen.NewFilePath(pkg)
|
|
|
|
file.Add(i.Definition().Definition())
|
|
|
|
f = append(f, &File{
|
|
|
|
F: file,
|
|
|
|
FileName: fmt.Sprintf("gen_%s.go", i.PropertyName()),
|
|
|
|
Directory: dir,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
for _, i := range v.NFProps {
|
|
|
|
var pkg string
|
|
|
|
pkg, e = c.propertyPackageFile(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var dir string
|
|
|
|
dir, e = c.propertyPackageDirectory(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
file := jen.NewFilePath(pkg)
|
|
|
|
s, t := i.Definitions()
|
|
|
|
file.Add(s.Definition()).Add(t.Definition())
|
|
|
|
f = append(f, &File{
|
|
|
|
F: file,
|
|
|
|
FileName: fmt.Sprintf("gen_%s.go", i.PropertyName()),
|
|
|
|
Directory: dir,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
for _, i := range v.Types {
|
|
|
|
var pkg string
|
|
|
|
pkg, e = c.typePackageFile(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var dir string
|
|
|
|
dir, e = c.typePackageDirectory(i)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
file := jen.NewFilePath(pkg)
|
|
|
|
file.Add(i.Definition().Definition())
|
|
|
|
f = append(f, &File{
|
|
|
|
F: file,
|
|
|
|
FileName: fmt.Sprintf("gen_%s.go", i.TypeName()),
|
|
|
|
Directory: dir,
|
|
|
|
})
|
|
|
|
}
|
2018-12-09 19:40:59 +09:00
|
|
|
return
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
|
2018-12-18 07:11:55 +09:00
|
|
|
// convertVocabulary works in a two-pass system: first converting all known
|
|
|
|
// properties, and then the types.
|
|
|
|
//
|
|
|
|
// Due to the fact that properties rely on the Kind abstraction, and both
|
|
|
|
// properties and types can be Kinds, this introduces tight coupling between
|
|
|
|
// the two so that callbacks can fill in missing links in data that isn't known
|
|
|
|
// beforehand (ex: how to serialize, deserialize, and compare types).
|
|
|
|
//
|
|
|
|
// This feels very hacky and could be decoupled using standard design patterns,
|
|
|
|
// but since there is no need, it isn't addressed now.
|
2018-12-09 19:40:59 +09:00
|
|
|
func (c Converter) convertVocabulary(p *rdf.ParsedVocabulary) (v vocabulary, e error) {
|
2018-12-09 07:05:02 +09:00
|
|
|
v = newVocabulary()
|
|
|
|
for k, val := range p.Vocab.Values {
|
|
|
|
v.Kinds[k] = c.convertValue(val)
|
|
|
|
}
|
|
|
|
for k, prop := range p.Vocab.Properties {
|
|
|
|
if prop.Functional {
|
|
|
|
v.FProps[k], e = c.convertFunctionalProperty(prop, v.Kinds, p.Vocab, p.References)
|
|
|
|
} else {
|
|
|
|
v.NFProps[k], e = c.convertNonFunctionalProperty(prop, v.Kinds, p.Vocab, p.References)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2018-12-09 19:40:59 +09:00
|
|
|
// Instead of building a dependency tree, naively keep iterating through
|
|
|
|
// 'allTypes' until it is empty (good) or we get stuck (return error).
|
|
|
|
allTypes := make([]rdf.VocabularyType, 0, len(p.Vocab.Types))
|
|
|
|
for _, t := range p.Vocab.Types {
|
|
|
|
allTypes = append(allTypes, t)
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
if len(allTypes) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
stuck := true
|
2018-12-10 05:23:32 +09:00
|
|
|
for i, t := range allTypes {
|
|
|
|
if allExtendsAreIn(t, v.Types) {
|
2018-12-18 07:11:55 +09:00
|
|
|
var tg *props.TypeGenerator
|
2018-12-10 05:23:32 +09:00
|
|
|
tg, e = c.convertType(t, p.Vocab, v.FProps, v.NFProps, v.Types)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
v.Types[t.Name] = tg
|
|
|
|
stuck = false
|
|
|
|
// Delete the one we just did.
|
|
|
|
allTypes[i] = allTypes[len(allTypes)-1]
|
|
|
|
allTypes = allTypes[:len(allTypes)-1]
|
|
|
|
break
|
2018-12-09 19:40:59 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if stuck {
|
2018-12-18 07:11:55 +09:00
|
|
|
e = fmt.Errorf("converting props got stuck in dependency cycle")
|
2018-12-09 19:40:59 +09:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertType(t rdf.VocabularyType,
|
|
|
|
v rdf.Vocabulary,
|
|
|
|
existingFProps map[string]*props.FunctionalPropertyGenerator,
|
|
|
|
existingNFProps map[string]*props.NonFunctionalPropertyGenerator,
|
2018-12-18 07:11:55 +09:00
|
|
|
existingTypes map[string]*props.TypeGenerator) (tg *props.TypeGenerator, e error) {
|
|
|
|
// Determine the props package name
|
2018-12-09 19:40:59 +09:00
|
|
|
var pkg string
|
|
|
|
pkg, e = c.typePackageName(t)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Determine the properties for this type
|
2018-12-18 07:11:55 +09:00
|
|
|
var p []props.Property
|
|
|
|
for _, prop := range t.Properties {
|
|
|
|
if len(prop.Vocab) != 0 {
|
|
|
|
e = fmt.Errorf("unhandled use case: property domain outside its vocabulary")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
var property props.Property
|
|
|
|
var ok bool
|
|
|
|
property, ok = existingFProps[prop.Name]
|
|
|
|
if !ok {
|
|
|
|
property, ok = existingNFProps[prop.Name]
|
|
|
|
if !ok {
|
|
|
|
e = fmt.Errorf("cannot find property with name: %s", prop.Name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p = append(p, property)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Determine WithoutProperties for this type
|
|
|
|
var wop []props.Property
|
|
|
|
for _, prop := range t.WithoutProperties {
|
|
|
|
if len(prop.Vocab) != 0 {
|
|
|
|
e = fmt.Errorf("unhandled use case: withoutproperty domain outside its vocabulary")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
var property props.Property
|
|
|
|
var ok bool
|
|
|
|
property, ok = existingFProps[prop.Name]
|
|
|
|
if !ok {
|
|
|
|
property, ok = existingNFProps[prop.Name]
|
|
|
|
if !ok {
|
|
|
|
e = fmt.Errorf("cannot find property with name: %s", prop.Name)
|
|
|
|
return
|
2018-12-09 19:40:59 +09:00
|
|
|
}
|
|
|
|
}
|
2018-12-18 07:11:55 +09:00
|
|
|
wop = append(wop, property)
|
2018-12-09 19:40:59 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Determine what this type extends
|
2018-12-18 07:11:55 +09:00
|
|
|
var ext []*props.TypeGenerator
|
2018-12-09 19:40:59 +09:00
|
|
|
for _, ex := range t.Extends {
|
|
|
|
if len(ex.Vocab) != 0 {
|
2018-12-18 07:11:55 +09:00
|
|
|
// TODO: This should be fixed to handle references
|
2018-12-09 19:40:59 +09:00
|
|
|
e = fmt.Errorf("unhandled use case: type extends another type outside its vocabulary")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
ext = append(ext, existingTypes[ex.Name])
|
|
|
|
}
|
|
|
|
}
|
2018-12-18 07:11:55 +09:00
|
|
|
tg, e = props.NewTypeGenerator(
|
2018-12-09 19:40:59 +09:00
|
|
|
pkg,
|
2018-12-09 20:45:08 +09:00
|
|
|
c.convertTypeToName(t),
|
2018-12-09 19:40:59 +09:00
|
|
|
t.Notes,
|
|
|
|
p,
|
2018-12-18 07:11:55 +09:00
|
|
|
wop,
|
2018-12-09 19:40:59 +09:00
|
|
|
ext,
|
|
|
|
nil)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
2018-12-19 17:44:57 +09:00
|
|
|
// Apply disjoint if both sides are available because the TypeGenerator
|
|
|
|
// does not know the entire vocabulary, so cannot do this lookup and
|
|
|
|
// create this connection for us.
|
|
|
|
//
|
|
|
|
// TODO: Pass in the disjoint and have the TypeGenerator complete the
|
|
|
|
// doubly-linked connection for us.
|
2018-12-09 19:40:59 +09:00
|
|
|
for _, disj := range t.DisjointWith {
|
|
|
|
if len(disj.Vocab) != 0 {
|
2018-12-18 07:11:55 +09:00
|
|
|
// TODO: This should be fixed to handle references
|
2018-12-09 19:40:59 +09:00
|
|
|
e = fmt.Errorf("unhandled use case: type is disjoint with another type outside its vocabulary")
|
|
|
|
return
|
|
|
|
} else if disjointType, ok := existingTypes[disj.Name]; ok {
|
|
|
|
disjointType.AddDisjoint(tg)
|
|
|
|
tg.AddDisjoint(disjointType)
|
|
|
|
}
|
|
|
|
}
|
2018-12-19 17:44:57 +09:00
|
|
|
// Apply the type's KindSerializationFuncs to the property because there
|
|
|
|
// is no way for the TypeGenerator to know all properties who have a
|
|
|
|
// range of this type.
|
|
|
|
//
|
|
|
|
// TODO: Pass in these properties to the TypeGenerator constructor so it
|
|
|
|
// can build these double-links properly. Note this would also need to
|
|
|
|
// apply to referenced properties, possibly.
|
|
|
|
for _, prop := range existingFProps {
|
|
|
|
for _, kind := range prop.Kinds {
|
|
|
|
if kind.Name.LowerName == tg.TypeName() {
|
|
|
|
ser, deser, less := tg.KindSerializationFuncs()
|
|
|
|
if e = prop.SetKindFns(tg.TypeName(), ser, deser, less); e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, prop := range existingNFProps {
|
|
|
|
for _, kind := range prop.Kinds {
|
|
|
|
if kind.Name.LowerName == tg.TypeName() {
|
|
|
|
ser, deser, less := tg.KindSerializationFuncs()
|
|
|
|
if e = prop.SetKindFns(tg.TypeName(), ser, deser, less); e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-09 07:05:02 +09:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertFunctionalProperty(p rdf.VocabularyProperty,
|
|
|
|
kinds map[string]*props.Kind,
|
|
|
|
v rdf.Vocabulary,
|
|
|
|
refs map[string]*rdf.Vocabulary) (fp *props.FunctionalPropertyGenerator, e error) {
|
|
|
|
var k []props.Kind
|
|
|
|
k, e = c.propertyKinds(p, kinds, v, refs)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var pkg string
|
|
|
|
pkg, e = c.propertyPackageName(p)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fp = props.NewFunctionalPropertyGenerator(
|
|
|
|
pkg,
|
|
|
|
c.toIdentifier(p),
|
|
|
|
k,
|
|
|
|
p.NaturalLanguageMap)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty,
|
|
|
|
kinds map[string]*props.Kind,
|
|
|
|
v rdf.Vocabulary,
|
|
|
|
refs map[string]*rdf.Vocabulary) (nfp *props.NonFunctionalPropertyGenerator, e error) {
|
|
|
|
var k []props.Kind
|
|
|
|
k, e = c.propertyKinds(p, kinds, v, refs)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var pkg string
|
|
|
|
pkg, e = c.propertyPackageName(p)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
nfp = props.NewNonFunctionalPropertyGenerator(
|
|
|
|
pkg,
|
|
|
|
c.toIdentifier(p),
|
|
|
|
k,
|
|
|
|
p.NaturalLanguageMap)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertValue(v rdf.VocabularyValue) (k *props.Kind) {
|
|
|
|
k = &props.Kind{
|
|
|
|
Name: c.toIdentifier(v),
|
|
|
|
ConcreteKind: v.DefinitionType,
|
|
|
|
Nilable: c.isNilable(v.DefinitionType),
|
|
|
|
SerializeFn: v.SerializeFn,
|
|
|
|
DeserializeFn: v.DeserializeFn,
|
|
|
|
LessFn: v.LessFn,
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-09 20:45:08 +09:00
|
|
|
func (c Converter) convertTypeToKind(v rdf.VocabularyType) (k *props.Kind, e error) {
|
2018-12-09 07:05:02 +09:00
|
|
|
k = &props.Kind{
|
2018-12-18 07:11:55 +09:00
|
|
|
Name: c.toIdentifier(v),
|
|
|
|
ConcreteKind: c.convertTypeToConcreteKind(v),
|
|
|
|
Nilable: true,
|
|
|
|
// Instead of populating:
|
|
|
|
// - SerializeFn
|
|
|
|
// - DeserializeFn
|
|
|
|
// - LessFn
|
|
|
|
//
|
|
|
|
// The TypeGenerator is responsible for calling setKindFns on
|
|
|
|
// the properties, to property wire a Property's Kind back to
|
|
|
|
// the Type's implementation.
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-09 20:45:08 +09:00
|
|
|
func (c Converter) convertTypeToName(v rdf.VocabularyType) string {
|
|
|
|
return strings.Title(v.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) convertTypeToConcreteKind(v rdf.VocabularyType) string {
|
|
|
|
return "*" + c.convertTypeToName(v)
|
|
|
|
}
|
|
|
|
|
2018-12-09 07:05:02 +09:00
|
|
|
func (c Converter) propertyKinds(v rdf.VocabularyProperty,
|
|
|
|
kinds map[string]*props.Kind,
|
|
|
|
vocab rdf.Vocabulary,
|
|
|
|
refs map[string]*rdf.Vocabulary) (k []props.Kind, e error) {
|
|
|
|
for _, r := range v.Range {
|
|
|
|
if len(r.Vocab) == 0 {
|
|
|
|
if kind, ok := kinds[r.Name]; !ok {
|
|
|
|
// It is a Type of the vocabulary
|
|
|
|
if t, ok := vocab.Types[r.Name]; !ok {
|
|
|
|
e = fmt.Errorf("cannot find own kind with name %q", r.Name)
|
|
|
|
return
|
|
|
|
} else {
|
2018-12-09 20:45:08 +09:00
|
|
|
var kt *props.Kind
|
|
|
|
kt, e = c.convertTypeToKind(t)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
k = append(k, *kt)
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// It is a Value of the vocabulary
|
|
|
|
k = append(k, *kind)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var url string
|
|
|
|
url, e = c.Registry.ResolveAlias(r.Vocab)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
refVocab, ok := refs[url]
|
|
|
|
if !ok {
|
|
|
|
e = fmt.Errorf("references do not contain %s", url)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if val, ok := refVocab.Values[r.Name]; !ok {
|
|
|
|
// It is a Type of the vocabulary instead
|
|
|
|
if t, ok := refVocab.Types[r.Name]; !ok {
|
|
|
|
e = fmt.Errorf("cannot find kind with name %q in %s", r.Name, url)
|
|
|
|
return
|
|
|
|
} else {
|
2018-12-09 20:45:08 +09:00
|
|
|
var kt *props.Kind
|
|
|
|
kt, e = c.convertTypeToKind(t)
|
|
|
|
if e != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
k = append(k, *kt)
|
2018-12-09 07:05:02 +09:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// It is a Value of the vocabulary
|
|
|
|
k = append(k, *c.convertValue(val))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-09 19:40:59 +09:00
|
|
|
func (c Converter) typePackageName(v rdf.VocabularyType) (pkg string, e error) {
|
|
|
|
switch c.TypePackagePolicy {
|
|
|
|
case TypeFlatUnderRoot:
|
|
|
|
pkg = c.TypePackageRoot
|
|
|
|
case TypeIndividualUnderRoot:
|
|
|
|
pkg = v.Name
|
|
|
|
case TypeFlatUnderVocabularyRoot:
|
|
|
|
pkg = c.VocabularyRoot
|
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-09 07:05:02 +09:00
|
|
|
func (c Converter) propertyPackageName(v rdf.VocabularyProperty) (pkg string, e error) {
|
|
|
|
switch c.PropertyPackagePolicy {
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyFlatUnderRoot:
|
2018-12-09 07:05:02 +09:00
|
|
|
pkg = c.PropertyPackageRoot
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyIndividualUnderRoot:
|
2018-12-09 07:05:02 +09:00
|
|
|
pkg = v.Name
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyFlatUnderVocabularyRoot:
|
|
|
|
pkg = c.VocabularyRoot
|
2018-12-09 07:05:02 +09:00
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-18 07:11:55 +09:00
|
|
|
func (c Converter) typePackageDirectory(v *props.TypeGenerator) (dir string, e error) {
|
2018-12-10 05:23:32 +09:00
|
|
|
switch c.TypePackagePolicy {
|
|
|
|
case TypeFlatUnderRoot:
|
|
|
|
dir = fmt.Sprintf("%s/%s/", c.VocabularyRoot, c.TypePackageRoot)
|
|
|
|
case TypeIndividualUnderRoot:
|
|
|
|
dir = fmt.Sprintf("%s/%s/%s/", c.VocabularyRoot, c.TypePackageRoot, v.TypeName())
|
|
|
|
case TypeFlatUnderVocabularyRoot:
|
|
|
|
dir = c.VocabularyRoot + "/"
|
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-18 07:11:55 +09:00
|
|
|
func (c Converter) typePackageFile(v *props.TypeGenerator) (pkg string, e error) {
|
2018-12-09 19:40:59 +09:00
|
|
|
switch c.TypePackagePolicy {
|
|
|
|
case TypeFlatUnderRoot:
|
|
|
|
pkg = fmt.Sprintf("%s/%s", c.VocabularyRoot, c.TypePackageRoot)
|
|
|
|
case TypeIndividualUnderRoot:
|
2018-12-10 05:23:32 +09:00
|
|
|
pkg = fmt.Sprintf("%s/%s/%s", c.VocabularyRoot, c.TypePackageRoot, v.TypeName())
|
2018-12-09 19:40:59 +09:00
|
|
|
case TypeFlatUnderVocabularyRoot:
|
|
|
|
pkg = c.VocabularyRoot
|
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-10 05:23:32 +09:00
|
|
|
type propertyNamer interface {
|
|
|
|
PropertyName() string
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
_ propertyNamer = &props.FunctionalPropertyGenerator{}
|
|
|
|
_ propertyNamer = &props.NonFunctionalPropertyGenerator{}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (c Converter) propertyPackageDirectory(v propertyNamer) (dir string, e error) {
|
|
|
|
switch c.PropertyPackagePolicy {
|
|
|
|
case PropertyFlatUnderRoot:
|
|
|
|
dir = fmt.Sprintf("%s/%s/", c.VocabularyRoot, c.PropertyPackageRoot)
|
|
|
|
case PropertyIndividualUnderRoot:
|
|
|
|
dir = fmt.Sprintf("%s/%s/%s/", c.VocabularyRoot, c.PropertyPackageRoot, v.PropertyName())
|
|
|
|
case PropertyFlatUnderVocabularyRoot:
|
|
|
|
dir = c.VocabularyRoot + "/"
|
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) propertyPackageFile(v propertyNamer) (pkg string, e error) {
|
2018-12-09 07:05:02 +09:00
|
|
|
switch c.PropertyPackagePolicy {
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyFlatUnderRoot:
|
2018-12-09 07:05:02 +09:00
|
|
|
pkg = fmt.Sprintf("%s/%s", c.VocabularyRoot, c.PropertyPackageRoot)
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyIndividualUnderRoot:
|
2018-12-10 05:23:32 +09:00
|
|
|
pkg = fmt.Sprintf("%s/%s/%s", c.VocabularyRoot, c.PropertyPackageRoot, v.PropertyName())
|
2018-12-09 19:40:59 +09:00
|
|
|
case PropertyFlatUnderVocabularyRoot:
|
|
|
|
pkg = c.VocabularyRoot
|
2018-12-09 07:05:02 +09:00
|
|
|
default:
|
|
|
|
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) toIdentifier(n rdf.NameGetter) props.Identifier {
|
|
|
|
return props.Identifier{
|
|
|
|
LowerName: n.GetName(),
|
|
|
|
CamelName: strings.Title(n.GetName()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Converter) isNilable(goType string) bool {
|
|
|
|
return goType[0] == '*'
|
|
|
|
}
|
2018-12-10 05:23:32 +09:00
|
|
|
|
2018-12-18 07:11:55 +09:00
|
|
|
func allExtendsAreIn(t rdf.VocabularyType, v map[string]*props.TypeGenerator) bool {
|
2018-12-10 05:23:32 +09:00
|
|
|
for _, e := range t.Extends {
|
|
|
|
if len(e.Vocab) != 0 {
|
2018-12-18 07:11:55 +09:00
|
|
|
// TODO: This should be fixed to handle references
|
2018-12-10 05:23:32 +09:00
|
|
|
return false
|
|
|
|
} else if _, ok := v[e.Name]; !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|