/// <summary> /// Embeds values for the given subject and property into the given output /// during the framing algorithm. /// </summary> /// <remarks> /// Embeds values for the given subject and property into the given output /// during the framing algorithm. /// </remarks> /// <param name="state">the current framing state.</param> /// <param name="element">the subject.</param> /// <param name="property">the property.</param> /// <param name="output">the output.</param> private void EmbedValues(JsonLdApi.FramingContext state, JObject element, string property, JToken output) { // embed subject properties in output JArray objects = (JArray)element[property]; foreach (JToken o in objects) { var eachObj = o; if (eachObj is JObject && ((JObject)eachObj).ContainsKey("@list")) { JObject list = new JObject { { "@list", new JArray() } }; if (output is JArray) { ((JArray)output).Add(list); } else { output[property] = new JArray(list); } EmbedValues(state, (JObject)eachObj, "@list", list["@list"]); } // handle subject reference else if (JsonLdUtils.IsNodeReference(eachObj)) { string sid = (string)((JObject)eachObj)["@id"]; // embed full subject if isn't already embedded if (!state.embeds.ContainsKey(sid)) { // add embed JsonLdApi.EmbedNode embed = new JsonLdApi.EmbedNode(this); embed.parent = output; embed.property = property; state.embeds[sid] = embed; // recurse into subject eachObj = new JObject(); JObject s = (JObject)this.nodeMap[sid]; if (s == null) { s = new JObject(); s["@id"] = sid; } foreach (string prop in s.GetKeys()) { // copy keywords if (JsonLdUtils.IsKeyword(prop)) { ((JObject)eachObj)[prop] = JsonLdUtils.Clone(s[prop]); continue; } EmbedValues(state, s, prop, eachObj); } } AddFrameOutput(state, output, property, eachObj); } else { // copy non-subject value AddFrameOutput(state, output, property, JsonLdUtils.Clone(eachObj)); } } }
/// <summary>Frames subjects according to the given frame.</summary> /// <remarks>Frames subjects according to the given frame.</remarks> /// <param name="state">the current framing state.</param> /// <param name="subjects">the subjects to filter.</param> /// <param name="frame">the frame.</param> /// <param name="parent">the parent subject or top-level array.</param> /// <param name="property">the parent property, initialized to null.</param> /// <exception cref="JSONLDProcessingError">JSONLDProcessingError</exception> /// <exception cref="JsonLD.Core.JsonLdError"></exception> private void Frame(JsonLdApi.FramingContext state, JObject nodes , JObject frame, JToken parent, string property) { // filter out subjects that match the frame JObject matches = FilterNodes(state, nodes, frame); // get flags for current frame bool embedOn = GetFrameFlag(frame, "@embed", state.embed); bool explicitOn = GetFrameFlag(frame, "@explicit", state.@explicit); // add matches to output JArray ids = new JArray(matches.GetKeys()); ids.SortInPlace(); foreach (string id in ids) { if (property == null) { state.embeds = new Dictionary<string, JsonLdApi.EmbedNode>(); } // start output JObject output = new JObject(); output["@id"] = id; // prepare embed meta info JsonLdApi.EmbedNode embeddedNode = new JsonLdApi.EmbedNode(this); embeddedNode.parent = parent; embeddedNode.property = property; // if embed is on and there is an existing embed if (embedOn && state.embeds.ContainsKey(id)) { JsonLdApi.EmbedNode existing = state.embeds[id]; embedOn = false; if (existing.parent is JArray) { foreach (JToken p in (JArray)(existing.parent)) { if (JsonLdUtils.CompareValues(output, p)) { embedOn = true; break; } } } else { // existing embed's parent is an object if (((JObject)existing.parent).ContainsKey(existing.property)) { foreach (JToken v in (JArray)((JObject)existing.parent)[existing.property]) { if (v is JObject && ((JObject)v)["@id"].SafeCompare(id)) { embedOn = true; break; } } } } // existing embed has already been added, so allow an overwrite if (embedOn) { RemoveEmbed(state, id); } } // not embedding, add output without any other properties if (!embedOn) { AddFrameOutput(state, parent, property, output); } else { // add embed meta info state.embeds[id] = embeddedNode; // iterate over subject properties JObject element = (JObject)matches[id]; JArray props = new JArray(element.GetKeys()); props.SortInPlace(); foreach (string prop in props) { // copy keywords to output if (JsonLdUtils.IsKeyword(prop)) { output[prop] = JsonLdUtils.Clone(element[prop]); continue; } // if property isn't in the frame if (!frame.ContainsKey(prop)) { // if explicit is off, embed values if (!explicitOn) { EmbedValues(state, element, prop, output); } continue; } // add objects JArray value = (JArray)element[prop]; foreach (JToken item in value) { // recurse into list if ((item is JObject) && ((JObject)item).ContainsKey("@list")) { // add empty list JObject list = new JObject(); list["@list"] = new JArray(); AddFrameOutput(state, output, prop, list); // add list objects foreach (JToken listitem in (JArray)((JObject)item)["@list" ]) { // recurse into subject reference if (JsonLdUtils.IsNodeReference(listitem)) { JObject tmp = new JObject(); string itemid = (string)((IDictionary<string, JToken>)listitem)["@id"]; // TODO: nodes may need to be node_map, // which is global tmp[itemid] = this.nodeMap[itemid]; Frame(state, tmp, (JObject)((JArray)frame[prop])[0], list , "@list"); } else { // include other values automatcially (TODO: // may need JsonLdUtils.clone(n)) AddFrameOutput(state, list, "@list", listitem); } } } else { // recurse into subject reference if (JsonLdUtils.IsNodeReference(item)) { JObject tmp = new JObject(); string itemid = (string)((JObject)item)["@id"]; // TODO: nodes may need to be node_map, which is // global tmp[itemid] = this.nodeMap[itemid]; Frame(state, tmp, (JObject)((JArray)frame[prop])[0], output , prop); } else { // include other values automatically (TODO: may // need JsonLdUtils.clone(o)) AddFrameOutput(state, output, prop, item); } } } } // handle defaults props = new JArray(frame.GetKeys()); props.SortInPlace(); foreach (string prop_1 in props) { // skip keywords if (JsonLdUtils.IsKeyword(prop_1)) { continue; } JArray pf = (JArray)frame[prop_1]; JObject propertyFrame = pf.Count > 0 ? (JObject)pf[0] : null; if (propertyFrame == null) { propertyFrame = new JObject(); } bool omitDefaultOn = GetFrameFlag(propertyFrame, "@omitDefault", state.omitDefault ); if (!omitDefaultOn && !output.ContainsKey(prop_1)) { JToken def = "@null"; if (propertyFrame.ContainsKey("@default")) { def = JsonLdUtils.Clone(propertyFrame["@default"]); } if (!(def is JArray)) { JArray tmp = new JArray(); tmp.Add(def); def = tmp; } JObject tmp1 = new JObject(); tmp1["@preserve"] = def; JArray tmp2 = new JArray(); tmp2.Add(tmp1); output[prop_1] = tmp2; } } // add output to parent AddFrameOutput(state, parent, property, output); } } }