// this shouldn't be a // valid iri/bnode i // hope! // TODO: fill with default namespaces public virtual object Call(RdfDataset dataset) { foreach (var e in dataset.GetNamespaces().GetEnumerableSelf ()) { availableNamespaces[e.Value] = e.Key; } usedNamespaces = new HashSet <string>(); var refs = new JObject(); var ttl = new JObject(); foreach (var graphName in dataset.Keys) { var localGraphName = graphName; var triples = dataset.GetQuads(localGraphName); if ("@default".Equals(localGraphName)) { localGraphName = null; } // http://www.w3.org/TR/turtle/#unlabeled-bnodes // TODO: implement nesting for unlabled nodes // map of what the output should look like // subj (or [ if bnode) > pred > obj // > obj (set ref if IRI) // > pred > obj (set ref if bnode) // subj > etc etc etc // subjid -> [ ref, ref, ref ] var prevSubject = string.Empty; var prevPredicate = string.Empty; JObject thisSubject = null; JArray thisPredicate = null; foreach (var triple in triples) { var subject = triple.GetSubject().GetValue(); var predicate = triple.GetPredicate().GetValue(); if (prevSubject.Equals(subject)) { if (prevPredicate.Equals(predicate)) { } else { // nothing to do // new predicate if (thisSubject.ContainsKey(predicate)) { thisPredicate = (JArray)thisSubject[predicate]; } else { thisPredicate = new JArray(); thisSubject[predicate] = thisPredicate; } prevPredicate = predicate; } } else { // new subject if (ttl.ContainsKey(subject)) { thisSubject = (JObject)ttl[subject]; } else { thisSubject = new JObject(); ttl[subject] = thisSubject; } if (thisSubject.ContainsKey(predicate)) { thisPredicate = (JArray)thisSubject[predicate]; } else { thisPredicate = new JArray(); thisSubject[predicate] = thisPredicate; } prevSubject = subject; prevPredicate = predicate; } if (triple.GetObject().IsLiteral()) { thisPredicate.Add(triple.GetObject()); } else { var o = triple.GetObject().GetValue(); if (o.StartsWith("_:")) { // add ref to o if (!refs.ContainsKey(o)) { refs[o] = new JArray(); } ((JArray)refs[o]).Add(thisPredicate); } thisPredicate.Add(o); } } } var collections = new JObject(); var subjects = new JArray(ttl.GetKeys()); // find collections foreach (string subj in subjects) { var preds = (JObject)ttl[subj]; if (preds != null && preds.ContainsKey(JsonLdConsts.RdfFirst)) { var col = new JArray(); collections[subj] = col; while (true) { var first = (JArray)Collections.Remove(preds, JsonLdConsts.RdfFirst); var o = first[0]; col.Add(o); // refs if (refs.ContainsKey((string)o)) { ((JArray)refs[(string)o]).Remove(first); ((JArray)refs[(string)o]).Add(col); } var next = (string)Collections.Remove(preds, JsonLdConsts.RdfRest)[0 ]; if (JsonLdConsts.RdfNil.Equals(next)) { break; } // if collections already contains a value for "next", add // it to this col and break out if (collections.ContainsKey(next)) { Collections.AddAll(col, (JArray)Collections.Remove(collections, next)); break; } preds = (JObject)Collections.Remove(ttl, next); Collections.Remove(refs, next); } } } // process refs (nesting referenced bnodes if only one reference to them // in the whole graph) foreach (var id in refs.GetKeys()) { // skip items if there is more than one reference to them in the // graph if (((JArray)refs[id]).Count > 1) { continue; } // otherwise embed them into the referenced location var @object = Collections.Remove(ttl, id); if (collections.ContainsKey(id)) { @object = new JObject(); var tmp = new JArray(); tmp.Add(Collections.Remove(collections, id)); ((JObject)@object)[ColsKey] = tmp; } var predicate = (JArray)refs[id][0]; // replace the one bnode ref with the object predicate[predicate.LastIndexOf(id)] = @object; } // replace the rest of the collections foreach (var id_1 in collections.GetKeys()) { var subj_1 = (JObject)ttl[id_1]; if (!subj_1.ContainsKey(ColsKey)) { subj_1[ColsKey] = new JArray(); } ((JArray)subj_1[ColsKey]).Add(collections[id_1]); } // build turtle output var output = GenerateTurtle(ttl, 0, 0, false); var prefixes = string.Empty; foreach (var prefix in usedNamespaces) { var name = availableNamespaces[prefix]; prefixes += "@prefix " + name + ": <" + prefix + "> .\n"; } return((string.Empty.Equals(prefixes) ? string.Empty : prefixes + "\n") + output); }
public virtual object Call(RdfDataset dataset) { return(RdfDatasetUtils.ToNQuads(dataset)); }
/// <exception cref="JsonLD.Core.JsonLdError"></exception> public virtual RdfDataset Parse(JToken input) { if (!(input.Type == JTokenType.String)) { throw new JsonLdError(JsonLdError.Error.InvalidInput, "Invalid input; Triple RDF Parser requires a string input" ); } var result = new RdfDataset(); var state = new State(this, (string)input); while (!string.Empty.Equals(state.line)) { // check if line is a directive var match = Regex.Directive.Matcher(state.line); if (match.Find()) { if (match.Group(1) != null || match.Group(4) != null) { var ns = match.Group(1) != null?match.Group(1) : match.Group(4); var iri = match.Group(1) != null?match.Group(2) : match.Group(5); if (!iri.Contains(":")) { iri = state.baseIri + iri; } iri = RdfDatasetUtils.Unescape(iri); ValidateIRI(state, iri); state.namespaces[ns] = iri; result.SetNamespace(ns, iri); } else { var @base = match.Group(3) != null?match.Group(3) : match.Group(6); @base = RdfDatasetUtils.Unescape(@base); ValidateIRI(state, @base); if ([email protected](":")) { state.baseIri = state.baseIri + @base; } else { state.baseIri = @base; } } state.AdvanceLinePosition(match.Group(0).Length); continue; } if (state.curSubject == null) { // we need to match a subject match = Regex.Subject.Matcher(state.line); if (match.Find()) { string iri; if (match.Group(1) != null) { // matched IRI iri = RdfDatasetUtils.Unescape(match.Group(1)); if (!iri.Contains(":")) { iri = state.baseIri + iri; } } else { if (match.Group(2) != null) { // matched NS:NAME var ns = match.Group(2); var name = UnescapeReserved(match.Group(3)); iri = state.ExpandIRI(ns, name); } else { if (match.Group(4) != null) { // match ns: only iri = state.ExpandIRI(match.Group(4), string.Empty); } else { if (match.Group(5) != null) { iri = state.namer.GetName(match.Group(0).Trim()); } else { iri = state.namer.GetName(); } } } } // make sure IRI still matches an IRI after escaping ValidateIRI(state, iri); state.curSubject = iri; state.AdvanceLinePosition(match.Group(0).Length); } else { // handle blank nodes if (state.line.StartsWith("[")) { var bnode = state.namer.GetName(); state.AdvanceLinePosition(1); state.Push(); state.curSubject = bnode; } else { // handle collections if (state.line.StartsWith("(")) { var bnode = state.namer.GetName(); // so we know we want a predicate if the collection close // isn't followed by a subject end state.curSubject = bnode; state.AdvanceLinePosition(1); state.Push(); state.curSubject = bnode; state.curPredicate = JsonLdConsts.RdfFirst; } else { // make sure we have a subject already throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; missing expected subject. {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } } } } if (state.curPredicate == null) { // match predicate match = Regex.Predicate.Matcher(state.line); if (match.Find()) { var iri = string.Empty; if (match.Group(1) != null) { // matched IRI iri = RdfDatasetUtils.Unescape(match.Group(1)); if (!iri.Contains(":")) { iri = state.baseIri + iri; } } else { if (match.Group(2) != null) { // matched NS:NAME var ns = match.Group(2); var name = UnescapeReserved(match.Group(3)); iri = state.ExpandIRI(ns, name); } else { if (match.Group(4) != null) { iri = state.ExpandIRI(match.Group(4), string.Empty); } else { iri = JsonLdConsts.RdfType; } } } ValidateIRI(state, iri); state.curPredicate = iri; state.AdvanceLinePosition(match.Group(0).Length); } else { throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; missing expected predicate. {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } } // expecting bnode or object // match BNODE values if (state.line.StartsWith("[")) { var bnode = state.namer.GetName(); result.AddTriple(state.curSubject, state.curPredicate, bnode); state.AdvanceLinePosition(1); // check for anonymous objects if (state.line.StartsWith("]")) { state.AdvanceLinePosition(1); } else { // next we expect a statement or object separator // otherwise we're inside the blank node state.Push(); state.curSubject = bnode; // next we expect a predicate continue; } } else { // match collections if (state.line.StartsWith("(")) { state.AdvanceLinePosition(1); // check for empty collection if (state.line.StartsWith(")")) { state.AdvanceLinePosition(1); result.AddTriple(state.curSubject, state.curPredicate, JsonLdConsts.RdfNil); } else { // next we expect a statement or object separator // otherwise we're inside the collection var bnode = state.namer.GetName(); result.AddTriple(state.curSubject, state.curPredicate, bnode); state.Push(); state.curSubject = bnode; state.curPredicate = JsonLdConsts.RdfFirst; continue; } } else { // match object match = Regex.Object.Matcher(state.line); if (match.Find()) { string iri = null; if (match.Group(1) != null) { // matched IRI iri = RdfDatasetUtils.Unescape(match.Group(1)); if (!iri.Contains(":")) { iri = state.baseIri + iri; } } else { if (match.Group(2) != null) { // matched NS:NAME var ns = match.Group(2); var name = UnescapeReserved(match.Group(3)); iri = state.ExpandIRI(ns, name); } else { if (match.Group(4) != null) { // matched ns: iri = state.ExpandIRI(match.Group(4), string.Empty); } else { if (match.Group(5) != null) { iri = state.namer.GetName(match.Group(0).Trim()); } } } } if (iri != null) { ValidateIRI(state, iri); // we have a object result.AddTriple(state.curSubject, state.curPredicate, iri); } else { // we have a literal var value = match.Group(6); string lang = null; string datatype = null; if (value != null) { // we have a string literal value = UnquoteString(value); value = RdfDatasetUtils.Unescape(value); lang = match.Group(7); if (lang == null) { if (match.Group(8) != null) { datatype = RdfDatasetUtils.Unescape(match.Group(8)); if (!datatype.Contains(":")) { datatype = state.baseIri + datatype; } ValidateIRI(state, datatype); } else { if (match.Group(9) != null) { datatype = state.ExpandIRI(match.Group(9), UnescapeReserved(match.Group(10))); } else { if (match.Group(11) != null) { datatype = state.ExpandIRI(match.Group(11), string.Empty); } } } } else { datatype = JsonLdConsts.RdfLangstring; } } else { if (match.Group(12) != null) { // integer literal value = match.Group(12); datatype = JsonLdConsts.XsdDouble; } else { if (match.Group(13) != null) { // decimal literal value = match.Group(13); datatype = JsonLdConsts.XsdDecimal; } else { if (match.Group(14) != null) { // double literal value = match.Group(14); datatype = JsonLdConsts.XsdInteger; } else { if (match.Group(15) != null) { // boolean literal value = match.Group(15); datatype = JsonLdConsts.XsdBoolean; } } } } } result.AddTriple(state.curSubject, state.curPredicate, value, datatype, lang); } state.AdvanceLinePosition(match.Group(0).Length); } else { throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; missing expected object or blank node. {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } } } // close collection var collectionClosed = false; while (state.line.StartsWith(")")) { if (!JsonLdConsts.RdfFirst.Equals(state.curPredicate)) { throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; unexpected ). {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } result.AddTriple(state.curSubject, JsonLdConsts.RdfRest, JsonLdConsts.RdfNil); state.Pop(); state.AdvanceLinePosition(1); collectionClosed = true; } var expectDotOrPred = false; // match end of bnode if (state.line.StartsWith("]")) { var bnode = state.curSubject; state.Pop(); state.AdvanceLinePosition(1); if (state.curSubject == null) { // this is a bnode as a subject and we // expect either a . or a predicate state.curSubject = bnode; expectDotOrPred = true; } } // match list separator if (!expectDotOrPred && state.line.StartsWith(",")) { state.AdvanceLinePosition(1); // now we expect another object/bnode continue; } // match predicate end if (!expectDotOrPred) { while (state.line.StartsWith(";")) { state.curPredicate = null; state.AdvanceLinePosition(1); // now we expect another predicate, or a dot expectDotOrPred = true; } } if (state.line.StartsWith(".")) { if (state.expectingBnodeClose) { throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; missing expected )\"]\". {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } state.curSubject = null; state.curPredicate = null; state.AdvanceLinePosition(1); // this can now be the end of the document. continue; } if (expectDotOrPred) { continue; } // if we're in a collection if (JsonLdConsts.RdfFirst.Equals(state.curPredicate)) { var bnode = state.namer.GetName(); result.AddTriple(state.curSubject, JsonLdConsts.RdfRest, bnode); state.curSubject = bnode; continue; } if (collectionClosed) { continue; } // if we get here, we're missing a close statement throw new JsonLdError(JsonLdError.Error.ParseError, "Error while parsing Turtle; missing expected \"]\" \",\" \";\" or \".\". {line: " + state.lineNumber + "position: " + state.linePosition + "}"); } return(result); }