feat: initial commit
This commit is contained in:
commit
a161b86c9a
705 changed files with 288162 additions and 0 deletions
771
vendor/sourcery.dny.nu/longdistance/term.go
vendored
Normal file
771
vendor/sourcery.dny.nu/longdistance/term.go
vendored
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
package longdistance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"sourcery.dny.nu/longdistance/internal/json"
|
||||
"sourcery.dny.nu/longdistance/internal/url"
|
||||
)
|
||||
|
||||
// Term represents a term definition in a JSON-LD context.
|
||||
type Term struct {
|
||||
IRI string
|
||||
Prefix bool
|
||||
Protected bool
|
||||
Reverse bool
|
||||
|
||||
BaseIRI string
|
||||
Context json.RawMessage
|
||||
Container []string
|
||||
Direction string
|
||||
Index string
|
||||
Language string
|
||||
Nest string
|
||||
Type string
|
||||
}
|
||||
|
||||
func (t *Term) equalWithoutProtected(ot *Term) bool {
|
||||
if t == nil && ot == nil {
|
||||
return true
|
||||
}
|
||||
if t == nil || ot == nil {
|
||||
return false
|
||||
}
|
||||
if t.IRI != ot.IRI {
|
||||
return false
|
||||
}
|
||||
if t.Prefix != ot.Prefix {
|
||||
return false
|
||||
}
|
||||
if t.Reverse != ot.Reverse {
|
||||
return false
|
||||
}
|
||||
if t.BaseIRI != ot.BaseIRI {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(t.Context, ot.Context) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Container, ot.Container) {
|
||||
return false
|
||||
}
|
||||
if t.Direction != ot.Direction {
|
||||
return false
|
||||
}
|
||||
if t.Index != ot.Index {
|
||||
return false
|
||||
}
|
||||
if t.Language != ot.Language {
|
||||
return false
|
||||
}
|
||||
if t.Nest != ot.Nest {
|
||||
return false
|
||||
}
|
||||
if t.Type != ot.Type {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *Term) IsZero() bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
return t.IRI == "" && !t.Prefix && !t.Protected &&
|
||||
!t.Reverse && t.BaseIRI == "" && t.Context == nil &&
|
||||
t.Container == nil && t.Direction == "" &&
|
||||
t.Index == "" && t.Language == "" && t.Nest == "" &&
|
||||
t.Type == ""
|
||||
}
|
||||
|
||||
type createTermOptions struct {
|
||||
baseURL string
|
||||
protected bool
|
||||
override bool
|
||||
remotes []string
|
||||
validate bool
|
||||
}
|
||||
|
||||
func newCreateTermOptions() createTermOptions {
|
||||
return createTermOptions{
|
||||
validate: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Processor) createTerm(
|
||||
activeContext *Context,
|
||||
localContext map[string]json.RawMessage,
|
||||
term string,
|
||||
defined map[string]*bool,
|
||||
opts createTermOptions,
|
||||
) error {
|
||||
// 1)
|
||||
if v := defined[term]; v != nil {
|
||||
if *v {
|
||||
return nil
|
||||
}
|
||||
return ErrCyclicIRIMapping
|
||||
}
|
||||
|
||||
// 2)
|
||||
if term == "" {
|
||||
return ErrInvalidTermDefinition
|
||||
} else {
|
||||
b := false
|
||||
defined[term] = &b
|
||||
}
|
||||
|
||||
// 3)
|
||||
value := localContext[term]
|
||||
|
||||
// 4)
|
||||
if term == KeywordType {
|
||||
if p.modeLD10 {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
|
||||
var obj map[string]json.RawMessage
|
||||
if err := json.Unmarshal(value, &obj); err != nil {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
|
||||
if len(obj) == 0 {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
|
||||
objCopy := maps.Clone(obj)
|
||||
delete(objCopy, KeywordContainer)
|
||||
delete(objCopy, KeywordProtected)
|
||||
if len(objCopy) != 0 {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
|
||||
if v, ok := obj[KeywordContainer]; ok {
|
||||
var s string
|
||||
if err := json.Unmarshal(v, &s); err != nil {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
if s != KeywordSet {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
}
|
||||
if v, ok := obj[KeywordProtected]; ok {
|
||||
var b bool
|
||||
if err := json.Unmarshal(v, &b); err != nil {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 5)
|
||||
if isKeyword(term) {
|
||||
return ErrKeywordRedefinition
|
||||
}
|
||||
|
||||
if looksLikeKeyword(term) {
|
||||
p.logger.Warn("keyword lookalike term encountered", slog.String("term", term))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 6)
|
||||
oldDef, oldDefOK := activeContext.defs[term]
|
||||
delete(activeContext.defs, term)
|
||||
if !oldDefOK {
|
||||
// check for aliasses
|
||||
for _, def := range activeContext.defs {
|
||||
if def.IRI != "" && def.IRI == term {
|
||||
oldDef = def
|
||||
oldDefOK = true
|
||||
delete(activeContext.defs, term)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simpleTerm := false
|
||||
var valueObj map[string]json.RawMessage
|
||||
|
||||
// 7) 8)
|
||||
if json.IsNull(value) || json.IsString(value) {
|
||||
// 8)
|
||||
if json.IsString(value) {
|
||||
simpleTerm = true
|
||||
}
|
||||
|
||||
// 7)
|
||||
value = bytes.Join([][]byte{
|
||||
[]byte(`{"@id":`),
|
||||
value,
|
||||
[]byte(`}`),
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// 9)
|
||||
if err := json.Unmarshal(value, &valueObj); err != nil {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 10)
|
||||
termDef := Term{
|
||||
Prefix: false,
|
||||
Protected: opts.protected,
|
||||
Reverse: false,
|
||||
}
|
||||
|
||||
// 11)
|
||||
if prot, ok := valueObj[KeywordProtected]; ok {
|
||||
if p.modeLD10 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
var b bool
|
||||
if err := json.Unmarshal(prot, &b); err != nil {
|
||||
return ErrInvalidProtectedValue
|
||||
}
|
||||
termDef.Protected = b
|
||||
}
|
||||
|
||||
// at this point protected is finalised, so add the
|
||||
// term to the protected set on activeContext
|
||||
if termDef.Protected {
|
||||
activeContext.protected[term] = struct{}{}
|
||||
}
|
||||
|
||||
// 12)
|
||||
if typ, ok := valueObj[KeywordType]; ok {
|
||||
if json.IsNull(typ) {
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
|
||||
var s string
|
||||
// 12.1)
|
||||
if err := json.Unmarshal(typ, &s); err != nil {
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
|
||||
// 12.2)
|
||||
u, err := p.expandIRI(activeContext, s, false, true, localContext, defined)
|
||||
if err != nil {
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
|
||||
// 12.3
|
||||
if p.modeLD10 {
|
||||
if u == KeywordNone || u == KeywordJSON {
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
}
|
||||
|
||||
// 12.4)
|
||||
switch u {
|
||||
case KeywordID, KeywordJSON, KeywordNone, KeywordVocab:
|
||||
default:
|
||||
if !url.IsIRI(u) {
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
}
|
||||
|
||||
// 12.5)
|
||||
termDef.Type = u
|
||||
}
|
||||
|
||||
// prep for branch 14)
|
||||
id, idOK := valueObj[KeywordID]
|
||||
var idStr string
|
||||
idErr := json.Unmarshal(id, &idStr)
|
||||
|
||||
// 13)
|
||||
if rev, ok := valueObj[KeywordReverse]; ok {
|
||||
_, hasID := valueObj[KeywordID]
|
||||
_, hasNest := valueObj[KeywordNest]
|
||||
// 13.1)
|
||||
if hasID || hasNest {
|
||||
return ErrInvalidReverseProperty
|
||||
}
|
||||
|
||||
// 13.2)
|
||||
if json.IsNull(rev) {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
var s string
|
||||
if err := json.Unmarshal(rev, &s); err != nil {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
// 13.3)
|
||||
if looksLikeKeyword(s) {
|
||||
p.logger.Warn("keyword lookalike value encountered",
|
||||
slog.String("value", s))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 13.4)
|
||||
u, err := p.expandIRI(activeContext, s, false, true, localContext, defined)
|
||||
if err != nil {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
if !url.IsIRI(u) && u != BlankNode {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
termDef.IRI = u
|
||||
|
||||
// 13.5)
|
||||
if v, ok := valueObj[KeywordContainer]; ok {
|
||||
if json.IsNull(v) {
|
||||
termDef.Container = nil
|
||||
} else {
|
||||
var c string
|
||||
if err := json.Unmarshal(v, &c); err != nil {
|
||||
return ErrInvalidReverseProperty
|
||||
}
|
||||
|
||||
if c != KeywordSet && c != KeywordIndex {
|
||||
return ErrInvalidReverseProperty
|
||||
}
|
||||
|
||||
termDef.Container = []string{c}
|
||||
}
|
||||
}
|
||||
|
||||
// 13.6)
|
||||
termDef.Reverse = true
|
||||
|
||||
// This whole step is missing in the spec but without
|
||||
// it t0131 can't pass. So. YOLO.
|
||||
if slices.Contains(termDef.Container, KeywordIndex) {
|
||||
idxVal, idxOK := valueObj[KeywordIndex]
|
||||
if idxOK && !json.IsNull(idxVal) {
|
||||
var idx string
|
||||
if err := json.Unmarshal(idxVal, &idx); err != nil {
|
||||
return err
|
||||
}
|
||||
termDef.Index = idx
|
||||
}
|
||||
}
|
||||
|
||||
// 13.7
|
||||
activeContext.defs[term] = termDef
|
||||
b := true
|
||||
defined[term] = &b
|
||||
return nil
|
||||
} else if idOK && term != idStr {
|
||||
// 14.1) 14.2)
|
||||
if idErr != nil {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
// 14.1)
|
||||
if !json.IsNull(id) {
|
||||
// 14.2)
|
||||
if !isKeyword(idStr) && looksLikeKeyword(idStr) {
|
||||
// 14.2.2)
|
||||
p.logger.Warn("keyword lookalike value encountered",
|
||||
slog.String("value", idStr))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 14.2.3)
|
||||
u, err := p.expandIRI(activeContext, idStr, false, true, localContext, defined)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !isKeyword(u) && !url.IsIRI(u) && u != BlankNode {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
if u == KeywordContext {
|
||||
return ErrInvalidKeywordAlias
|
||||
}
|
||||
|
||||
termDef.IRI = u
|
||||
|
||||
// 14.2.4)
|
||||
if strings.Contains(term, "/") || (!strings.HasPrefix(term, ":") && !strings.HasSuffix(term, ":") && strings.Contains(term, ":")) {
|
||||
b := true
|
||||
// 14.2.4.1)
|
||||
defined[term] = &b
|
||||
|
||||
// 14.2.4.2)
|
||||
tu, err := p.expandIRI(activeContext, term, false, true, localContext, defined)
|
||||
if err != nil {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
if tu != u {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
} else {
|
||||
// 14.2.5)
|
||||
if simpleTerm && url.EndsInGenDelim(u) || u == BlankNode {
|
||||
if v, ok := p.remapPrefixIRIs[u]; ok {
|
||||
termDef.IRI = v
|
||||
}
|
||||
termDef.Prefix = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if strings.Contains(term[1:], ":") {
|
||||
// 15)
|
||||
prefix, suffix, _ := strings.Cut(term, ":")
|
||||
|
||||
// 15.1)
|
||||
if !strings.HasPrefix(suffix, "//") {
|
||||
if _, ok := localContext[prefix]; ok {
|
||||
err := p.createTerm(activeContext, localContext, prefix, defined, newCreateTermOptions())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 15.2)
|
||||
if def, ok := activeContext.defs[prefix]; ok {
|
||||
termDef.IRI = def.IRI + suffix
|
||||
} else {
|
||||
// 15.3)
|
||||
termDef.IRI = term
|
||||
}
|
||||
} else if strings.Contains(term, "/") {
|
||||
// 16)
|
||||
// 16.2)
|
||||
u, err := p.expandIRI(activeContext, term, false, true, nil, nil)
|
||||
if err != nil {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
if !url.IsIRI(u) {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
termDef.IRI = u
|
||||
} else if term == KeywordType {
|
||||
// 17)
|
||||
termDef.IRI = KeywordType
|
||||
} else if activeContext.vocabMapping != "" {
|
||||
// 18)
|
||||
termDef.IRI = activeContext.vocabMapping + term
|
||||
} else {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
|
||||
// 19)
|
||||
if cnt, ok := valueObj[KeywordContainer]; ok {
|
||||
if json.IsNull(cnt) {
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
|
||||
// 19.2)
|
||||
// do this check early since we're going to rewrap
|
||||
// into an array
|
||||
if p.modeLD10 && !json.IsString(cnt) {
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
|
||||
cnt = json.MakeArray(cnt)
|
||||
|
||||
// 19.1)
|
||||
var values []string
|
||||
if err := json.Unmarshal(cnt, &values); err != nil {
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
|
||||
for _, vl := range values {
|
||||
switch vl {
|
||||
case KeywordGraph, KeywordID, KeywordIndex,
|
||||
KeywordLanguage, KeywordList, KeywordSet,
|
||||
KeywordType:
|
||||
default:
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
}
|
||||
|
||||
if slices.Contains(values, KeywordGraph) && (slices.Contains(values, KeywordID) || slices.Contains(values, KeywordIndex)) {
|
||||
kws := map[string]struct{}{}
|
||||
for _, vl := range values {
|
||||
kws[vl] = struct{}{}
|
||||
}
|
||||
delete(kws, KeywordGraph)
|
||||
delete(kws, KeywordIndex)
|
||||
delete(kws, KeywordID)
|
||||
if _, ok := kws[KeywordSet]; ok && len(kws) != 1 {
|
||||
return ErrInvalidIRIMapping
|
||||
}
|
||||
} else if slices.Contains(values, KeywordSet) {
|
||||
for _, vl := range values {
|
||||
switch vl {
|
||||
case KeywordGraph, KeywordID, KeywordIndex,
|
||||
KeywordLanguage, KeywordType,
|
||||
KeywordSet:
|
||||
default:
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 19.2)
|
||||
if p.modeLD10 {
|
||||
if len(values) > 1 {
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
switch values[0] {
|
||||
case KeywordID, KeywordGraph, KeywordType:
|
||||
return ErrInvalidContainerMapping
|
||||
}
|
||||
}
|
||||
|
||||
// 19.3)
|
||||
termDef.Container = values
|
||||
|
||||
// 19.4)
|
||||
if slices.Contains(values, KeywordType) {
|
||||
// 19.4.1)
|
||||
if termDef.Type == "" {
|
||||
termDef.Type = KeywordID
|
||||
}
|
||||
// 19.4.2)
|
||||
switch termDef.Type {
|
||||
case KeywordID, KeywordVocab, "":
|
||||
default:
|
||||
return ErrInvalidTypeMapping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 20)
|
||||
if idx, ok := valueObj[KeywordIndex]; ok {
|
||||
// 20.1)
|
||||
if p.modeLD10 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
if !slices.Contains(termDef.Container, KeywordIndex) {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 20.2)
|
||||
var s string
|
||||
if err := json.Unmarshal(idx, &s); err != nil {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
u, err := p.expandIRI(activeContext, s, false, true, localContext, defined)
|
||||
if err != nil {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
if !url.IsIRI(u) {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 20.3)
|
||||
termDef.Index = s
|
||||
}
|
||||
|
||||
// 21)
|
||||
if ctx, ok := valueObj[KeywordContext]; ok {
|
||||
// 21.1)
|
||||
if p.modeLD10 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 21.3)
|
||||
resolvOpts := newCtxProcessingOpts()
|
||||
resolvOpts.override = true
|
||||
resolvOpts.remotes = slices.Clone(opts.remotes)
|
||||
resolvOpts.validate = false
|
||||
_, err := p.context(
|
||||
activeContext,
|
||||
ctx,
|
||||
opts.baseURL,
|
||||
resolvOpts,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return ErrInvalidScopedContext
|
||||
}
|
||||
|
||||
// 21.4
|
||||
termDef.Context = ctx
|
||||
termDef.BaseIRI = opts.baseURL
|
||||
}
|
||||
|
||||
_, hasType := valueObj[KeywordType]
|
||||
|
||||
// 22)
|
||||
if lang, ok := valueObj[KeywordLanguage]; ok && !hasType {
|
||||
if json.IsNull(lang) {
|
||||
termDef.Language = KeywordNull
|
||||
} else {
|
||||
var lm string
|
||||
// 22.1)
|
||||
if err := json.Unmarshal(lang, &lm); err != nil {
|
||||
return ErrInvalidLanguageMapping
|
||||
}
|
||||
|
||||
// 22.2)
|
||||
termDef.Language = strings.ToLower(lm)
|
||||
}
|
||||
}
|
||||
|
||||
// 23)
|
||||
if dir, ok := valueObj[KeywordDirection]; ok && !hasType {
|
||||
if json.IsNull(dir) {
|
||||
termDef.Direction = KeywordNull
|
||||
} else {
|
||||
var d string
|
||||
// 23.1)
|
||||
if err := json.Unmarshal(dir, &d); err != nil {
|
||||
return ErrInvalidBaseDirection
|
||||
}
|
||||
|
||||
switch d {
|
||||
case DirectionLTR, DirectionRTL:
|
||||
default:
|
||||
return ErrInvalidBaseDirection
|
||||
}
|
||||
|
||||
// 23.2)
|
||||
termDef.Direction = d
|
||||
}
|
||||
}
|
||||
|
||||
// 24)
|
||||
if nest, ok := valueObj[KeywordNest]; ok {
|
||||
// 24.1)
|
||||
if p.modeLD10 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
if json.IsNull(nest) {
|
||||
return ErrInvalidNestValue
|
||||
}
|
||||
|
||||
// 24.2)
|
||||
var n string
|
||||
if err := json.Unmarshal(nest, &n); err != nil {
|
||||
return ErrInvalidNestValue
|
||||
}
|
||||
|
||||
if isKeyword(n) && n != KeywordNest {
|
||||
return ErrInvalidNestValue
|
||||
}
|
||||
termDef.Nest = n
|
||||
}
|
||||
|
||||
// 25)
|
||||
if prefix, ok := valueObj[KeywordPrefix]; ok {
|
||||
// 25.1)
|
||||
if p.modeLD10 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 25.2)
|
||||
if json.IsNull(prefix) {
|
||||
return ErrInvalidPrefixValue
|
||||
}
|
||||
|
||||
if strings.Contains(term, ":") || strings.Contains(term, "/") {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
var p bool
|
||||
if err := json.Unmarshal(prefix, &p); err != nil {
|
||||
return ErrInvalidPrefixValue
|
||||
}
|
||||
|
||||
// 25.3)
|
||||
if p && isKeyword(termDef.IRI) {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
termDef.Prefix = p
|
||||
}
|
||||
|
||||
// 26)
|
||||
valKeys := map[string]struct{}{}
|
||||
for k := range valueObj {
|
||||
valKeys[k] = struct{}{}
|
||||
}
|
||||
|
||||
for _, kw := range []string{KeywordID, KeywordReverse, KeywordContainer,
|
||||
KeywordContext, KeywordDirection, KeywordIndex, KeywordLanguage,
|
||||
KeywordNest, KeywordPrefix, KeywordProtected, KeywordType} {
|
||||
delete(valKeys, kw)
|
||||
}
|
||||
|
||||
if len(valKeys) > 0 {
|
||||
return ErrInvalidTermDefinition
|
||||
}
|
||||
|
||||
// 27)
|
||||
if oldDefOK && oldDef.Protected && !opts.override {
|
||||
// 27.1)
|
||||
if !oldDef.equalWithoutProtected(&termDef) {
|
||||
return ErrProtectedTermRedefinition
|
||||
}
|
||||
// 27.2)
|
||||
termDef = oldDef
|
||||
}
|
||||
|
||||
// 28)
|
||||
activeContext.defs[term] = termDef
|
||||
b := true
|
||||
defined[term] = &b
|
||||
return nil
|
||||
}
|
||||
|
||||
func selectTerm(
|
||||
activeContext *Context,
|
||||
keyIriVar string,
|
||||
containers []string,
|
||||
typeLanguage string,
|
||||
preferredValues []string,
|
||||
) string {
|
||||
// 1)
|
||||
if activeContext.inverse == nil {
|
||||
activeContext.inverse = workIt(activeContext)
|
||||
}
|
||||
|
||||
// 2)
|
||||
inverse := activeContext.inverse
|
||||
|
||||
// 3)
|
||||
containerMap := inverse[keyIriVar]
|
||||
|
||||
for _, container := range containers {
|
||||
// 4.1)
|
||||
// 4.2)
|
||||
typeLanguageMap, ok := containerMap[container]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// 4.3)
|
||||
var valMap map[string]string
|
||||
switch typeLanguage {
|
||||
case KeywordLanguage:
|
||||
valMap = typeLanguageMap.Language
|
||||
case KeywordType:
|
||||
valMap = typeLanguageMap.Type
|
||||
case KeywordAny:
|
||||
valMap = typeLanguageMap.Any
|
||||
}
|
||||
|
||||
// 4.4)
|
||||
for _, pval := range preferredValues {
|
||||
if v, ok := valMap[pval]; !ok {
|
||||
// 4.4.1)
|
||||
continue
|
||||
} else {
|
||||
// 4.4.2)
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5)
|
||||
return ""
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue