-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow @context to appear anywhere in JSON-LD document
- Loading branch information
Greg McFall
committed
Nov 5, 2013
1 parent
4ce5f6d
commit 7ac9856
Showing
12 changed files
with
882 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
272 changes: 272 additions & 0 deletions
272
semantictools-jsonld/src/main/java/org/semantictools/jsonld/impl/LdTreeReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
package org.semantictools.jsonld.impl; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.Iterator; | ||
import java.util.Map.Entry; | ||
|
||
import org.codehaus.jackson.JsonNode; | ||
import org.codehaus.jackson.JsonParseException; | ||
import org.codehaus.jackson.JsonParser.Feature; | ||
import org.codehaus.jackson.map.ObjectMapper; | ||
import org.codehaus.jackson.node.ArrayNode; | ||
import org.codehaus.jackson.node.ObjectNode; | ||
import org.semantictools.jsonld.LdContainerType; | ||
import org.semantictools.jsonld.LdContext; | ||
import org.semantictools.jsonld.LdField; | ||
import org.semantictools.jsonld.LdLiteral; | ||
import org.semantictools.jsonld.LdNode; | ||
import org.semantictools.jsonld.LdObject; | ||
import org.semantictools.jsonld.LdTerm; | ||
import org.semantictools.jsonld.io.LdContextReader; | ||
import org.semantictools.jsonld.io.LdParseException; | ||
import org.semantictools.jsonld.io.LdParser; | ||
|
||
public class LdTreeReader implements LdParser { | ||
private LdContextReader contextReader; | ||
|
||
public LdTreeReader(LdContextReader contextReader) { | ||
this.contextReader = contextReader; | ||
} | ||
|
||
@Override | ||
public LdNode parse(InputStream input) throws LdParseException, IOException { | ||
|
||
ObjectMapper mapper = new ObjectMapper(); | ||
mapper.configure(Feature.ALLOW_COMMENTS, true); | ||
JsonNode node = mapper.readTree(input); | ||
if (! (node instanceof ObjectNode)) { | ||
throw new LdParseException("JSON-LD document must have an object as the root element"); | ||
} | ||
|
||
LdNode result = parseNode(node, null, null, null); | ||
|
||
return result; | ||
} | ||
|
||
LdNode parseNode(JsonNode node, LdObjectImpl parent, LdTerm term, LdField owner) throws JsonParseException, IOException, LdParseException { | ||
LdNode result = null; | ||
|
||
if ( node instanceof ObjectNode) { | ||
result = parseObject((ObjectNode) node, parent, owner); | ||
} else if (node.isBoolean()) { | ||
LdLiteral literal = new LdLiteral(); | ||
literal.setBooleanValue(node.getBooleanValue()); | ||
result = literal; | ||
} else if (node.isFloatingPointNumber()) { | ||
LdLiteral literal = new LdLiteral(); | ||
literal.setDoubleValue(node.getDoubleValue()); | ||
result = literal; | ||
} else if (node.isLong() || node.isInt()) { | ||
LdLiteral literal = new LdLiteral(); | ||
literal.setLongValue(node.getLongValue()); | ||
result = literal; | ||
} else if (node.isTextual()) { | ||
result = parseStringNode(node.getTextValue(), parent, term); | ||
} else if (node.isArray()) { | ||
result = parseArray((ArrayNode)node, parent, term, owner); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private LdNode parseStringNode(String text, LdObject parent, LdTerm term) throws JsonParseException, IOException { | ||
LdNode result = null; | ||
String type = (term==null) ? null : term.getRawTypeIRI(); | ||
if ("@id".equals(type)) { | ||
LdContext context = (parent==null) ? null : parent.getContext(); | ||
LdObjectImpl object = new LdObjectImpl(context); | ||
object.setId(text); | ||
result = object; | ||
} else { | ||
|
||
LdLiteral literal = new LdLiteral(); | ||
literal.setStringValue(text); | ||
result = literal; | ||
|
||
} | ||
return result; | ||
} | ||
|
||
private LdNode parseArray(ArrayNode array, LdObjectImpl parent, LdTerm term, LdField owner) throws JsonParseException, IOException, LdParseException { | ||
LdList list = new LdList(LdContainerType.SET); | ||
parseElements(array, term, parent, list, owner); | ||
|
||
return list; | ||
} | ||
|
||
private void parseElements(ArrayNode array, LdTerm term, LdObjectImpl parent, LdList list, | ||
LdField field) throws JsonParseException, IOException, LdParseException { | ||
|
||
for (int i=0; i<array.size(); i++) { | ||
JsonNode node = array.get(i); | ||
list.add(parseNode(node, parent, term, field)); | ||
} | ||
} | ||
|
||
|
||
private LdNode parseObject(ObjectNode node, LdObjectImpl parent, LdField owner) throws LdParseException, JsonParseException, IOException { | ||
JsonNode value = node.get("@value"); | ||
if (value != null) { | ||
return parseExtendedValue(node, parent, owner); | ||
} | ||
|
||
JsonNode contextNode = node.get("@context"); | ||
LdContext context = null; | ||
if (contextNode == null) { | ||
context = parent.getContext(); | ||
} | ||
if (contextNode != null) { | ||
try { | ||
context = contextReader.parseContext(contextNode); | ||
|
||
} catch (Exception e) { | ||
throw new LdParseException(e); | ||
} | ||
} | ||
LdObjectImpl object = new LdObjectImpl(context); | ||
object.setOwner(owner); | ||
parseFields(node, object, (ObjectNode)node, parent); | ||
return object; | ||
} | ||
|
||
private LdNode parseExtendedValue(ObjectNode object, LdObjectImpl parent, | ||
LdField owner) { | ||
LdLiteral literal = new LdLiteral(); | ||
|
||
Iterator<Entry<String,JsonNode>> sequence = object.getFields(); | ||
while (sequence.hasNext()) { | ||
Entry<String,JsonNode> entry = sequence.next(); | ||
String fieldName = entry.getKey(); | ||
JsonNode node = entry.getValue(); | ||
|
||
if (fieldName.equals("@language")) { | ||
literal.setLanguage(node.getTextValue()); | ||
} else if (fieldName.equals("@type")) { | ||
literal.setType(node.getTextValue()); | ||
} else if ("@value".equals(fieldName)) { | ||
if (node.isBoolean()) { | ||
literal.setBooleanValue(node.getBooleanValue()); | ||
} else if (node.isFloatingPointNumber()) { | ||
literal.setDoubleValue(node.getDoubleValue()); | ||
} else if (node.isLong()) { | ||
literal.setLongValue(literal.getLongValue()); | ||
} else if (node.isTextual()) { | ||
literal.setStringValue(node.getTextValue()); | ||
} | ||
} | ||
} | ||
|
||
return literal; | ||
} | ||
|
||
private void parseFields(ObjectNode json, LdObjectImpl object, ObjectNode node, | ||
LdObjectImpl parent) throws JsonParseException, IOException, LdParseException { | ||
|
||
FieldList fieldList = new FieldList(); | ||
object.setFieldList(fieldList); | ||
LdContext context = object.getContext(); | ||
|
||
Iterator<Entry<String,JsonNode>> sequence = json.getFields(); | ||
while (sequence.hasNext()) { | ||
Entry<String,JsonNode> entry = sequence.next(); | ||
String fieldName = entry.getKey(); | ||
JsonNode value = entry.getValue(); | ||
|
||
if ("@context".equals(fieldName)) { | ||
continue; | ||
} else if ("@id".equals(fieldName)) { | ||
object.setId(value.getTextValue()); | ||
} else if ("@type".equals(fieldName)) { | ||
object.setRawType(value.getTextValue()); | ||
} else { | ||
|
||
LdTerm term = (context==null) ? null : context.getTerm(fieldName); | ||
LinkedLdField field = new LinkedLdField(object); | ||
|
||
// If the field name contains a '#', '/', or ':' | ||
// then the simple name is substring after that delimiter. | ||
|
||
int delim = fieldName.lastIndexOf('#'); | ||
if (delim < 0) { | ||
delim = fieldName.lastIndexOf('/'); | ||
} | ||
if (delim < 0) { | ||
delim = fieldName.lastIndexOf(':'); | ||
} | ||
if (delim >= 0) { | ||
field.setLocalName(fieldName.substring(delim+1)); | ||
} else { | ||
field.setLocalName(fieldName); | ||
} | ||
|
||
|
||
String propertyIRI = (context == null) ? fieldName : context.expand(fieldName); | ||
field.setPropertyURI(propertyIRI); | ||
|
||
LdNode v = parseNode(value, object, term, field); | ||
field.setValue(v); | ||
setValueOwner(field); | ||
|
||
setType(field, fieldName, context); | ||
object.fieldList.add(field); | ||
} | ||
|
||
|
||
|
||
} | ||
|
||
} | ||
|
||
/** | ||
* Set the type of the given field based on the given context, but only if the | ||
* field does not already have the type declared. | ||
*/ | ||
private void setType(LinkedLdField field, String fieldName, LdContext context) { | ||
if (context == null) return; | ||
|
||
LdNode value = field.getValue(); | ||
if (value == null) return; | ||
|
||
LdTerm term = context.getTerm(fieldName); | ||
if (term == null) return; | ||
|
||
if (value instanceof LdObjectImpl) { | ||
LdObjectImpl object = (LdObjectImpl) value; | ||
if (object.getTypeIRI() != null) return; | ||
object.setTypeIRI(term.getTypeIRI()); | ||
|
||
} else if (value instanceof LdLiteral) { | ||
LdLiteral literal = (LdLiteral) value; | ||
if (literal.getType() == null) { | ||
literal.setType(term.getTypeIRI()); | ||
} | ||
} | ||
|
||
} | ||
|
||
private void setValueOwner(LdField field) { | ||
|
||
LdNode value = field.getValue(); | ||
|
||
if (value instanceof LdObjectImpl) { | ||
LdObjectImpl object = (LdObjectImpl) value; | ||
object.setOwner(field); | ||
} else if (value instanceof LdContainerImpl) { | ||
LdContainerImpl container = (LdContainerImpl) value; | ||
container.setOwner(field); | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public void setStreaming(boolean streaming) { | ||
|
||
} | ||
|
||
@Override | ||
public boolean isStreaming() { | ||
return false; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.