/androjena/src/com/hp/hpl/jena/db/impl/SpecializedGraphReifier_RDB.java

http://androjena.googlecode.com/ · Java · 543 lines · 294 code · 47 blank · 202 comment · 67 complexity · 14e022b3620df36cc853e08f69fbd3c4 MD5 · raw file

  1. /*
  2. * (c) Copyright 2003 Hewlett-Packard Development Company, LP
  3. * All rights reserved.
  4. *
  5. */
  6. package com.hp.hpl.jena.db.impl;
  7. import java.util.ArrayList;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import com.hp.hpl.jena.db.GraphRDB;
  11. import com.hp.hpl.jena.graph.*;
  12. import com.hp.hpl.jena.util.iterator.*;
  13. import com.hp.hpl.jena.shared.*;
  14. import com.hp.hpl.jena.vocabulary.RDF;
  15. /**
  16. * @author hkuno
  17. * @version $Version$
  18. *
  19. * TripleStoreGraph is an abstract superclass for TripleStoreGraph
  20. * implementations. By "triple store," we mean that the subjects, predicate
  21. * and object URI's are stored in a single collection (denormalized).
  22. *
  23. */
  24. public class SpecializedGraphReifier_RDB
  25. extends SpecializedGraphBase
  26. implements SpecializedGraphReifier {
  27. /**
  28. * holds PSet
  29. */
  30. public PSet_ReifStore_RDB m_pset;
  31. /**
  32. * caches a copy of LSet properties
  33. */
  34. public DBPropLSet m_dbPropLSet;
  35. /**
  36. * holds ID of graph in database (defaults to "0")
  37. */
  38. public IDBID my_GID = null;
  39. // cache of reified statement status
  40. private ReificationCacheMap m_reifCache;
  41. public PSet_ReifStore_RDB m_reif;
  42. // constructors
  43. /**
  44. * Constructor
  45. * Create a new instance of a TripleStore graph.
  46. */
  47. SpecializedGraphReifier_RDB(DBPropLSet lProp, IPSet pSet, Integer dbGraphID) {
  48. m_pset = (PSet_ReifStore_RDB) pSet;
  49. m_dbPropLSet = lProp;
  50. my_GID = new DBIDInt(dbGraphID);
  51. m_reifCache = new ReificationCacheMap(this, 1);
  52. m_reif = m_pset;
  53. }
  54. /**
  55. * Constructor
  56. *
  57. * Create a new instance of a TripleStore graph, taking
  58. * DBPropLSet and a PSet as arguments
  59. */
  60. public SpecializedGraphReifier_RDB(IPSet pSet, Integer dbGraphID) {
  61. m_pset = (PSet_ReifStore_RDB) pSet;
  62. my_GID = new DBIDInt(dbGraphID);
  63. m_reifCache = new ReificationCacheMap(this, 1);
  64. m_reif = m_pset;
  65. }
  66. /* (non-Javadoc)
  67. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#add(com.hp.hpl.jena.graph.Node, com.hp.hpl.jena.graph.Triple, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  68. */
  69. public void add(Node n, Triple t, CompletionFlag complete) throws CannotReifyException {
  70. ReificationStatementMask same = new ReificationStatementMask();
  71. ReificationStatementMask diff = new ReificationStatementMask();
  72. ReificationCache rs = m_reifCache.load(n, t, same, diff);
  73. if (rs == null) {
  74. m_reif.storeReifStmt(n, t, my_GID);
  75. } else {
  76. /* node already reifies something. is that a subset of triple t? */
  77. if ( diff.hasNada() ) {
  78. boolean didUpdate = false;
  79. /* add whatever is missing to reify t */
  80. if ( !same.hasSubj() ) {
  81. Triple st = Triple.create(n,RDF.Nodes.subject,t.getSubject());
  82. m_reif.updateFrag(n, st, new ReificationStatementMask(st), my_GID);
  83. didUpdate = true;
  84. }
  85. if ( !same.hasPred() ) {
  86. Triple pt = Triple.create(n,RDF.Nodes.predicate,t.getPredicate());
  87. m_reif.updateFrag(n, pt, new ReificationStatementMask(pt), my_GID);
  88. didUpdate = true;
  89. }
  90. if ( !same.hasObj() ) {
  91. Triple ot = Triple.create(n,RDF.Nodes.object,t.getObject());
  92. m_reif.updateFrag(n, ot, new ReificationStatementMask(ot), my_GID);
  93. didUpdate = true;
  94. }
  95. if ( !rs.mask.hasType() ) {
  96. Triple tt = Triple.create(n,RDF.Nodes.type,RDF.Nodes.Statement);
  97. m_reif.updateFrag(n, tt, new ReificationStatementMask(tt), my_GID);
  98. didUpdate = true;
  99. }
  100. if ( didUpdate )
  101. fragCompact(n);
  102. m_reifCache.flushAll();
  103. } else {
  104. /* node reifies something that is not a subset of triple t */
  105. if ( rs.mask.isStmt() )
  106. throw new AlreadyReifiedException(n);
  107. else
  108. throw new CannotReifyException(n);
  109. }
  110. }
  111. complete.setDone();
  112. }
  113. /* (non-Javadoc)
  114. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#delete(com.hp.hpl.jena.graph.Node, com.hp.hpl.jena.graph.Triple, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  115. */
  116. public void delete(Node n, Triple t, CompletionFlag complete) {
  117. m_reifCache.flushAll();
  118. m_reif.deleteReifStmt( n, t, my_GID);
  119. complete.setDone();
  120. }
  121. /* (non-Javadoc)
  122. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#contains(com.hp.hpl.jena.graph.Node, com.hp.hpl.jena.graph.Triple, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  123. */
  124. public boolean contains(Node n, Triple t, CompletionFlag complete) {
  125. if (true)
  126. throw new JenaException("SpecializedGraphReifier.contains called");
  127. return false;
  128. }
  129. /* (non-Javadoc)
  130. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#findReifiedNodes(com.hp.hpl.jena.graph.TripleMatch, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  131. */
  132. public ExtendedIterator<Node> findReifiedNodes(Triple t, CompletionFlag complete) {
  133. complete.setDone();
  134. return m_reif.findReifStmtURIByTriple(t, my_GID);
  135. }
  136. /* (non-Javadoc)
  137. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#findReifiedTriple(com.hp.hpl.jena.graph.Node, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  138. */
  139. public Triple findReifiedTriple(Node n, CompletionFlag complete) {
  140. ResultSetReifIterator it = m_reif.findReifStmt(n, true, my_GID, false);
  141. Triple res = null;
  142. if ( it.hasNext() ) {
  143. res = it.next();
  144. }
  145. complete.setDone();
  146. return res;
  147. }
  148. /** Find all the triples corresponding to a given reified node.
  149. * In a perfect world, there would only ever be one, but when a user calls
  150. * add(Triple) there is nothing in RDF that prevents them from adding several
  151. * subjects,predicates or objects for the same statement.
  152. *
  153. * The resulting Triples may be incomplete, in which case some of the
  154. * nodes may be Node_ANY.
  155. *
  156. * For example, if an application had previously done:
  157. * add( new Triple( a, rdf.subject A )) and
  158. * add( new Triple( a, rdf.object B )) and
  159. * add( new Triple( a, rdf.object B2 ))
  160. *
  161. * Then the result of findReifiedTriple(a, flag) will be an iterator containing
  162. * Triple(A, ANY, B) and Triple(ANY, ANY, B2).
  163. *
  164. * @param n is the Node for which we are querying.
  165. * @param complete is true if we know we've returned all the triples which may exist.
  166. * @return ExtendedIterator.
  167. */
  168. public ExtendedIterator<Triple> findReifiedTriples(Node n, CompletionFlag complete) {
  169. complete.setDone();
  170. return m_reif.findReifStmt(n, false, my_GID, true);
  171. }
  172. /**
  173. * Attempt to add all the triples from a graph to the specialized graph
  174. *
  175. * Caution - this call changes the graph passed in, deleting from
  176. * it each triple that is successfully added.
  177. *
  178. * Node that when calling add, if complete is true, then the entire
  179. * graph was added successfully and the graph g will be empty upon
  180. * return. If complete is false, then some triples in the graph could
  181. * not be added. Those triples remain in g after the call returns.
  182. *
  183. * If the triple can't be stored for any reason other than incompatability
  184. * (for example, a lack of disk space) then the implemenation should throw
  185. * a runtime exception.
  186. *
  187. * @param g is a graph containing triples to be added
  188. * @param complete is true if a subsequent call to contains(triple) will return true for any triple in g.
  189. */
  190. public void add( Graph g, CompletionFlag complete ) {
  191. throw new AddDeniedException( "sorry, not implemented" );
  192. }
  193. /* (non-Javadoc)
  194. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#add(com.hp.hpl.jena.graph.Triple, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  195. */
  196. public void add(Triple frag, CompletionFlag complete) throws AlreadyReifiedException {
  197. ReificationStatementMask fragMask = new ReificationStatementMask(frag);
  198. if (fragMask.hasNada())
  199. return;
  200. boolean fragHasType = fragMask.hasType();
  201. Node stmtURI = frag.getSubject();
  202. ReificationCache cachedFrag = m_reifCache.load(stmtURI);
  203. if (cachedFrag == null) {
  204. // not in database
  205. m_reif.storeFrag(stmtURI, frag, fragMask, my_GID);
  206. complete.setDone();
  207. } else {
  208. ReificationStatementMask cachedMask = cachedFrag.getStmtMask();
  209. if (cachedMask.hasIntersect(fragMask)) {
  210. // see if this is a duplicate fragment
  211. boolean dup = fragHasType && cachedMask.hasType();
  212. if (dup == false) {
  213. // not a type fragement; have to search db to check for dup
  214. ExtendedIterator<Triple> it = m_reif.findFrag (stmtURI, frag, fragMask, my_GID);
  215. dup = it.hasNext();
  216. if ( dup == false ) {
  217. if ( cachedMask.isStmt())
  218. throw new AlreadyReifiedException(frag.getSubject());
  219. // cannot perform a reificiation; store fragment
  220. m_reif.storeFrag(stmtURI, frag, fragMask, my_GID);
  221. m_reifCache.flush(cachedFrag);
  222. }
  223. }
  224. } else {
  225. // reification may be possible; update if possible, else compact
  226. if (cachedFrag.canMerge(fragMask)) {
  227. if ( cachedFrag.canUpdate(fragMask) ) {
  228. m_reif.updateFrag(stmtURI, frag, fragMask, my_GID);
  229. cachedFrag.update(fragMask);
  230. } else
  231. fragCompact(stmtURI);
  232. } else {
  233. // reification not possible
  234. m_reif.storeFrag(stmtURI, frag, fragMask, my_GID);
  235. }
  236. }
  237. }
  238. complete.setDone();
  239. }
  240. /* (non-Javadoc)
  241. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#delete(com.hp.hpl.jena.graph.Triple, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  242. */
  243. public void delete(Triple frag, CompletionFlag complete) {
  244. ReificationStatementMask fragMask = new ReificationStatementMask(frag);
  245. if (fragMask.hasNada())
  246. return;
  247. Node stmtURI = frag.getSubject();
  248. ResultSetReifIterator it = m_reif.findFrag(stmtURI, frag, fragMask, my_GID);
  249. if ( it.hasNext() ) {
  250. if ( it.getFragCount() == 1 ) {
  251. /* last fragment in this tuple; can just delete it */
  252. m_reif.deleteFrag(frag, fragMask, my_GID);
  253. it.close();
  254. } else {
  255. /* remove fragment from row */
  256. m_reif.nullifyFrag(stmtURI, fragMask, my_GID);
  257. /* compact remaining fragments, if possible */
  258. it.close();
  259. fragCompact(stmtURI);
  260. }
  261. // remove cache entry, if any
  262. ReificationCache cachedFrag = m_reifCache.lookup(stmtURI);
  263. if ( cachedFrag != null ) m_reifCache.flush(cachedFrag);
  264. }
  265. complete.setDone();
  266. }
  267. /* fragCompact
  268. *
  269. * Compact fragments for a given statement URI.
  270. *
  271. * first, find the unique row for stmtURI that with the HasType Statement fragment.
  272. * if no such row exists, we are done. then, get all fragments for stmtURI and
  273. * try to merge them with the hasType fragment, deleting each as they are merged.
  274. */
  275. protected void fragCompact ( Node stmtURI ) {
  276. ResultSetReifIterator itHasType;
  277. Triple t;
  278. itHasType = m_reif.findReifStmt(stmtURI,true,my_GID, false);
  279. if ( itHasType.hasNext() ) {
  280. /* something to do */
  281. t = itHasType.next();
  282. if ( itHasType.hasNext() )
  283. throw new JenaException("Multiple HasType fragments for URI");
  284. ReificationStatementMask htMask = new ReificationStatementMask(t);
  285. itHasType.close();
  286. // now, look at fragments and try to merge them with the hasType fragement
  287. ResultSetReifIterator itFrag = m_reif.findReifStmt(stmtURI,false,my_GID, false);
  288. ReificationStatementMask upMask = new ReificationStatementMask();
  289. while ( itFrag.hasNext() ) {
  290. t = itFrag.next();
  291. if ( itFrag.getHasType() ) continue;
  292. ReificationStatementMask fm = new ReificationStatementMask(rowToFrag(stmtURI, t));
  293. if ( htMask.hasIntersect(fm) )
  294. break; // can't merge all fragments
  295. // at this point, we can merge in the current fragment
  296. m_reif.updateFrag(stmtURI, t, fm, my_GID);
  297. htMask.setMerge(fm);
  298. m_reif.deleteFrag(t, fm, my_GID);
  299. }
  300. }
  301. }
  302. protected Triple rowToFrag ( Node stmtURI, Triple row )
  303. {
  304. Node pred = null;
  305. Node obj = null;
  306. int valCnt = 0;
  307. if ( row.getSubject() != null ) {
  308. obj = row.getSubject();
  309. pred = RDF.Nodes.subject;
  310. valCnt++;
  311. }
  312. if ( row.getPredicate() != null ) {
  313. obj = row.getPredicate();
  314. pred = RDF.Nodes.predicate;
  315. valCnt++;
  316. }
  317. if ( row.getObject() != null ) {
  318. obj = row.getObject();
  319. pred = RDF.Nodes.object;
  320. valCnt++;
  321. }
  322. if ( valCnt != 1 )
  323. throw new JenaException("Partially reified row must have exactly one value");
  324. return Triple.create(stmtURI, pred, obj);
  325. }
  326. /* (non-Javadoc)
  327. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#add(java.util.List, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  328. */
  329. public void add(List<Triple> triples, CompletionFlag complete) {
  330. List<Triple> remainingTriples = new ArrayList<Triple>();
  331. for( int i=0; i< triples.size(); i++) {
  332. CompletionFlag partialResult = newComplete();
  333. add( triples.get(i), partialResult);
  334. if( !partialResult.isDone())
  335. remainingTriples.add(triples.get(i));
  336. }
  337. triples.clear();
  338. if( remainingTriples.isEmpty())
  339. complete.setDone();
  340. else
  341. triples.addAll(remainingTriples);
  342. }
  343. /* (non-Javadoc)
  344. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#delete(java.util.List, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  345. */
  346. public void delete(List<Triple> triples, CompletionFlag complete) {
  347. boolean result = true;
  348. Iterator<Triple> it = triples.iterator();
  349. while(it.hasNext()) {
  350. CompletionFlag partialResult = newComplete();
  351. delete( it.next(), partialResult);
  352. result = result && partialResult.isDone();
  353. }
  354. if( result )
  355. complete.setDone();
  356. }
  357. /* (non-Javadoc)
  358. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#tripleCount()
  359. */
  360. public int tripleCount() {
  361. // A very inefficient, but simple implementation
  362. ExtendedIterator<Triple> it = find( null, null, null, newComplete() );
  363. int count = 0;
  364. while (it.hasNext()) {
  365. it.next(); count++;
  366. }
  367. it.close();
  368. return count;
  369. }
  370. /* (non-Javadoc)
  371. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#find(com.hp.hpl.jena.graph.TripleMatch, com.hp.hpl.jena.db.impl.SpecializedGraph.CompletionFlag)
  372. */
  373. public ExtendedIterator<Triple> find(TripleMatch t, CompletionFlag complete) {
  374. // Node stmtURI = t.getMatchSubject(); // note: can be null
  375. // ResultSetReifIterator it = m_reif.findReifStmt(stmtURI, false, my_GID, true);
  376. // return it.filterKeep( new TripleMatchFilter( t.asTriple() ) );
  377. ResultSetReifIterator it = m_reif.findReifTripleMatch(t, my_GID);
  378. return it;
  379. }
  380. /**
  381. * Tests if a triple is contained in the specialized graph.
  382. * @param t is the triple to be tested
  383. * @param complete is true if the graph can guarantee that
  384. * no other specialized graph could hold any matching triples.
  385. * @return boolean result to indicate if the triple was contained
  386. */
  387. public boolean contains(Triple t, CompletionFlag complete) {
  388. // A very inefficient, but simple implementation
  389. ExtendedIterator<Triple> it = find( t, complete );
  390. try { return it.hasNext(); } finally { it.close(); }
  391. }
  392. /*
  393. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#close()
  394. */
  395. public void close() {
  396. m_reif.close();
  397. }
  398. /*
  399. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#clear()
  400. */
  401. public void clear() {
  402. m_reif.removeStatementsFromDB(my_GID);
  403. }
  404. static boolean isReifProp ( Node_URI p ) {
  405. return p.equals(RDF.Nodes.subject) ||
  406. p.equals(RDF.Nodes.predicate)||
  407. p.equals(RDF.Nodes.object) ||
  408. p.equals(RDF.Nodes.type);
  409. }
  410. /* (non-Javadoc)
  411. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#graphIdGet()
  412. */
  413. public int getGraphId() {
  414. return ((DBIDInt)my_GID).getIntID();
  415. }
  416. /* (non-Javadoc)
  417. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#PSetGet()
  418. */
  419. public IPSet getPSet() {
  420. return m_pset;
  421. }
  422. /* (non-Javadoc)
  423. * @see com.hp.hpl.jena.db.impl.SpecializedGraphReifier#DBPropLSetGet()
  424. */
  425. public DBPropLSet getDBPropLSet() {
  426. return m_dbPropLSet;
  427. }
  428. /*
  429. * (non-Javadoc)
  430. * @see com.hp.hpl.jena.db.impl.SpecializedGraph#subsumes(com.hp.hpl.jena.graph.Triple, int)
  431. *
  432. * determine if the reifier graph has any triples of the given pattern.
  433. * the table below indicates the return value for each reif style for
  434. * the various types of patterns.
  435. * note: "conc" means the node in the pattern is not a concrete node.
  436. *
  437. * Pattern Minimal Conv Standard
  438. * ANY rdf:subj ANY none none all
  439. * ANY rdf:pred ANY none none all
  440. * ANY rdf:obj ANY none none all
  441. * ANY rdf:type rdf:stmt none none all
  442. * ANY rdf:type conc none none none
  443. * ANY rdf:type !conc none none some
  444. * ANY !conc ANY none none some
  445. * else none none none
  446. */
  447. public char subsumes ( Triple pattern, int reifBehavior ) {
  448. char res = noTriplesForPattern;
  449. if ( reifBehavior != GraphRDB.OPTIMIZE_ALL_REIFICATIONS_AND_HIDE_NOTHING )
  450. return res;
  451. Node pred = pattern.getPredicate();
  452. if ( pred.isConcrete() ) {
  453. if ( pred.equals(RDF.Nodes.subject) ||
  454. pred.equals(RDF.Nodes.predicate) ||
  455. pred.equals(RDF.Nodes.object) )
  456. res = allTriplesForPattern;
  457. else if ( pred.equals(RDF.Nodes.type) ) {
  458. Node obj = pattern.getObject();
  459. if ( obj.equals(RDF.Nodes.Statement) )
  460. res = allTriplesForPattern;
  461. else if ( !obj.isConcrete() )
  462. res = someTriplesForPattern;
  463. }
  464. } else if ( (pred.isVariable()) || pred.equals(Node.ANY) ) {
  465. res = someTriplesForPattern;
  466. } else
  467. throw new JenaException("Unexpected predicate: " + pred.toString());
  468. return res;
  469. }
  470. }
  471. /*
  472. * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP
  473. * All rights reserved.
  474. *
  475. * Redistribution and use in source and binary forms, with or without
  476. * modification, are permitted provided that the following conditions
  477. * are met:
  478. * 1. Redistributions of source code must retain the above copyright
  479. * notice, this list of conditions and the following disclaimer.
  480. * 2. Redistributions in binary form must reproduce the above copyright
  481. * notice, this list of conditions and the following disclaimer in the
  482. * documentation and/or other materials provided with the distribution.
  483. * 3. The name of the author may not be used to endorse or promote products
  484. * derived from this software without specific prior written permission.
  485. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  486. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  487. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  488. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  489. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  490. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  491. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  492. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  493. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  494. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  495. */