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; 017 018import java.util.stream.Stream; 019 020import com.hp.hpl.jena.graph.Graph; 021import com.hp.hpl.jena.graph.Triple; 022import com.hp.hpl.jena.rdf.model.Model; 023 024import static java.util.Spliterator.IMMUTABLE; 025import static java.util.Spliterators.spliteratorUnknownSize; 026import static java.util.stream.StreamSupport.stream; 027import static com.hp.hpl.jena.graph.Node.ANY; 028import static com.hp.hpl.jena.sparql.graph.GraphFactory.createDefaultGraph; 029 030/** 031 * A wrapping {@link Stream} that calculates two differences between a 032 * {@link Graph} A and a source Stream B. The differences are (A - (A ∩ B)) and 033 * (B - (A ∩ B)). The ordinary output of this stream is (B - (A ∩ B)), and 034 * after exhaustion, sets containing (A - (A ∩ B)) and (A ∩ B) are available. 035 * 036 * @author ajs6f 037 * @author acoburn 038 * @since Oct 24, 2013 039 */ 040public class GraphDifferencer { 041 042 private Graph notCommon; 043 044 private Graph common; 045 046 private Stream.Builder<Triple> source = Stream.builder(); 047 048 /** 049 * Diff a Model against a stream of triples 050 * 051 * @param replacement the replacement 052 * @param original the original 053 */ 054 public GraphDifferencer(final Model replacement, 055 final Stream<Triple> original) { 056 this(replacement.getGraph(), original); 057 } 058 059 /** 060 * Diff a graph against a stream of triples 061 * 062 * @param replacement the replacement 063 * @param original the original 064 */ 065 public GraphDifferencer(final Graph replacement, 066 final Stream<Triple> original) { 067 notCommon = replacement; 068 common = createDefaultGraph(); 069 original.forEach(x -> { 070 if (notCommon.contains(x)) { 071 notCommon.remove(x.getSubject(), x.getPredicate(), x.getObject()); 072 common.add(x); 073 } else if (!common.contains(x)) { 074 source.accept(x); 075 } 076 }); 077 } 078 079 /** 080 * This method returns the difference between the two input sources. 081 * 082 * @return The differences between the two inputs. 083 */ 084 public Stream<Triple> difference() { 085 return source.build(); 086 } 087 088 /** 089 * This method will return null until the source iterator is exhausted. 090 * 091 * @return The elements that turned out to be common to the two inputs. 092 */ 093 public Stream<Triple> common() { 094 return stream(spliteratorUnknownSize(common.find(ANY, ANY, ANY), IMMUTABLE), false); 095 } 096 097 /** 098 * This method will return null until the source iterator is exhausted. 099 * 100 * @return The elements that turned out not to be common to the two inputs. 101 */ 102 public Stream<Triple> notCommon() { 103 return stream(spliteratorUnknownSize(notCommon.find(ANY, ANY, ANY), IMMUTABLE), false); 104 } 105}