/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.mem; import java.util.Iterator; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; import org.apache.jena.graph.impl.TripleStore ; import org.apache.jena.util.iterator.* ; public abstract class GraphTripleStoreBase implements TripleStore { protected final Graph parent; protected NodeToTriplesMapBase subjects; protected NodeToTriplesMapBase predicates; protected NodeToTriplesMapBase objects; protected GraphTripleStoreBase ( Graph parent, NodeToTriplesMapBase subjects, NodeToTriplesMapBase predicates, NodeToTriplesMapBase objects ) { this.parent = parent; this.subjects = subjects; this.objects = objects; this.predicates = predicates; } /** Destroy this triple store - discard the indexes. */ @Override public void close() { subjects = predicates = objects = null; } /** Add a triple to this triple store. */ @Override public void add( Triple t ) { if (subjects.add( t )) { predicates.add( t ); objects.add( t ); } } /** Remove a triple from this triple store. */ @Override public void delete( Triple t ) { if (subjects.remove( t )) { predicates.remove( t ); objects.remove( t ); } } /** Clear this store, ie remove all triples from it. */ @Override public void clear() { subjects.clear(); predicates.clear(); objects.clear(); } /** Answer the size (number of triples) of this triple store. */ @Override public int size() { return subjects.size(); } /** Answer true iff this triple store is empty. */ @Override public boolean isEmpty() { return subjects.isEmpty(); } @Override public ExtendedIterator<Node> listSubjects() { return expectOnlyNodes( subjects.domain() ); } @Override public ExtendedIterator<Node> listPredicates() { return expectOnlyNodes( predicates.domain() ); } private ExtendedIterator<Node> expectOnlyNodes( Iterator<Object> elements ) { return WrappedIterator.createNoRemove( elements ).mapWith( o -> (Node) o ); } @Override public ExtendedIterator<Node> listObjects() { return new ObjectIterator( objects.domain() ) { @Override protected Iterator <Triple>iteratorFor( Object y ) { return objects.iteratorForIndexed( y ); } }; } /** Answer true iff this triple store contains the (concrete) triple <code>t</code>. */ @Override public boolean contains( Triple t ) { return subjects.containsBySameValueAs( t ); } public boolean containsByEquality( Triple t ) { return subjects.contains( t ); } /** Answer an ExtendedIterator returning all the triples from this store that match the pattern <code>m = (S, P, O)</code>. <p>Because the node-to-triples maps index on each of subject, predicate, and (non-literal) object, concrete S/P/O patterns can immediately select an appropriate map. Because the match for literals must be by sameValueAs, not equality, the optimisation is not applied for literals. [This is probably a Bad Thing for strings.] <p>Practice suggests doing the predicate test <i>last</i>, because there are "usually" many more statements than predicates, so the predicate doesn't cut down the search space very much. By "practice suggests" I mean that when the order went, accidentally, from S/O/P to S/P/O, performance on (ANY, P, O) searches on largish models with few predicates declined dramatically - specifically on the not-galen.owl ontology. */ @Override public ExtendedIterator<Triple> find( Triple t ) { Node pm = t.getPredicate(); Node om = t.getObject(); Node sm = t.getSubject(); if (sm.isConcrete()) return new StoreTripleIterator( parent, subjects.iterator( sm, pm, om ), subjects, predicates, objects ); else if (om.isConcrete()) return new StoreTripleIterator( parent, objects.iterator( om, sm, pm ), objects, subjects, predicates ); else if (pm.isConcrete()) return new StoreTripleIterator( parent, predicates.iterator( pm, om, sm ), predicates, subjects, objects ); else return new StoreTripleIterator( parent, subjects.iterateAll(), subjects, predicates, objects ); } }