001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.rio.trig;
007:
008: import java.io.IOException;
009:
010: import org.openrdf.model.Resource;
011: import org.openrdf.model.Statement;
012: import org.openrdf.model.URI;
013: import org.openrdf.model.Value;
014: import org.openrdf.model.ValueFactory;
015: import org.openrdf.model.impl.ValueFactoryImpl;
016: import org.openrdf.rio.RDFFormat;
017: import org.openrdf.rio.RDFHandlerException;
018: import org.openrdf.rio.RDFParseException;
019: import org.openrdf.rio.turtle.TurtleParser;
020: import org.openrdf.rio.turtle.TurtleUtil;
021:
022: /**
023: * RDF parser for <a
024: * href="http://www.wiwiss.fu-berlin.de/suhl/bizer/TriG/Spec/">TriG</a> files.
025: * This parser is not thread-safe, therefore its public methods are
026: * synchronized.
027: * <p>
028: * This implementation is based on the 2005/06/06 version of the TriG
029: * specification, but implemented as an extension of the <a
030: * href="http://www.dajobe.org/2004/01/turtle/">Turtle</a> specification of
031: * 2006/01/02.
032: *
033: * @see TurtleParser
034: * @author Arjohn Kampman
035: */
036: public class TriGParser extends TurtleParser {
037:
038: /*-----------*
039: * Variables *
040: *-----------*/
041:
042: private Resource context;
043:
044: /*--------------*
045: * Constructors *
046: *--------------*/
047:
048: /**
049: * Creates a new TriGParser that will use a {@link ValueFactoryImpl} to
050: * create RDF model objects.
051: */
052: public TriGParser() {
053: super ();
054: }
055:
056: /**
057: * Creates a new TriGParser that will use the supplied ValueFactory to create
058: * RDF model objects.
059: *
060: * @param valueFactory
061: * A ValueFactory.
062: */
063: public TriGParser(ValueFactory valueFactory) {
064: super (valueFactory);
065: }
066:
067: /*---------*
068: * Methods *
069: *---------*/
070:
071: @Override
072: public RDFFormat getRDFFormat() {
073: return RDFFormat.TRIG;
074: }
075:
076: @Override
077: protected void parseStatement() throws IOException,
078: RDFParseException, RDFHandlerException {
079: int c = peek();
080:
081: if (c == '@') {
082: parseDirective();
083: skipWSC();
084: verifyCharacter(read(), ".");
085: } else {
086: parseGraph();
087: }
088: }
089:
090: protected void parseGraph() throws IOException, RDFParseException,
091: RDFHandlerException {
092: int c = read();
093: int c2 = peek();
094:
095: if (c == '<' || TurtleUtil.isPrefixStartChar(c)
096: || (c == ':' && c2 != '-') || (c == '_' && c2 == ':')) {
097: unread(c);
098:
099: Value value = parseValue();
100:
101: if (value instanceof Resource) {
102: context = (Resource) value;
103: } else {
104: reportFatalError("Illegal graph name: " + value);
105: }
106:
107: skipWSC();
108: c = read();
109: } else {
110: context = null;
111: }
112:
113: if (c == ':') {
114: verifyCharacter(read(), "-");
115: skipWSC();
116: c = read();
117: }
118:
119: verifyCharacter(c, "{");
120:
121: c = skipWSC();
122:
123: if (c != '}') {
124: parseTriples();
125:
126: c = skipWSC();
127:
128: while (c == '.') {
129: read();
130:
131: c = skipWSC();
132:
133: if (c == '}') {
134: break;
135: }
136:
137: parseTriples();
138:
139: c = skipWSC();
140: }
141:
142: verifyCharacter(c, "}");
143: }
144:
145: read();
146:
147: // FIXME: Blank nodes are scoped to the named graph?
148: // clearBNodeIDMap();
149: }
150:
151: @Override
152: protected void reportStatement(Resource subj, URI pred, Value obj)
153: throws RDFParseException, RDFHandlerException {
154: Statement st = createStatement(subj, pred, obj, context);
155: rdfHandler.handleStatement(st);
156: }
157: }
|