001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.kernel.api.utils.iterators; 017 018import java.util.Iterator; 019 020import com.google.common.collect.AbstractIterator; 021import com.hp.hpl.jena.graph.Graph; 022import com.hp.hpl.jena.graph.Triple; 023import com.hp.hpl.jena.rdf.model.Model; 024 025import static com.hp.hpl.jena.graph.Node.ANY; 026import static com.hp.hpl.jena.sparql.graph.GraphFactory.createDefaultGraph; 027 028/** 029 * A wrapping {@link Iterator} that calculates two differences between a 030 * {@link Graph} A and a source Iterator B. The differences are (A - (A ∩ B)) and 031 * (B - (A ∩ B)). The ordinary output of this iterator is (B - (A ∩ B)), and 032 * after exhaustion, sets containing (A - (A ∩ B)) and (A ∩ B) are available. 033 * 034 * @author ajs6f 035 * @since Oct 24, 2013 036 */ 037public class GraphDifferencingIterator extends AbstractIterator<Triple> { 038 039 private Graph notCommon; 040 041 private Graph common; 042 043 private Iterator<Triple> source; 044 045 /** 046 * Diff a Model against a stream of triples 047 * 048 * @param replacement the replacement 049 * @param original the original 050 */ 051 public GraphDifferencingIterator(final Model replacement, 052 final Iterator<Triple> original) { 053 this(replacement.getGraph(), original); 054 } 055 056 /** 057 * Diff a graph against a stream of triples 058 * 059 * @param replacement the replacement 060 * @param original the original 061 */ 062 public GraphDifferencingIterator(final Graph replacement, 063 final Iterator<Triple> original) { 064 super(); 065 this.notCommon = replacement; 066 this.common = createDefaultGraph(); 067 this.source = original; 068 069 } 070 071 @Override 072 protected Triple computeNext() { 073 if (source.hasNext()) { 074 Triple next = source.next(); 075 // we only want to return this element if it is not common 076 // to the two inputs 077 while (common.contains(next) || notCommon.contains(next)) { 078 // it was common, so shift it to common 079 if (notCommon.contains(next)) { 080 notCommon.remove(next.getSubject(), next.getPredicate(), next.getObject()); 081 common.add(next); 082 } 083 // move onto the next candidate 084 if (!source.hasNext()) { 085 return endOfData(); 086 } 087 next = source.next(); 088 } 089 // it was not common so return it 090 return next; 091 } 092 return endOfData(); 093 } 094 095 /** 096 * This method will return null until the source iterator is exhausted. 097 * 098 * @return The elements that turned out to be common to the two inputs. 099 */ 100 public Iterator<Triple> common() { 101 return source.hasNext() ? null : common.find(ANY, ANY, ANY); 102 } 103 104 /** 105 * This method will return null until the source iterator is exhausted. 106 * 107 * @return The elements that turned out not to be common to the two inputs. 108 */ 109 public Iterator<Triple> notCommon() { 110 return source.hasNext() ? null : notCommon.find(ANY, ANY, ANY); 111 } 112 113}