001: package org.ontoware.semversion.impl;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.util.HashMap;
006: import java.util.Iterator;
007: import java.util.Map;
008:
009: import org.ontoware.aifbcommons.collection.ClosableIterator;
010: import org.ontoware.rdf2go.model.Model;
011: import org.ontoware.rdf2go.model.ModelSet;
012: import org.ontoware.rdf2go.model.Statement;
013: import org.ontoware.rdf2go.model.impl.DelegatingModel;
014: import org.ontoware.rdf2go.model.impl.DiffImpl;
015: import org.ontoware.rdf2go.model.node.BlankNode;
016: import org.ontoware.rdf2go.model.node.Resource;
017: import org.ontoware.rdf2go.model.node.URI;
018: import org.ontoware.semversion.SemVersion;
019: import org.openrdf.rdf2go.RepositoryModelFactory;
020: import org.openrdf.rdf2go.RepositoryModelSet;
021: import org.openrdf.repository.Repository;
022: import org.openrdf.repository.RepositoryException;
023: import org.openrdf.repository.sail.SailRepository;
024: import org.openrdf.sail.nativerdf.NativeStore;
025: import org.slf4j.Logger;
026: import org.slf4j.LoggerFactory;
027:
028: /**
029: * This class determines the storage strategy. Internally an RDF2Go ContextModel
030: * is used.
031: *
032: * @author $Author: xamde $
033: * @version $Id: TripleStore.java,v 1.23 2006/10/16 17:30:25 xamde Exp $
034: *
035: */
036: public class TripleStore {
037:
038: private static Logger log = LoggerFactory
039: .getLogger(TripleStore.class);
040:
041: /** the real persistent store of SemVersion */
042: private ModelSet persistentModelSet;
043:
044: public TripleStore(File storageDir) throws IOException {
045:
046: // persistent store
047: NativeStore ns = new NativeStore(storageDir);
048: ns.setTripleIndexes("spoc, posc, sopc, psoc, ospc, opsc");
049: Repository myRepository = new SailRepository(ns);
050: try {
051: myRepository.initialize();
052: persistentModelSet = new RepositoryModelSet(myRepository);
053: persistentModelSet.open();
054: } catch (RepositoryException e) {
055: throw new RuntimeException(e);
056: }
057:
058: }
059:
060: /**
061: * @return an open RDF2Go model as a view on a certain set of quads in the
062: * ContextModel
063: */
064: public Model getPersistentModel(URI contextURI) {
065: if (contextURI == null)
066: throw new IllegalArgumentException("null");
067: log.debug("Getting model: " + contextURI);
068: Model model = persistentModelSet.getModel(contextURI);
069: model.open();
070: return model;
071: }
072:
073: /** return an in-memory Model, opened */
074: public Model getTempModel(URI uri) {
075: // IMPROVE for hardcore scalability use persistent modlsets here
076: ModelSet inMemoryModelSet = new RepositoryModelFactory()
077: .createModelSet();
078: inMemoryModelSet.open();
079: Model m = inMemoryModelSet.getModel(uri);
080: m.open();
081: return new ClosingModel(m, inMemoryModelSet);
082: }
083:
084: class ClosingModel extends DelegatingModel {
085: private ModelSet modelset;
086:
087: public ClosingModel(Model model, ModelSet modelset) {
088: super (model);
089: this .modelset = modelset;
090: }
091:
092: public void close() {
093: super .close();
094: modelset.close();
095: }
096: }
097:
098: /**
099: * Adds the contents of an external model to the context model. Expensive
100: * operation, as the model has to be copied.
101: *
102: * @param m
103: * @return the persistent Model, opened
104: */
105: public Model addModelAndPersist(Model m) {
106: assert m != null;
107:
108: // if m is a persistent model already: copy to memory first
109: if (m.getContextURI() != null
110: && persistentModelSet.containsModel(m.getContextURI())) {
111: throw new RuntimeException("A model with URI "
112: + m.getContextURI()
113: + " is already in the persistent store");
114: } else {
115: URI u = persistentModelSet.newRandomUniqueURI();
116: Model persistent = getPersistentModel(u);
117: ClosableIterator<Statement> it = m.iterator();
118: persistent.addAll(it);
119: it.close();
120: return persistent;
121: }
122:
123: }
124:
125: public void dump() {
126: System.out.println("Persistent modeset:");
127: persistentModelSet.dump();
128: }
129:
130: public void deleteStore() {
131: persistentModelSet.removeAll();
132: }
133:
134: /**
135: * Make sure all bnodes have a unique inverse functional property
136: *
137: * TODO: test this method
138: *
139: * @param m
140: * @return
141: * @throws Exception
142: */
143: public static void bnodeEnrichment(Model m) throws Exception {
144: Iterator<Statement> it = m.iterator();
145: Map<BlankNode, URI> knownBnodes = new HashMap<BlankNode, URI>();
146:
147: DiffImpl diff = new DiffImpl();
148: boolean changed = false;
149: while (it.hasNext()) {
150: Statement s = it.next();
151: if (s.getSubject() instanceof BlankNode) {
152: changed = true;
153: URI u = knownBnodes.get(s.getSubject());
154: if (u == null) {
155: u = m.newRandomUniqueURI();
156: knownBnodes.put((BlankNode) s.getSubject(), u);
157: }
158: diff.addStatement(s.getSubject(),
159: SemVersion.BLANK_NODE_ID, u);
160: }
161: if (s.getObject() instanceof BlankNode) {
162: changed = true;
163: URI u = knownBnodes.get(s.getObject());
164: if (u == null) {
165: u = m.newRandomUniqueURI();
166: knownBnodes.put((BlankNode) s.getObject(), u);
167: }
168: diff.addStatement((Resource) s.getObject(),
169: SemVersion.BLANK_NODE_ID, u);
170: }
171: }
172: if (changed) {
173: m.addAll(diff.getAdded().iterator());
174: }
175: }
176:
177: public URI newRandomUniqueURI() {
178: return this .persistentModelSet.newRandomUniqueURI();
179: }
180:
181: /**
182: * @return persistent ModelSet
183: */
184: ModelSet getModelSet() {
185: return this .persistentModelSet;
186: }
187:
188: /**
189: * return a non-persistent copy of the model stored at the given URI.
190: * Returned model is open
191: */
192: public Model getAsTempCopy(URI modelURI) {
193: Model p = getPersistentModel(modelURI);
194: Model copy = getTempModel(newRandomUniqueURI());
195: ClosableIterator<Statement> it = p.iterator();
196: copy.addAll(it);
197: it.close();
198: return copy;
199: }
200:
201: public void finalize() {
202: persistentModelSet.close();
203: }
204:
205: }
|