package org.linkeddatafragments.model; import com.google.common.primitives.Ints; import org.apache.jena.graph.*; import org.apache.jena.graph.impl.GraphBase; import org.apache.jena.graph.impl.GraphMatcher; import org.apache.jena.query.ARQ; import org.apache.jena.shared.AddDeniedException; import org.apache.jena.shared.ClosedException; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.sparql.engine.main.QC; import org.apache.jena.sparql.engine.optimizer.reorder.ReorderTransformation; import org.apache.jena.util.iterator.ClosableIterator; import org.apache.jena.util.iterator.ExtendedIterator; import org.apache.jena.util.iterator.WrappedIterator; import org.linkeddatafragments.client.LinkedDataFragmentsClient; import org.linkeddatafragments.solver.LDFStatistics; import org.linkeddatafragments.solver.LinkedDataFragmentEngine; import org.linkeddatafragments.solver.OpExecutorLDF; import org.linkeddatafragments.solver.ReorderTransformationLDF; public class LinkedDataFragmentGraph extends GraphBase { protected final LinkedDataFragmentsClient ldfClient; protected ReorderTransformation reorderTransform; protected LDFStatistics ldfStatistics; static { // Register OpExecutor QC.setFactory(ARQ.getContext(), OpExecutorLDF.opExecFactoryLDF); LinkedDataFragmentEngine.register(); } public LinkedDataFragmentGraph(String dataSource) { super(); this.ldfClient = new LinkedDataFragmentsClient(dataSource); this.reorderTransform=new ReorderTransformationLDF(this); this.ldfStatistics = new LDFStatistics(this); //must go after ldfClient created } /** Default implementation answers <code>true</code> iff this graph is the same graph as the argument graph. */ @Override public boolean dependsOn( Graph other ) { return ldfClient.getBaseFragment().getGraph() == other; } @Override public void add(Triple t) throws AddDeniedException { throw new UnsupportedOperationException(); } /** Answer the capabilities of this graph; the default is an AllCapabilities object (the same one each time, not that it matters - Capabilities should be immutable). */ @Override public Capabilities getCapabilities() { if (capabilities == null) capabilities = new LinkedDataFragmentGraphCapabilities(); return capabilities; } @Override protected ExtendedIterator<Triple> graphBaseFind(Triple m) { try{ LinkedDataFragment ldf = ldfClient.getFragment(ldfClient.getBaseFragment(), m); // ExtendedIterator<Triple> triples = ldf.getTriples(); // Iterator<LinkedDataFragment> ldfIterator = LinkedDataFragmentIterator.create(ldf, ldfClient); // while(ldfIterator.hasNext()) { // ldf = ldfIterator.next(); // triples = triples.andThen(ldf.getTriples()); // } ExtendedIterator<Triple> triples = ExtendedTripleIteratorLDF.create(ldfClient, ldf); return triples; } catch(Exception e) { e.printStackTrace(); return WrappedIterator.emptyIterator(); //Do not block on error but return empty iterator } } public Long getCount(Triple m) { //System.out.println("count requested"); try{ LinkedDataFragment ldf = ldfClient.getFragment(ldfClient.getBaseFragment(), m); Long count = ldf.getMatchCount(); //System.out.println(String.format("%s found", count)); return count; } catch(Exception e) { return 0L; } } public ReorderTransformation getReorderTransform() { return reorderTransform; } protected int graphBaseSize() { try{ return Ints.checkedCast(ldfClient.getBaseFragment().getTriplesSize()); } catch(IllegalArgumentException e) { return Integer.MAX_VALUE; //return a very high number } } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public GraphStatisticsHandler getStatisticsHandler() { if(this.ldfStatistics == null) { this.ldfStatistics = new LDFStatistics(this); } return this.ldfStatistics; } @Override public void remove(Node s, Node p, Node o) { throw new UnsupportedOperationException(); } /** Answer true iff this graph is isomorphic to <code>g</code> according to the algorithm (indeed, method) in <code>GraphMatcher</code>. */ @Override public boolean isIsomorphicWith( Graph g ) { checkOpen(); return g != null && GraphMatcher.equals(ldfClient.getBaseFragment().getGraph(), g); } /** Answer a human-consumable representation of this graph. Not advised for big graphs, as it generates a big string: intended for debugging purposes. */ /** Utility method: throw a ClosedException if this graph has been closed. */ protected void checkOpen() { if (closed) throw new ClosedException( "already closed", ldfClient.getBaseFragment().getGraph() ); } @Override public String toString() { return toString( (closed ? "closed " : ""), ldfClient.getBaseFragment().getGraph() ); } /** Answer a human-consumable representation of <code>that</code>. The string <code>prefix</code> will appear near the beginning of the string. Nodes may be prefix-compressed using <code>that</code>'s prefix-mapping. This default implementation will display all the triples exposed by the graph (ie including reification triples if it is Standard). */ public static String toString( String prefix, Graph that ) { PrefixMapping pm = that.getPrefixMapping(); StringBuffer b = new StringBuffer( prefix + " {" ); int count = 0; String gap = ""; ClosableIterator<Triple> it = GraphUtil.findAll(that); while (it.hasNext() && count < TOSTRING_TRIPLE_LIMIT) { b.append( gap ); gap = "; "; count += 1; b.append( it.next().toString( pm ) ); } if (it.hasNext()) b.append( "..." ); it.close(); b.append( "}" ); return b.toString(); } // @Override // protected ExtendedIterator<Triple> graphBaseFind(Triple triple) { // return find(triple); // } }