001: package org.ontoware.rdf2go.impl.jena24;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.io.OutputStream;
006: import java.io.Reader;
007: import java.io.Writer;
008: import java.net.URL;
009: import java.util.Iterator;
010:
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013: import org.ontoware.aifbcommons.collection.ClosableIterable;
014: import org.ontoware.aifbcommons.collection.ClosableIterator;
015: import org.ontoware.rdf2go.Reasoning;
016: import org.ontoware.rdf2go.exception.LockException;
017: import org.ontoware.rdf2go.exception.ModelRuntimeException;
018: import org.ontoware.rdf2go.exception.SyntaxNotSupportedException;
019: import org.ontoware.rdf2go.model.Diff;
020: import org.ontoware.rdf2go.model.Model;
021: import org.ontoware.rdf2go.model.QueryResultTable;
022: import org.ontoware.rdf2go.model.Statement;
023: import org.ontoware.rdf2go.model.Syntax;
024: import org.ontoware.rdf2go.model.impl.AbstractModel;
025: import org.ontoware.rdf2go.model.node.BlankNode;
026: import org.ontoware.rdf2go.model.node.DatatypeLiteral;
027: import org.ontoware.rdf2go.model.node.NodeOrVariable;
028: import org.ontoware.rdf2go.model.node.ResourceOrVariable;
029: import org.ontoware.rdf2go.model.node.URI;
030: import org.ontoware.rdf2go.model.node.UriOrVariable;
031: import org.ontoware.rdf2go.model.node.impl.AbstractBlankNodeImpl;
032:
033: import com.hp.hpl.jena.graph.Node;
034: import com.hp.hpl.jena.graph.Triple;
035: import com.hp.hpl.jena.iri.IRI;
036: import com.hp.hpl.jena.iri.IRIFactory;
037: import com.hp.hpl.jena.iri.Violation;
038: import com.hp.hpl.jena.query.Query;
039: import com.hp.hpl.jena.query.QueryExecution;
040: import com.hp.hpl.jena.query.QueryExecutionFactory;
041: import com.hp.hpl.jena.query.QueryFactory;
042: import com.hp.hpl.jena.rdf.model.AnonId;
043: import com.hp.hpl.jena.rdf.model.Literal;
044: import com.hp.hpl.jena.rdf.model.ModelFactory;
045: import com.hp.hpl.jena.rdf.model.Property;
046: import com.hp.hpl.jena.rdf.model.Resource;
047: import com.hp.hpl.jena.reasoner.ReasonerRegistry;
048: import com.hp.hpl.jena.shared.BadURIException;
049:
050: // import de.fuberlin.wiwiss.ng4j.triql.TriQLQuery;
051:
052: /**
053: *
054: * (wth) for information on typed literals see this very good how to
055: * http://jena.sourceforge.net/how-to/typedLiterals.html
056: *
057: */
058: public class ModelImplJena24 extends AbstractModel implements Model {
059: protected static final Log log = LogFactory
060: .getLog(ModelImplJena24.class);
061:
062: protected com.hp.hpl.jena.rdf.model.Model jenaModel;
063:
064: /**
065: * used to check wheter iterators work on the up-to-date model
066: */
067: protected long modificationCount = 0;
068:
069: protected Reasoning reasoning;
070:
071: private URI contextURI;
072:
073: private boolean locked;
074:
075: /**
076: * @param reasoning
077: */
078: public ModelImplJena24(URI contextURI, Reasoning r) {
079: this .contextURI = contextURI;
080: this .reasoning = r;
081: jenaModel = ModelFactory.createDefaultModel();
082: applyReasoning(reasoning);
083: }
084:
085: /**
086: * wraps a Jena Model in a rdf2go Model
087: *
088: * @param jenaModel
089: */
090: public ModelImplJena24(URI contextURI,
091: com.hp.hpl.jena.rdf.model.Model jenaModel) {
092: this (contextURI, jenaModel, Reasoning.none);
093: }
094:
095: public ModelImplJena24(com.hp.hpl.jena.rdf.model.Model jenaModel) {
096: this (null, jenaModel, Reasoning.none);
097: }
098:
099: public ModelImplJena24(URI contextURI,
100: com.hp.hpl.jena.rdf.model.Model jenaModel,
101: Reasoning reasoning) {
102: this .contextURI = contextURI;
103: this .reasoning = reasoning;
104: // re-use
105: this .jenaModel = jenaModel;
106: applyReasoning(reasoning);
107: }
108:
109: public ModelImplJena24(Reasoning reasoning) {
110: this (null, reasoning);
111: }
112:
113: @Override
114: public void addAll(Iterator<? extends Statement> other)
115: throws ModelRuntimeException {
116: assertModel();
117: if (other instanceof ModelImplJena24) {
118: com.hp.hpl.jena.rdf.model.Model otherJenaModel = (com.hp.hpl.jena.rdf.model.Model) ((ModelImplJena24) other)
119: .getUnderlyingModelImplementation();
120: this .jenaModel.add(otherJenaModel);
121: } else
122: super .addAll(other);
123: }
124:
125: void applyReasoning(Reasoning r) {
126: switch (r) {
127: case rdfs:
128: jenaModel = ModelFactory.createRDFSModel(jenaModel);
129: break;
130: case owl:
131: jenaModel = ModelFactory.createInfModel(ReasonerRegistry
132: .getOWLReasoner(), jenaModel);
133: default:
134: break;
135: }
136: }
137:
138: public BlankNode createBlankNode() {
139: // this.modificationCount++;
140: // should be unique across models
141:
142: return new JenaBlankNode(com.hp.hpl.jena.graph.Node
143: .createAnon());
144: }
145:
146: public BlankNode createBlankNode(String id) {
147: // this.modificationCount++;
148: // should be unique across models
149: AnonId anonid = AnonId.create(id);
150: return new JenaBlankNode(com.hp.hpl.jena.graph.Node
151: .createAnon(anonid));
152: }
153:
154: /*
155: * (non-Javadoc)
156: *
157: * @see org.ontoware.rdf2go.Model#addStatement(java.lang.Object,
158: * java.net.URI, java.lang.Object)
159: */
160: public void addStatement(
161: org.ontoware.rdf2go.model.node.Resource subject,
162: URI predicate, org.ontoware.rdf2go.model.node.Node object)
163: throws ModelRuntimeException {
164: assertModel();
165: try {
166: log.debug("adding a statement (" + subject + ","
167: + predicate + "," + object + ")");
168: this .modificationCount++;
169: if (!(object instanceof DatatypeLiteral)) {
170: this .jenaModel.getGraph().add(
171: new Triple(TypeConversion.toJenaNode(subject,
172: jenaModel), TypeConversion.toJenaNode(
173: predicate, jenaModel), TypeConversion
174: .toJenaNode(object, jenaModel)));
175: } else
176: // DatatypeLiteral
177: {
178: // build Resources/Literals
179: Resource s = null;
180: if (subject instanceof URI) {
181: s = this .jenaModel.createResource(subject
182: .toString());
183: } else
184: // subject is a BlankNode
185: {
186: s = this .jenaModel
187: .createResource(((Node) ((AbstractBlankNodeImpl) subject)
188: .getUnderlyingBlankNode())
189: .getBlankNodeId());
190: }
191:
192: Property p = this .jenaModel.createProperty(predicate
193: .toString());
194:
195: String datatypeValue = ((DatatypeLiteral) object)
196: .getValue();
197: String datatypeURI = ((DatatypeLiteral) object)
198: .getDatatype().toString();
199: Literal o = this .jenaModel.createTypedLiteral(
200: datatypeValue, datatypeURI);
201:
202: // Add the statement to the model
203: this .jenaModel.add(s, p, o);
204: }
205: } catch (BadURIException e) {
206: throw new ModelRuntimeException(e);
207: }
208: }
209:
210: /*
211: * (non-Javadoc)
212: *
213: * @see org.ontoware.rdf2go.Model#removeStatement(java.lang.Object,
214: * java.net.URI, java.lang.Object)
215: */
216: public void removeStatement(
217: org.ontoware.rdf2go.model.node.Resource subject,
218: URI predicate, org.ontoware.rdf2go.model.node.Node object)
219: throws ModelRuntimeException {
220: assertModel();
221:
222: log.debug("removing a statement (" + subject + "," + predicate
223: + "," + object + ")");
224: this .modificationCount++;
225: this .jenaModel
226: .getGraph()
227: .delete(
228: new Triple(
229:
230: TypeConversion.toJenaNode(subject, jenaModel),
231: TypeConversion.toJenaNode(predicate,
232: jenaModel), TypeConversion
233: .toJenaNode(object, jenaModel)));
234: }
235:
236: public QueryResultTable sparqlSelect(String queryString)
237: throws ModelRuntimeException {
238: assertModel();
239: log.debug("Query " + queryString);
240: Query query = QueryFactory.create(queryString);
241: return new QueryResultTableImpl(query, jenaModel);
242: }
243:
244: public ClosableIterable<Statement> sparqlConstruct(
245: String queryString) throws ModelRuntimeException {
246: assertModel();
247: Query query = QueryFactory.create(queryString);
248: QueryExecution qexec = QueryExecutionFactory.create(query,
249: jenaModel);
250:
251: if (query.isConstructType()) {
252: com.hp.hpl.jena.rdf.model.Model m = qexec.execConstruct();
253: Model resultModel = new ModelImplJena24(null, m,
254: Reasoning.none);
255: resultModel.open();
256: return resultModel;
257: } else {
258: throw new RuntimeException(
259: "Cannot handle this type of queries! Please use CONSTRUCT.");
260: }
261: }
262:
263: public boolean sparqlAsk(String queryString)
264: throws ModelRuntimeException {
265: assertModel();
266: log.debug("Query " + queryString);
267: Query query = QueryFactory.create(queryString);
268:
269: if (!query.isAskType()) {
270: throw new ModelRuntimeException(
271: "The given query is not an ASK query");
272: }
273: // else
274: QueryExecution qexec = QueryExecutionFactory.create(query,
275: jenaModel);
276: return qexec.execAsk();
277: }
278:
279: /**
280: * handle with care, iterators based on this model might (silently!) throw
281: * concurrent modification exceptions
282: *
283: * @return the underlying jena model
284: */
285: public com.hp.hpl.jena.rdf.model.Model getInternalJenaModel() {
286: assertModel();
287: return this .jenaModel;
288: }
289:
290: /*
291: * (non-Javadoc)
292: *
293: * @see org.ontoware.rdf2go.Model#size()
294: */
295: @Override
296: public long size() throws ModelRuntimeException {
297: assertModel();
298: return (int) this .jenaModel.size();
299: }
300:
301: /**
302: * @return count of modifications, used to prevent iterators from accessing
303: * old modle state
304: */
305: public long getModificationCount() {
306: return this .modificationCount;
307: }
308:
309: public Object getUnderlyingModelImplementation() {
310: return jenaModel;
311: }
312:
313: public void setUnderlyingModelImplementation(Object o) {
314: assert o instanceof com.hp.hpl.jena.rdf.model.Model;
315: jenaModel = (com.hp.hpl.jena.rdf.model.Model) o;
316: }
317:
318: public ClosableIterator<Statement> iterator() {
319: assertModel();
320: return new TripleIterator(jenaModel.getGraph().find(Node.ANY,
321: Node.ANY, Node.ANY), modificationCount, this );
322: }
323:
324: public URI getContextURI() {
325: return this .contextURI;
326: }
327:
328: public void lock() throws LockException {
329: locked = true;
330: jenaModel.enterCriticalSection(true);
331:
332: }
333:
334: public boolean isLocked() {
335: return locked;
336: }
337:
338: public void unlock() {
339: assertModel();
340: jenaModel.leaveCriticalSection();
341: this .locked = false;
342: }
343:
344: public void update(Diff diff) throws ModelRuntimeException {
345: assertModel();
346: lock();
347: addAll(diff.getAdded().iterator());
348: removeAll(diff.getRemoved().iterator());
349: unlock();
350: }
351:
352: public ClosableIterator<Statement> findStatements(
353: ResourceOrVariable subject, UriOrVariable predicate,
354: NodeOrVariable object) throws ModelRuntimeException {
355: assertModel();
356:
357: return new TripleIterator(jenaModel.getGraph().find(
358: TypeConversion.toJenaNode(subject),
359: TypeConversion.toJenaNode(predicate),
360: TypeConversion.toJenaNode(object)), modificationCount,
361: this );
362: }
363:
364: /**
365: * @return opened result Model
366: */
367: public ClosableIterable<Statement> sparqlDescribe(String queryString)
368: throws ModelRuntimeException {
369: assertModel();
370: Query query = QueryFactory.create(queryString);
371: QueryExecution qexec = QueryExecutionFactory.create(query,
372: jenaModel);
373:
374: if (query.isDescribeType()) {
375: com.hp.hpl.jena.rdf.model.Model m = qexec.execDescribe();
376: Model resultModel = new ModelImplJena24(null, m,
377: Reasoning.none);
378: resultModel.open();
379: return resultModel;
380: } else {
381: throw new RuntimeException(
382: "Cannot handle this type of queries! Please use DESCRIBE.");
383: }
384:
385: }
386:
387: public void readFrom(Reader r) {
388: assertModel();
389: this .jenaModel.read(r, "", "RDF/XML");
390: }
391:
392: /**
393: * Might need this code fragment:
394: *
395: * FileOutputStream fos = new FileOutputStream(tmpFile); OutputStreamWriter
396: * osw = new OutputStreamWriter(fos, "utf8"); synchronized
397: * (getDelegatedModel()) {
398: * DumpUtils.addCommonPrefixesToJenaModel(jenaModel); jenaModel.write(osw,
399: * lang, ""); } osw.close();
400: *
401: */
402: public void readFrom(Reader reader, Syntax syntax) {
403: assertModel();
404: if (syntax == Syntax.RdfXml) {
405: readFrom(reader);
406: } else if (syntax == Syntax.Ntriples) {
407: this .jenaModel.read(reader, "", "N-TRIPLE");
408: } else if (syntax == Syntax.Turtle) {
409: this .jenaModel.read(reader, "", "N3");
410: } else if (syntax == Syntax.Trix) {
411: throw new IllegalArgumentException(
412: "Not implemented in Jena 2.4");
413: }
414: };
415:
416: public void readFrom(Reader reader, Syntax syntax, URL baseURI) {
417: assertModel();
418: if (syntax == Syntax.RdfXml) {
419: readFrom(reader);
420: } else if (syntax == Syntax.Ntriples) {
421: this .jenaModel.read(reader, baseURI.toExternalForm(),
422: "N-TRIPLE");
423: } else if (syntax == Syntax.Turtle) {
424: this .jenaModel.read(reader, baseURI.toExternalForm(), "N3");
425: } else if (syntax == Syntax.Trix) {
426: throw new IllegalArgumentException(
427: "Not implemented in Jena 2.4");
428: }
429: };
430:
431: private static void registerNamespaces(
432: com.hp.hpl.jena.rdf.model.Model jenaModel) {
433: // beautify output
434: jenaModel.setNsPrefix("rdf",
435: "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
436: jenaModel.setNsPrefix("xsd",
437: "http://www.w3.org/2001/XMLSchema#");
438: jenaModel.setNsPrefix("rdfs",
439: "http://www.w3.org/2000/01/rdf-schema#");
440: jenaModel.setNsPrefix("foaf", "http://xmlns.com/foaf/0.1/");
441: }
442:
443: // TODO: check valid XML output
444: public void writeTo(Writer w) {
445: writeTo(w, Syntax.RdfXml);
446: }
447:
448: public void writeTo(Writer writer, Syntax syntax) {
449: assertModel();
450: registerNamespaces(jenaModel);
451:
452: if (syntax == Syntax.RdfXml) {
453: this .jenaModel.write(writer, "RDF/XML", "");
454: } else if (syntax == Syntax.Ntriples) {
455: this .jenaModel.write(writer, "N-TRIPLE", "");
456: } else if (syntax == Syntax.Turtle) {
457: if (this .jenaModel.size() < 1000) {
458: log.debug("Model is small enough for pretty-print.");
459: this .jenaModel.write(writer, "N3-PP", "");
460: } else {
461: this .jenaModel.write(writer, "N3", "");
462: }
463: } else {
464: throw new IllegalArgumentException(syntax
465: + " is not implemented in Jena 2.4");
466: }
467: }
468:
469: public void dump() {
470: assertModel();
471: jenaModel.write(System.out, "N3-PP", "");
472: }
473:
474: public void readFrom(InputStream in) throws IOException,
475: ModelRuntimeException {
476: assertModel();
477: this .jenaModel.read(in, "", "RDF/XML");
478: }
479:
480: public void writeTo(OutputStream out) throws IOException,
481: ModelRuntimeException {
482: assertModel();
483: writeTo(out, Syntax.RdfXml);
484: }
485:
486: /**
487: * Throws an exception if the syntax is not SPARQL
488: *
489: * @throws IOException
490: * @throws ModelRuntimeException
491: */
492: public void writeTo(OutputStream out, Syntax syntax)
493: throws ModelRuntimeException, IOException {
494: assertModel();
495: if (syntax == Syntax.RdfXml) {
496: jenaModel.write(out, "RDF/XML", "");
497: } else if (syntax == Syntax.Ntriples) {
498: this .jenaModel.write(out, "N-TRIPLE", "");
499: } else if (syntax == Syntax.Turtle) {
500: if (this .jenaModel.size() < 1000) {
501: log.debug("Model is small enough for pretty-print.");
502: this .jenaModel.write(out, "N3-PP", "");
503: } else {
504: this .jenaModel.write(out, "N3", "");
505: }
506: } else {
507: throw new SyntaxNotSupportedException(syntax
508: + " is not implemented in Jena 2.4");
509: }
510: }
511:
512: private String getJenaSyntaxName(Syntax syntax) {
513: if (syntax == Syntax.Ntriples)
514: return "N-TRIPLE";
515: if (syntax == Syntax.Turtle)
516: return "N3";
517: else if (syntax == Syntax.RdfXml)
518: return "RDF/XML";
519: else
520: return null;
521: }
522:
523: public void readFrom(InputStream in, Syntax syntax)
524: throws IOException, ModelRuntimeException {
525: assertModel();
526: assert in != null;
527: String jenaSyntax = getJenaSyntaxName(syntax);
528: if (jenaSyntax == null)
529: throw new SyntaxNotSupportedException(
530: "Could not process syntax named <"
531: + syntax.getName()
532: + "> directly, maybe the underlying Jena can...");
533:
534: this .jenaModel.read(in, "", jenaSyntax);
535: }
536:
537: public void readFrom(InputStream in, Syntax syntax, URL baseURI)
538: throws IOException, ModelRuntimeException {
539: assertModel();
540: assert in != null;
541: String jenaSyntax = getJenaSyntaxName(syntax);
542: if (jenaSyntax == null)
543: throw new SyntaxNotSupportedException(
544: "Could not process syntax named <"
545: + syntax.getName()
546: + "> directly, maybe the underlying Jena can...");
547:
548: this .jenaModel.read(in, baseURI.toExternalForm(), jenaSyntax);
549: }
550:
551: public boolean isIsomorphicWith(Model other) {
552: if (other instanceof ModelImplJena24) {
553: return this .jenaModel
554: .isIsomorphicWith(((ModelImplJena24) other)
555: .getInternalJenaModel());
556: } else {
557: // TODO: reasoning might be different
558: ModelImplJena24 otherJenaModel = new ModelImplJena24(
559: Reasoning.none);
560: otherJenaModel.addAll(other.iterator());
561: return this .jenaModel.isIsomorphicWith(otherJenaModel
562: .getInternalJenaModel());
563: }
564: }
565:
566: static IRIFactory factory = IRIFactory.jenaImplementation();
567:
568: public boolean isValidURI(String uriString) {
569: IRI iri = factory.create(uriString);
570: if (iri.hasViolation(false)) {
571: log
572: .debug("Only well-formed absolute URIrefs can be included in RDF/XML output: <"
573: + uriString
574: + "> "
575: + ((Violation) iri.violations(false).next())
576: .getLongMessage());
577: return false;
578: }
579: return true;
580: }
581: }
|