/* * 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 static org.apache.jena.util.iterator.WrappedIterator.create; import java.util.Iterator ; import java.util.function.Predicate; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; import org.apache.jena.graph.Triple.Field ; import org.apache.jena.shared.JenaException ; import org.apache.jena.util.iterator.ExtendedIterator ; import org.apache.jena.util.iterator.NullIterator ; public class NodeToTriplesMapMem extends NodeToTriplesMapBase { public NodeToTriplesMapMem( Field indexField, Field f2, Field f3 ) { super( indexField, f2, f3 ); } /** Add <code>t</code> to this NTM; the node <code>o</code> <i>must</i> be the index node of the triple. Answer <code>true</code> iff the triple was not previously in the set, ie, it really truly has been added. */ @Override public boolean add( Triple t ) { Object o = getIndexField( t ); // Feb 2016 : no measurable difference. //TripleBunch s = bunchMap.getOrSet(o, (k)->new ArrayBunch()) ; TripleBunch s = bunchMap.get( o ); if (s == null) bunchMap.put( o, s = new ArrayBunch() ); if (s.contains( t )) return false; else { if (s.size() == 9 && s instanceof ArrayBunch) bunchMap.put( o, s = new HashedTripleBunch( s ) ); s.add( t ); size += 1; return true; } } /** Remove <code>t</code> from this NTM. Answer <code>true</code> iff the triple was previously in the set, ie, it really truly has been removed. */ @Override public boolean remove( Triple t ) { Object o = getIndexField( t ); TripleBunch s = bunchMap.get( o ); if (s == null || !s.contains( t )) return false; else { s.remove( t ); size -= 1; if (s.size() == 0) bunchMap.remove( o ); return true; } } /** Answer an iterator over all the triples in this NTM which have index node <code>o</code>. */ @Override public Iterator<Triple> iterator( Object o, HashCommon.NotifyEmpty container ) { // System.err.println( ">> BOINK" ); // if (true) throw new JenaException( "BOINK" ); TripleBunch s = bunchMap.get( o ); return s == null ? NullIterator.<Triple>instance() : s.iterator( container ); } public class NotifyMe implements HashCommon.NotifyEmpty { protected final Object key; public NotifyMe( Object key ) { this.key = key; } // TODO fix the way this interacts (badly) with iteration and CMEs. @Override public void emptied() { if (false) throw new JenaException( "BOOM" ); /* System.err.println( ">> OOPS" ); */ bunchMap.remove( key ); } } /** Answer true iff this NTM contains the concrete triple <code>t</code>. */ @Override public boolean contains( Triple t ) { TripleBunch s = bunchMap.get( getIndexField( t ) ); return s == null ? false : s.contains( t ); } @Override public boolean containsBySameValueAs( Triple t ) { TripleBunch s = bunchMap.get( getIndexField( t ) ); return s == null ? false : s.containsBySameValueAs( t ); } /** Answer an iterator over all the triples in this NTM which match <code>pattern</code>. The index field of this NTM is guaranteed concrete in the pattern. */ @Override public ExtendedIterator<Triple> iterator( Node index, Node n2, Node n3 ) { Object indexValue = index.getIndexingValue(); TripleBunch s = bunchMap.get( indexValue ); // System.err.println( ">> ntmf::iterator: " + (s == null ? (Object) "None" : s.getClass()) ); if (s == null) return NullIterator.<Triple>instance(); final Predicate<Triple> filter = f2.filterOn( n2 ).and( f3.filterOn( n3 ) ); return create(s.iterator( new NotifyMe( indexValue ))).filterKeep(filter); } protected TripleBunch get( Object index ) { return bunchMap.get( index ); } /** Answer an iterator over all the triples that are indexed by the item <code>y</code>. Note that <code>y</code> need not be a Node (because of indexing values). */ @Override public Iterator<Triple> iteratorForIndexed( Object y ) { return get( y ).iterator(); } }