From 61cacf0e0af40db196ecfda68e61da53a3eaa5b6 Mon Sep 17 00:00:00 2001 From: Michael Adler Date: Wed, 10 Dec 2025 16:03:59 +0100 Subject: [PATCH] fix: restore external access to Context fields Commit dd9b662 inadvertently made Context fields and subfields inaccessible to library users, breaking the ability to inspect Context contents (e.g., using AsMap()). This change restores public visibility to the relevant Context fields, allowing external code to access all necessary data. Internal fields (e.g., those used for caching) remain private. Additionally, this commit removes the unused 'typ' field from Values by inlining its default value (the empty string), as it was never set. Signed-off-by: Michael Adler --- ld/api_compact.go | 26 +-- ld/api_expand.go | 24 +-- ld/context.go | 436 +++++++++++++++++++++++----------------------- 3 files changed, 243 insertions(+), 243 deletions(-) diff --git a/ld/api_compact.go b/ld/api_compact.go index c470057..69f6137 100644 --- a/ld/api_compact.go +++ b/ld/api_compact.go @@ -49,8 +49,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element } // use any scoped context on activeProperty - if td := activeCtx.GetTermDefinition(activeProperty); td != nil && td.hasContext { - newCtx, err := activeCtx.parse(td.context, make([]string, 0), false, true, false, true) + if td := activeCtx.GetTermDefinition(activeProperty); td != nil && td.HasContext { + newCtx, err := activeCtx.parse(td.Context, make([]string, 0), false, true, false, true) if err != nil { return nil, err } @@ -68,7 +68,7 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element propType := "" if td := activeCtx.GetTermDefinition(activeProperty); td != nil { - propType = td.typ + propType = td.Type } if _, isMap := compactedValue.(map[string]interface{}); !isMap || propType == "@json" { return compactedValue, nil @@ -97,8 +97,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element } // apply property-scoped context after reverting term-scoped context - if td := inputCtx.GetTermDefinition(activeProperty); td != nil && td.context != nil { - newCtx, err := activeCtx.parse(td.context, nil, false, true, false, true) + if td := inputCtx.GetTermDefinition(activeProperty); td != nil && td.Context != nil { + newCtx, err := activeCtx.parse(td.Context, nil, false, true, false, true) if err != nil { return nil, err } @@ -124,8 +124,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element // process in lexicographical order, see https://github.com/json-ld/json-ld.org/issues/616 sort.Strings(types) for _, tt := range types { - if td := inputCtx.GetTermDefinition(tt); td != nil && td.hasContext { - newCtx, err := activeCtx.parse(td.context, nil, false, false, false, false) + if td := inputCtx.GetTermDefinition(tt); td != nil && td.HasContext { + newCtx, err := activeCtx.parse(td.Context, nil, false, false, false, false) if err != nil { return nil, err } @@ -274,8 +274,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element } nestResult := result - if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.nest != "" { - nestProperty := td.nest + if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.Nest != "" { + nestProperty := td.Nest if err := api.checkNestProperty(activeCtx, nestProperty); err != nil { return nil, err } @@ -304,8 +304,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element // if itemActiveProperty is a @nest property, add values to nestResult, otherwise result nestResult := result - if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.nest != "" { - nestProperty := td.nest + if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.Nest != "" { + nestProperty := td.Nest if err := api.checkNestProperty(activeCtx, nestProperty); err != nil { return nil, err } @@ -475,8 +475,8 @@ func (api *JsonLdApi) Compact(activeCtx *Context, activeProperty string, element } else if isIndexContainer { indexKey := "@index" - if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.index != "" { - indexKey = td.index + if td := activeCtx.GetTermDefinition(itemActiveProperty); td != nil && td.Index != "" { + indexKey = td.Index } containerKey, err := activeCtx.CompactIri(indexKey, nil, true, false) diff --git a/ld/api_expand.go b/ld/api_expand.go index 6d85b37..693c5c6 100644 --- a/ld/api_expand.go +++ b/ld/api_expand.go @@ -88,7 +88,7 @@ func (api *JsonLdApi) Expand(activeCtx *Context, activeProperty string, element // Get any property-scoped context for activeProperty var propertyScopedCtx interface{} if td := activeCtx.GetTermDefinition(activeProperty); td != nil { - propertyScopedCtx = td.context + propertyScopedCtx = td.Context } // second, determine if any type-scoped context should be reverted; it @@ -182,8 +182,8 @@ func (api *JsonLdApi) Expand(activeCtx *Context, activeProperty string, element } for _, tt := range types { - if td := typeScopedContext.GetTermDefinition(tt); td != nil && td.hasContext { - newCtx, err := activeCtx.parse(td.context, nil, false, false, false, false) + if td := typeScopedContext.GetTermDefinition(tt); td != nil && td.HasContext { + newCtx, err := activeCtx.parse(td.Context, nil, false, false, false, false) if err != nil { return nil, err } @@ -669,10 +669,10 @@ func (api *JsonLdApi) expandObject(activeCtx *Context, activeProperty string, ex // use potential scoped context for key termCtx := activeCtx td := activeCtx.GetTermDefinition(key) - if td != nil && td.hasContext { + if td != nil && td.HasContext { // TODO: fix calling a private method //termCtx, err = activeCtx.Parse(ctx) - termCtx, err = activeCtx.parse(td.context, make([]string, 0), false, true, false, true) + termCtx, err = activeCtx.parse(td.Context, make([]string, 0), false, true, false, true) if err != nil { return err } @@ -682,7 +682,7 @@ func (api *JsonLdApi) expandObject(activeCtx *Context, activeProperty string, ex if termCtx.HasContainerMapping(key, "@language") && isMap { var expandedValueList []interface{} - dir, hasDir := td.direction, td.hasDirection + dir, hasDir := td.Direction, td.HasDirection for _, language := range GetOrderedKeys(valueMap) { expandedLanguage, err := termCtx.ExpandIri(language, false, true, nil, nil) @@ -710,7 +710,7 @@ func (api *JsonLdApi) expandObject(activeCtx *Context, activeProperty string, ex if dir != nil { v["@direction"] = dir } - } else if defaultDir := termCtx.values.direction; defaultDir != "" { + } else if defaultDir := termCtx.Values.Direction; defaultDir != "" { v["@direction"] = defaultDir } expandedValueList = append(expandedValueList, v) @@ -720,8 +720,8 @@ func (api *JsonLdApi) expandObject(activeCtx *Context, activeProperty string, ex } else if termCtx.HasContainerMapping(key, "@index") && isMap { // 7.6) asGraph := termCtx.HasContainerMapping(key, "@graph") indexKey := "@index" - if tdKey := termCtx.GetTermDefinition(key); tdKey != nil && tdKey.index != "" { - indexKey = tdKey.index + if tdKey := termCtx.GetTermDefinition(key); tdKey != nil && tdKey.Index != "" { + indexKey = tdKey.Index } var propertyIndex string if indexKey != "@index" { @@ -761,7 +761,7 @@ func (api *JsonLdApi) expandObject(activeCtx *Context, activeProperty string, ex if err != nil { return err } - } else if tdKey != nil && tdKey.typ == "@json" { + } else if tdKey != nil && tdKey.Type == "@json" { expandedValue = map[string]interface{}{ "@type": "@json", "@value": value, @@ -913,8 +913,8 @@ func (api *JsonLdApi) expandIndexMap(activeCtx *Context, activeProperty string, indexCtx := activeCtx // if indexKey is @type, there may be a context defined for it - if td := activeCtx.GetTermDefinition(key); indexKey == "@type" && td != nil && td.hasContext { - newCtx, err := activeCtx.Parse(td.context) + if td := activeCtx.GetTermDefinition(key); indexKey == "@type" && td != nil && td.HasContext { + newCtx, err := activeCtx.Parse(td.Context) if err != nil { return nil, err } diff --git a/ld/context.go b/ld/context.go index bbdfef4..973b98d 100644 --- a/ld/context.go +++ b/ld/context.go @@ -43,75 +43,78 @@ var ( // Context represents a JSON-LD context and provides easy access to specific // keys and operations. type Context struct { - values *Values + Values *Values + TermDefinitions map[string]*TermDefinition + Protected map[string]bool // @protected terms + options *JsonLdOptions - termDefinitions map[string]*TermDefinition - inverse map[string]interface{} - protected map[string]bool + inverse map[string]interface{} // cache for inverse context previousContext *Context fastCurieMap map[string]interface{} } type Values struct { - vocab *string - base string - direction string - version *float64 - processingMode string - typ string - language string - hasLanguage bool + Vocab *string // @vocab + Base string // @base IRI against which to resolve those relative IRI references which are otherwise interpreted relative to the document + Direction string // @direction + Version *float64 // @version + Language string // @language + HasLanguage bool // whether @language is set + + processingMode string // JSON-LD processingMode based on @version and/or JsonLdOptions } +// TermDefinition is an expanded term definition, see ยง 9.15.1 (https://www.w3.org/TR/json-ld11/#expanded-term-definition). type TermDefinition struct { - id string - reverse bool - container []string - typ string - nest string - context interface{} - hasContext bool // nil is not the same as having explicitly "null" in the JSON-LD context - prefix *bool - index string - protected bool - direction *string - hasDirection bool - language *string - hasLanguage bool - termHasColon bool + ID string // The @id mapping for the term + Reverse bool // Indicates if the term is defined with @reverse + Container []string // The @container mapping for the term + Type string // The @type mapping for the term + Nest string // If the expanded term definition contains the @nest keyword, its value MUST be either @nest, or a term which expands to @nest. + Context any // The @context mapping for the term + HasContext bool // Indicates if the @context key is set (might be set to "null" which has a different semantic than being just absent, i.e. nil) + Prefix *bool // Indicates if the term is a prefix (@prefix) + Index string // If the expanded term definition contains the @index keyword, its value MUST be an IRI, a compact IRI, or a term. + Protected bool // Indicates if the term is protected (@protected) + Direction *string // The @direction mapping for the term + HasDirection bool // Indicates if the @direction key is set (might be set to "null" which has a different semantic than being just absent, i.e. nil) + Language *string // The @language mapping for the term (optional) + HasLanguage bool // Indicates if the term explicitly specifies a language + + termHasColon bool // whether the term contains a colon (:) } func (td *TermDefinition) Copy() *TermDefinition { var result TermDefinition - result.id = td.id - result.reverse = td.reverse - result.container = td.container - result.typ = td.typ - result.context = td.context - result.hasContext = td.hasContext - result.prefix = td.prefix - result.nest = td.nest - result.index = td.index - result.protected = td.protected - result.direction = td.direction - result.hasDirection = td.hasDirection - result.language = td.language - result.hasLanguage = td.hasLanguage + result.ID = td.ID + result.Reverse = td.Reverse + result.Container = td.Container + result.Type = td.Type + result.Context = td.Context + result.HasContext = td.HasContext + result.Prefix = td.Prefix + result.Nest = td.Nest + result.Index = td.Index + result.Protected = td.Protected + result.Direction = td.Direction + result.HasDirection = td.HasDirection + result.Language = td.Language + result.HasLanguage = td.HasLanguage return &result } func DeepCompareTermDef(lhs *TermDefinition, rhs *TermDefinition, listOrderMatters bool) bool { - return lhs.id == rhs.id && - lhs.reverse == rhs.reverse && - lhs.typ == rhs.typ && - lhs.hasContext == rhs.hasContext && - lhs.nest == rhs.nest && - lhs.index == rhs.index && - lhs.protected == rhs.protected && - reflect.DeepEqual(lhs.container, rhs.container) && - reflect.DeepEqual(lhs.direction, rhs.direction) && lhs.hasDirection == rhs.hasDirection && - reflect.DeepEqual(lhs.language, rhs.language) && lhs.hasLanguage == rhs.hasLanguage && - DeepCompare(lhs.context, rhs.context, listOrderMatters) + return lhs.ID == rhs.ID && + lhs.Reverse == rhs.Reverse && + lhs.Type == rhs.Type && + lhs.HasContext == rhs.HasContext && + lhs.Nest == rhs.Nest && + lhs.Index == rhs.Index && + lhs.Protected == rhs.Protected && + reflect.DeepEqual(lhs.Container, rhs.Container) && + reflect.DeepEqual(lhs.Direction, rhs.Direction) && lhs.HasDirection == rhs.HasDirection && + reflect.DeepEqual(lhs.Language, rhs.Language) && lhs.HasLanguage == rhs.HasLanguage && + DeepCompare(lhs.Context, rhs.Context, listOrderMatters) } type FastCurieEntry struct { @@ -126,37 +129,37 @@ func NewContext(values map[string]interface{}, options *JsonLdOptions) *Context } context := &Context{ - values: &Values{}, + Values: &Values{}, options: options, - termDefinitions: make(map[string]*TermDefinition), - protected: make(map[string]bool), + TermDefinitions: make(map[string]*TermDefinition), + Protected: make(map[string]bool), fastCurieMap: make(map[string]any), } - context.values.base = options.Base + context.Values.Base = options.Base if values != nil { if val, ok := values["@vocab"]; ok { s := val.(string) - context.values.vocab = &s + context.Values.Vocab = &s } if val, ok := values["@language"]; ok { - context.values.language = val.(string) - context.values.hasLanguage = true + context.Values.Language = val.(string) + context.Values.HasLanguage = true } } - context.values.processingMode = options.ProcessingMode + context.Values.processingMode = options.ProcessingMode return context } func (c *Context) AsMap() map[string]interface{} { res := map[string]interface{}{ - "values": c.values, - "termDefinitions": c.termDefinitions, + "values": c.Values, + "termDefinitions": c.TermDefinitions, "inverse": c.inverse, - "protected": c.protected, + "protected": c.Protected, "fastCurieMap": c.fastCurieMap, } if c.previousContext != nil { @@ -168,17 +171,17 @@ func (c *Context) AsMap() map[string]interface{} { // CopyContext creates a full copy of the given context. func CopyContext(ctx *Context) *Context { context := NewContext(nil, ctx.options) - if ctx.values != nil { - values := *ctx.values - context.values = &values + if ctx.Values != nil { + values := *ctx.Values + context.Values = &values } - for k, v := range ctx.termDefinitions { - context.termDefinitions[k] = v + for k, v := range ctx.TermDefinitions { + context.TermDefinitions[k] = v } - for k, v := range ctx.protected { - context.protected[k] = v + for k, v := range ctx.Protected { + context.Protected[k] = v } // do not copy c.inverse, because it will be regenerated @@ -242,7 +245,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if context == nil { // We can't nullify if there are protected terms and we're // not allowing overrides (e.g. processing a property term scoped context) - if !overrideProtected && len(result.protected) != 0 { + if !overrideProtected && len(result.Protected) != 0 { return nil, NewJsonLdError(InvalidContextNullification, "tried to nullify a context with protected terms outside of a term definition.") } @@ -261,7 +264,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi result = ctx // 3.2) case string: - uri := Resolve(result.values.base, ctx) + uri := Resolve(result.Values.Base, ctx) // 3.2.2 for _, remoteCtx := range remoteContexts { if remoteCtx == uri { @@ -309,7 +312,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi } } - pm := c.values.processingMode + pm := c.Values.processingMode if versionValue, versionPresent := contextMap["@version"]; versionPresent { if versionValue != 1.1 { @@ -318,14 +321,14 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if pm == JsonLd_1_0 { return nil, NewJsonLdError(ProcessingModeConflict, fmt.Sprintf("@version: %v not compatible with %s", versionValue, pm)) } - result.values.processingMode = JsonLd_1_1 + result.Values.processingMode = JsonLd_1_1 ver := versionValue.(float64) - result.values.version = &ver + result.Values.Version = &ver } else if pm == "" { // if not set explicitly, set processingMode to "json-ld-1.0" - result.values.processingMode = JsonLd_1_0 + result.Values.processingMode = JsonLd_1_0 } else { - result.values.processingMode = pm + result.Values.processingMode = pm } // handle @import @@ -337,7 +340,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if !isString { return nil, NewJsonLdError(InvalidImportValue, "@import must be a string") } - uri := Resolve(result.values.base, importStr) + uri := Resolve(result.Values.Base, importStr) rd, err := c.options.DocumentLoader.LoadDocument(uri) if err != nil { @@ -372,16 +375,16 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi baseValue, basePresent := contextMap["@base"] if !parsingARemoteContext && basePresent { if baseValue == nil { - result.values.base = "" + result.Values.Base = "" } else if baseString, isString := baseValue.(string); isString { if IsAbsoluteIri(baseString) { - result.values.base = baseString + result.Values.Base = baseString } else { - baseURI := result.values.base + baseURI := result.Values.Base if !IsAbsoluteIri(baseURI) { return nil, NewJsonLdError(InvalidBaseIRI, baseURI) } - result.values.base = Resolve(baseURI, baseString) + result.Values.Base = Resolve(baseURI, baseString) } } else { return nil, NewJsonLdError(InvalidBaseIRI, "the value of @base in a @context must be a string or null") @@ -391,11 +394,11 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi // handle @language if languageValue, languagePresent := contextMap["@language"]; languagePresent { if languageValue == nil { - result.values.hasLanguage = false - result.values.language = "" + result.Values.HasLanguage = false + result.Values.Language = "" } else if languageString, isString := languageValue.(string); isString { - result.values.hasLanguage = true - result.values.language = strings.ToLower(languageString) + result.Values.HasLanguage = true + result.Values.Language = strings.ToLower(languageString) } else { return nil, NewJsonLdError(InvalidDefaultLanguage, languageValue) } @@ -404,10 +407,10 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi // handle @direction if directionValue, directionPresent := contextMap["@direction"]; directionPresent { if directionValue == nil { - result.values.direction = "" + result.Values.Direction = "" } else if directionString, isString := directionValue.(string); isString { if directionString == "rtl" || directionString == "ltr" { - result.values.direction = strings.ToLower(directionString) + result.Values.Direction = strings.ToLower(directionString) } else { return nil, NewJsonLdError(InvalidBaseDirection, directionValue) } @@ -425,7 +428,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if propagateValue, propagatePresent := contextMap["@propagate"]; propagatePresent { if c.processingMode(1.0) { return nil, NewJsonLdError(InvalidContextEntry, - fmt.Sprintf("@propagate not compatible with %s", c.values.processingMode)) + fmt.Sprintf("@propagate not compatible with %s", c.Values.processingMode)) } if _, isBool := propagateValue.(bool); isBool { defined["@propagate"] = true @@ -436,7 +439,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if vocabValue, vocabPresent := contextMap["@vocab"]; vocabPresent { if vocabValue == nil { - result.values.vocab = nil + result.Values.Vocab = nil } else if vocabString, isString := vocabValue.(string); isString { if !IsAbsoluteIri(vocabString) && c.processingMode(1.0) { return nil, NewJsonLdError(InvalidVocabMapping, "@vocab must be an absolute IRI in 1.0 mode") @@ -445,7 +448,7 @@ func (c *Context) parse(localContext interface{}, remoteContexts []string, parsi if err != nil { return nil, err } - result.values.vocab = &expandedVocab + result.Values.Vocab = &expandedVocab } else { return nil, NewJsonLdError(InvalidVocabMapping, "@vocab must be a string or null") } @@ -502,7 +505,7 @@ func (c *Context) CompactValue(activeProperty string, value map[string]interface propType := "" if td := c.GetTermDefinition(activeProperty); td != nil { - propType = td.typ + propType = td.Type } languageVal := "" @@ -614,7 +617,7 @@ func (c *Context) CompactValue(activeProperty string, value map[string]interface // processingMode returns true if the given version is compatible with the current processing mode func (c *Context) processingMode(version float64) bool { - mode := c.values.processingMode + mode := c.Values.processingMode if version >= 1.1 { if mode != "" { return mode >= fmt.Sprintf("json-ld-%v", version) @@ -649,7 +652,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri mapValue, isMap := value.(map[string]interface{}) idValue, hasID := mapValue["@id"] if value == nil || (isMap && hasID && idValue == nil) { - c.termDefinitions[term] = nil + c.TermDefinitions[term] = nil defined[term] = true return nil } @@ -686,9 +689,9 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri } // keep reference to previous mapping for potential `@protected` check - prevDefinition := c.termDefinitions[term] + prevDefinition := c.TermDefinitions[term] - delete(c.termDefinitions, term) + delete(c.TermDefinitions, term) // casting the value so it doesn't have to be done below everytime val := mapValue @@ -722,7 +725,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri colIndex := strings.Index(term, ":") termHasColon := colIndex > 0 - definition.reverse = false + definition.Reverse = false definition.termHasColon = termHasColon // 11) @@ -752,8 +755,8 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri return nil } - definition.id = id - definition.reverse = true + definition.ID = id + definition.Reverse = true } else if idValue, hasID := val["@id"]; hasID { // 13) idStr, isString := idValue.(string) if !isString { @@ -775,7 +778,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri if res == "@context" { return NewJsonLdError(InvalidKeywordAlias, "cannot alias @context") } - definition.id = res + definition.ID = res if iriLikeTermPattern.MatchString(term) { defined[term] = true @@ -808,7 +811,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri } prefix := !termHasColon && termHasSuffix && (simpleTerm || c.processingMode(1.0)) - definition.prefix = &prefix + definition.Prefix = &prefix } else { return NewJsonLdError(InvalidIRIMapping, "resulting IRI mapping should be a keyword, absolute IRI or blank node") @@ -817,7 +820,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri // 14) } - if definition.id == "" { + if definition.ID == "" { if termHasColon { prefix := term[0:colIndex] if _, containsPrefix := context[prefix]; containsPrefix { @@ -825,15 +828,15 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri return err } } - if termDef, hasTermDef := c.termDefinitions[prefix]; hasTermDef { + if termDef, hasTermDef := c.TermDefinitions[prefix]; hasTermDef { suffix := term[colIndex+1:] - definition.id = termDef.id + suffix + definition.ID = termDef.ID + suffix } else { - definition.id = term + definition.ID = term } // 15) - } else if vocabValue := c.values.vocab; vocabValue != nil { - definition.id = *vocabValue + term + } else if vocabValue := c.Values.Vocab; vocabValue != nil { + definition.ID = *vocabValue + term } else if term != "@type" { return NewJsonLdError(InvalidIRIMapping, "relative term definition without vocab mapping") } @@ -842,8 +845,8 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri // handle term protection valProtected, protectedFound := mapValue["@protected"] if (protectedFound && valProtected.(bool)) || (defined["@protected"] && !(protectedFound && !valProtected.(bool))) { - c.protected[term] = true - definition.protected = true + c.Protected[term] = true + definition.Protected = true } defined[term] = true @@ -878,7 +881,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri } // add @type to mapping - definition.typ = typeStr + definition.Type = typeStr } // 16) @@ -940,11 +943,11 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri if _, hasType := containerValueMap["@type"]; hasType { // if mapping does not have an @type, set it to @id - if definition.typ == "" { - definition.typ = "@id" + if definition.Type == "" { + definition.Type = "@id" } - if definition.typ != "@id" && definition.typ != "@vocab" { + if definition.Type != "@id" && definition.Type != "@vocab" { return NewJsonLdError(InvalidTypeMapping, "container: @type requires @type to be @id or @vocab") } @@ -975,7 +978,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri return NewJsonLdError(InvalidContainerMapping, "@set not allowed with @list") } - if definition.reverse { + if definition.Reverse { for key := range containerValueMap { if key != "@index" && key != "@set" { @@ -985,17 +988,17 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri } } - definition.container = container + definition.Container = container if term == "@type" { - definition.id = "@type" + definition.ID = "@type" } } // property indexing if indexVal, hasIndex := val["@index"]; hasIndex { _, hasContainer := val["@container"] - tdHasContainer := definition.container != nil + tdHasContainer := definition.Container != nil if !hasContainer || !tdHasContainer { return NewJsonLdError(InvalidTermDefinition, fmt.Sprintf("@index without @index in @container: %s on term %s", indexVal, term)) @@ -1005,13 +1008,13 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri return NewJsonLdError(InvalidTermDefinition, fmt.Sprintf("@index must expand to an IRI: %s on term %s", indexVal, term)) } - definition.index = indexStr + definition.Index = indexStr } // scoped contexts if ctxVal, hasCtx := val["@context"]; hasCtx { - definition.context = ctxVal - definition.hasContext = true + definition.Context = ctxVal + definition.HasContext = true } // 17) @@ -1019,11 +1022,11 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri if languageVal, hasLanguage := val["@language"]; hasLanguage && !hasType { if language, isString := languageVal.(string); isString { s := strings.ToLower(language) - definition.language = &s - definition.hasLanguage = true + definition.Language = &s + definition.HasLanguage = true } else if languageVal == nil { - definition.language = nil - definition.hasLanguage = true + definition.Language = nil + definition.HasLanguage = true } else { return NewJsonLdError(InvalidLanguageMapping, "@language must be a string or null") } @@ -1038,21 +1041,21 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri if !isBool { return NewJsonLdError(InvalidPrefixValue, "@context value for @prefix must be boolean") } - if IsKeyword(definition.id) { + if IsKeyword(definition.ID) { return NewJsonLdError(InvalidTermDefinition, "keywords may not be used as prefixes") } - definition.prefix = &prefix + definition.Prefix = &prefix } // handle direction if directionVal, hasDirection := val["@direction"]; hasDirection { if dir, isString := directionVal.(string); isString { s := strings.ToLower(dir) - definition.direction = &s - definition.hasDirection = true + definition.Direction = &s + definition.HasDirection = true } else if directionVal == nil { - definition.direction = nil - definition.hasDirection = true + definition.Direction = nil + definition.HasDirection = true } else { return NewJsonLdError(InvalidBaseDirection, fmt.Sprintf("direction must be null, 'ltr', or 'rtl', was %s on term %s", directionVal, term)) @@ -1066,20 +1069,20 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri return NewJsonLdError(InvalidNestValue, "@context @nest value must be a string which is not a keyword other than @nest") } - definition.nest = nest + definition.Nest = nest } // disallow aliasing @context and @preserve - if id := definition.id; id == "@context" || id == "@preserve" { + if id := definition.ID; id == "@context" || id == "@preserve" { return NewJsonLdError(InvalidKeywordAlias, "@context and @preserve cannot be aliased") } // Check for overriding protected terms if prevDefinition != nil { - if protectedVal := prevDefinition.protected; protectedVal && !overrideProtected { + if protectedVal := prevDefinition.Protected; protectedVal && !overrideProtected { // force new term to continue to be protected and see if the mappings would be equal - c.protected[term] = true - definition.protected = true + c.Protected[term] = true + definition.Protected = true if !DeepCompareTermDef(prevDefinition, definition, false) { return NewJsonLdError(ProtectedTermRedefinition, "invalid JSON-LD syntax; tried to redefine a protected term") } @@ -1087,7 +1090,7 @@ func (c *Context) createTermDefinition(context map[string]interface{}, term stri } // 18) - c.termDefinitions[term] = definition + c.TermDefinitions[term] = definition return nil } @@ -1131,9 +1134,9 @@ func (c *Context) ExpandIri(value string, relative bool, vocab bool, context map } } // 3) - if termDef, hasTermDef := c.termDefinitions[value]; vocab && hasTermDef { + if termDef, hasTermDef := c.TermDefinitions[value]; vocab && hasTermDef { if termDef != nil { - return termDef.id, nil + return termDef.ID, nil } return "", nil @@ -1161,9 +1164,9 @@ func (c *Context) ExpandIri(value string, relative bool, vocab bool, context map // 4.4) // If active context contains a term definition for prefix, return the result of concatenating // the IRI mapping associated with prefix and suffix. - termDef, hasPrefix := c.termDefinitions[prefix] - if hasPrefix && termDef.id != "" && termDef.prefix != nil && *termDef.prefix { - return termDef.id + suffix, nil + termDef, hasPrefix := c.TermDefinitions[prefix] + if hasPrefix && termDef.ID != "" && termDef.Prefix != nil && *termDef.Prefix { + return termDef.ID + suffix, nil } else if IsAbsoluteIri(value) { // Otherwise, if the value has the form of an absolute IRI, return it return value, nil @@ -1172,11 +1175,11 @@ func (c *Context) ExpandIri(value string, relative bool, vocab bool, context map } // 5) - if vocabValue := c.values.vocab; vocab && vocabValue != nil { + if vocabValue := c.Values.Vocab; vocab && vocabValue != nil { return *vocabValue + value, nil } else if relative { // 6) - baseValue := c.values.base + baseValue := c.Values.Base hasBase := baseValue != "" var base string if hasBase { @@ -1228,8 +1231,8 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool if relativeToVocab { if _, containsIRI := inverseCtx[iri]; containsIRI { var defaultLanguage string - langVal, hasLang := c.values.language, c.values.hasLanguage - if dir := c.values.direction; hasLang && dir != "" { + langVal, hasLang := c.Values.Language, c.Values.HasLanguage + if dir := c.Values.Direction; hasLang && dir != "" { defaultLanguage = fmt.Sprintf("%s_%s", langVal, dir) } else { if hasLang { @@ -1434,10 +1437,10 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool if err != nil { return "", err } - resultVal, hasResult := c.termDefinitions[result] + resultVal, hasResult := c.TermDefinitions[result] check := false if hasResult { - resultIDVal, hasResultID := resultVal.id, resultVal.id != "" + resultIDVal, hasResultID := resultVal.ID, resultVal.ID != "" check = hasResultID && idVal == resultIDVal } if check { @@ -1473,7 +1476,7 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool } // 3) - if vocabVal := c.values.vocab; vocabVal != nil { + if vocabVal := c.Values.Vocab; vocabVal != nil { // determine if vocab is a prefix of the iri vocab := *vocabVal // 3.1) @@ -1481,7 +1484,7 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool // use suffix as relative iri if it is not a term in the // active context suffix := iri[len(vocab):] - if _, hasSuffix := c.termDefinitions[suffix]; !hasSuffix { + if _, hasSuffix := c.TermDefinitions[suffix]; !hasSuffix { return suffix, nil } } @@ -1512,7 +1515,7 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool for i := len(partialMatches) - 1; i >= 0; i-- { entry := partialMatches[i] for _, term := range entry.terms { - termDefinitionAny, ok := c.termDefinitions[term] + termDefinitionAny, ok := c.TermDefinitions[term] if !ok { continue } @@ -1522,10 +1525,10 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool // 2. value is null, which means we're not compacting an @value, AND // the mapping matches the IRI curie := term + ":" + iri[len(entry.iri):] - prefix := termDefinitionAny.prefix - curieMapping, hasCurie := c.termDefinitions[curie] + prefix := termDefinitionAny.Prefix + curieMapping, hasCurie := c.TermDefinitions[curie] - isUsableCurie := prefix != nil && *prefix && (!hasCurie || value == nil && curieMapping.id == iri) + isUsableCurie := prefix != nil && *prefix && (!hasCurie || value == nil && curieMapping.ID == iri) // select curie if it is shorter or the same length but lexicographically // less than the current choice @@ -1541,9 +1544,9 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool // If iri could be confused with a compact IRI using a term in this context, // signal an error - for term, td := range c.termDefinitions { + for term, td := range c.TermDefinitions { if td != nil { - prefix := td.prefix + prefix := td.Prefix if prefix != nil && *prefix && strings.HasPrefix(iri, term+":") { return "", NewJsonLdError(IRIConfusedWithPrefix, fmt.Sprintf("Absolute IRI %s confused with prefix %s", iri, term)) } @@ -1552,7 +1555,7 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool // compact IRI relative to base if !relativeToVocab { - return RemoveBase(c.values.base, iri), nil + return RemoveBase(c.Values.Base, iri), nil } // return IRI as is @@ -1570,11 +1573,11 @@ func (c *Context) CompactIri(iri string, value interface{}, relativeToVocab bool func (c *Context) GetPrefixes(onlyCommonPrefixes bool) map[string]string { prefixes := make(map[string]string) - for term, termDefinition := range c.termDefinitions { - if strings.Contains(term, ":") || termDefinition == nil || termDefinition.id == "" { + for term, termDefinition := range c.TermDefinitions { + if strings.Contains(term, ":") || termDefinition == nil || termDefinition.ID == "" { continue } - id := termDefinition.id + id := termDefinition.ID if strings.HasPrefix(term, "@") || strings.HasPrefix(id, "@") { continue } @@ -1601,20 +1604,20 @@ func (c *Context) GetInverse() map[string]interface{} { // 2) defaultLanguage := "@none" - if c.values.hasLanguage { - defaultLanguage = c.values.language + if c.Values.HasLanguage { + defaultLanguage = c.Values.Language } // create term selections for each mapping in the context, ordered by // shortest and then lexicographically least - terms := GetKeys(c.termDefinitions) + terms := GetKeys(c.TermDefinitions) sort.Sort(ShortestLeast(terms)) // variables for building fast CURIE map irisToTerms := make(map[string][]string, 0) for _, term := range terms { - definition := c.termDefinitions[term] + definition := c.TermDefinitions[term] // 3.1) if definition == nil { continue @@ -1622,10 +1625,10 @@ func (c *Context) GetInverse() map[string]interface{} { // 3.2) var containerJoin string // this implementation was adapted from pyLD - if definition.container == nil { + if definition.Container == nil { containerJoin = "@none" // see Ruby, as_set? } else { - container := definition.container + container := definition.Container strList := make([]string, len(container)) copy(strList, container) sort.Strings(strList) @@ -1633,7 +1636,7 @@ func (c *Context) GetInverse() map[string]interface{} { } // 3.3) - iri := definition.id + iri := definition.ID // 3.4 + 3.5) var containerMap map[string]interface{} @@ -1680,12 +1683,12 @@ func (c *Context) GetInverse() map[string]interface{} { typeLanguageMap = typeLanguageMapVal.(map[string]interface{}) } - langVal, hasLang := definition.language, definition.hasLanguage - dirVal, hasDir := definition.direction, definition.hasDirection - typeVal := definition.typ + langVal, hasLang := definition.Language, definition.HasLanguage + dirVal, hasDir := definition.Direction, definition.HasDirection + typeVal := definition.Type // 3.8) - if definition.reverse { + if definition.Reverse { typeMap := typeLanguageMap["@type"].(map[string]interface{}) if _, hasValue := typeMap["@reverse"]; !hasValue { typeMap["@reverse"] = term @@ -1740,7 +1743,7 @@ func (c *Context) GetInverse() map[string]interface{} { if _, hasLang := languageMap[dir]; !hasLang { languageMap[dir] = term } - } else if defDir := c.values.direction; defDir != "" { + } else if defDir := c.Values.Direction; defDir != "" { languageMap := typeLanguageMap["@language"].(map[string]interface{}) typeMap := typeLanguageMap["@type"].(map[string]interface{}) var langDir string @@ -1862,9 +1865,9 @@ func (c *Context) SelectTerm(iri string, containers []string, typeLanguage strin // GetContainer retrieves container mapping for the given property. func (c *Context) GetContainer(property string) []string { - td, ok := c.termDefinitions[property] - if ok && td != nil && td.container != nil { - return td.container + td, ok := c.TermDefinitions[property] + if ok && td != nil && td.Container != nil { + return td.Container } return []string{} @@ -1872,9 +1875,9 @@ func (c *Context) GetContainer(property string) []string { // GetContainer retrieves container mapping for the given property. func (c *Context) HasContainerMapping(property string, val string) bool { - td, ok := c.termDefinitions[property] - if ok && td != nil && td.container != nil { - for _, container := range td.container { + td, ok := c.TermDefinitions[property] + if ok && td != nil && td.Container != nil { + for _, container := range td.Container { if container == val { return true } @@ -1890,34 +1893,31 @@ func (c *Context) IsReverseProperty(property string) bool { if td == nil { return false } - return td.reverse + return td.Reverse } // GetTypeMapping returns type mapping for the given property func (c *Context) GetTypeMapping(property string) string { // default type - rval := c.values.typ - td := c.GetTermDefinition(property) - if td != nil && td.typ != "" { - return td.typ + if td != nil && td.Type != "" { + return td.Type } - - return rval + return "" } // GetLanguageMapping returns language mapping for the given property func (c *Context) GetLanguageMapping(property string) string { td := c.GetTermDefinition(property) - if td != nil && td.hasLanguage { - if td.language != nil { - return *td.language + if td != nil && td.HasLanguage { + if td.Language != nil { + return *td.Language } return "" } - if c.values.hasLanguage { - return c.values.language + if c.Values.HasLanguage { + return c.Values.Language } return "" @@ -1926,14 +1926,14 @@ func (c *Context) GetLanguageMapping(property string) string { // GetDirectionMapping returns direction mapping for the given property func (c *Context) GetDirectionMapping(property string) string { td := c.GetTermDefinition(property) - if td != nil && td.hasDirection { - if td.direction != nil { - return *td.direction + if td != nil && td.HasDirection { + if td.Direction != nil { + return *td.Direction } return "" } - if defaultDir := c.values.direction; defaultDir != "" { + if defaultDir := c.Values.Direction; defaultDir != "" { return defaultDir } @@ -1942,7 +1942,7 @@ func (c *Context) GetDirectionMapping(property string) string { // GetTermDefinition returns a term definition for the given key func (c *Context) GetTermDefinition(key string) *TermDefinition { - if value, ok := c.termDefinitions[key]; ok { + if value, ok := c.TermDefinitions[key]; ok { return value } return nil @@ -1956,7 +1956,7 @@ func (c *Context) ExpandValue(activeProperty string, value interface{}) (interfa // If the active property has a type mapping in active context that is @id, return a new JSON object // containing a single key-value pair where the key is @id and the value is the result of using // the IRI Expansion algorithm, passing active context, value, and true for document relative. - if td != nil && td.typ == "@id" { + if td != nil && td.Type == "@id" { if strVal, isString := value.(string); isString { var err error rval["@id"], err = c.ExpandIri(strVal, true, false, nil, nil) @@ -1971,7 +1971,7 @@ func (c *Context) ExpandValue(activeProperty string, value interface{}) (interfa // If active property has a type mapping in active context that is @vocab, return a new JSON object // containing a single key-value pair where the key is @id and the value is the result of using // the IRI Expansion algorithm, passing active context, value, true for vocab, and true for document relative. - if td != nil && td.typ == "@vocab" { + if td != nil && td.Type == "@vocab" { if strVal, isString := value.(string); isString { var err error rval["@id"], err = c.ExpandIri(strVal, true, true, nil, nil) @@ -1987,26 +1987,26 @@ func (c *Context) ExpandValue(activeProperty string, value interface{}) (interfa // 3) rval["@value"] = value // 4) - if td != nil && td.typ != "" && td.typ != "@id" && td.typ != "@vocab" && - td.typ != "@none" { - rval["@type"] = td.typ + if td != nil && td.Type != "" && td.Type != "@id" && td.Type != "@vocab" && + td.Type != "@none" { + rval["@type"] = td.Type } else if _, isString := value.(string); isString { // 5.1) - if containsLang := td != nil && td.hasLanguage; containsLang { - langVal := td.language + if containsLang := td != nil && td.HasLanguage; containsLang { + langVal := td.Language if langVal != nil { rval["@language"] = *langVal } - } else if defaultLangVal := c.values.language; c.values.hasLanguage { + } else if defaultLangVal := c.Values.Language; c.Values.HasLanguage { rval["@language"] = defaultLangVal } - if containsDir := td != nil && td.hasDirection; containsDir { - dirVal := td.direction + if containsDir := td != nil && td.HasDirection; containsDir { + dirVal := td.Direction if dirVal != nil { rval["@direction"] = *dirVal } - } else if dirVal := c.values.direction; dirVal != "" { + } else if dirVal := c.Values.Direction; dirVal != "" { rval["@direction"] = dirVal } } @@ -2017,32 +2017,32 @@ func (c *Context) ExpandValue(activeProperty string, value interface{}) (interfa func (c *Context) Serialize() (map[string]interface{}, error) { ctx := make(map[string]interface{}) - baseVal := c.values.base + baseVal := c.Values.Base hasBase := baseVal != "" if hasBase && baseVal != c.options.Base { ctx["@base"] = baseVal } - if versionVal := c.values.version; versionVal != nil { + if versionVal := c.Values.Version; versionVal != nil { ctx["@version"] = *versionVal } - if langVal := c.values.language; c.values.hasLanguage { + if langVal := c.Values.Language; c.Values.HasLanguage { ctx["@language"] = langVal } - if dirVal := c.values.direction; dirVal != "" { + if dirVal := c.Values.Direction; dirVal != "" { ctx["@direction"] = dirVal } - if vocabVal := c.values.vocab; vocabVal != nil { + if vocabVal := c.Values.Vocab; vocabVal != nil { ctx["@vocab"] = *vocabVal } - for term, definition := range c.termDefinitions { + for term, definition := range c.TermDefinitions { // Note: definitionVal may be nil for terms which are set to be ignored // (see the definition for null value in JSON-LD spec) - langVal, hasLang := definition.language, definition.hasLanguage - containerVal, hasContainer := definition.container, definition.container != nil - typeMapping := definition.typ - if !hasLang && !hasContainer && typeMapping == "" && !definition.reverse { + langVal, hasLang := definition.Language, definition.HasLanguage + containerVal, hasContainer := definition.Container, definition.Container != nil + typeMapping := definition.Type + if !hasLang && !hasContainer && typeMapping == "" && !definition.Reverse { var cid interface{} - id := definition.id + id := definition.ID if id == "" { cid = nil ctx[term] = cid @@ -2063,12 +2063,12 @@ func (c *Context) Serialize() (map[string]interface{}, error) { } } else { defn := make(map[string]interface{}) - id := definition.id + id := definition.ID cid, err := c.CompactIri(id, nil, false, false) if err != nil { return nil, err } - reverseProperty := definition.reverse + reverseProperty := definition.Reverse if !(term == cid && !reverseProperty) { if reverseProperty { defn["@reverse"] = cid