001: /*
002: * LICENSE INFORMATION
003: * Copyright 2005-2007 by FZI (http://www.fzi.de).
004: * Licensed under a BSD license (http://www.opensource.org/licenses/bsd-license.php)
005: * <OWNER> = Max Völkel
006: * <ORGANIZATION> = FZI Forschungszentrum Informatik Karlsruhe, Karlsruhe, Germany
007: * <YEAR> = 2007
008: *
009: * Project information at http://semweb4j.org/rdf2go
010: */
011: package org.ontoware.rdf2go.model.impl;
012:
013: import java.util.ArrayList;
014: import java.util.Collections;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Set;
019:
020: import org.ontoware.aifbcommons.collection.ClosableIterator;
021: import org.ontoware.rdf2go.exception.LockException;
022: import org.ontoware.rdf2go.exception.ModelRuntimeException;
023: import org.ontoware.rdf2go.model.Diff;
024: import org.ontoware.rdf2go.model.DiffReader;
025: import org.ontoware.rdf2go.model.Statement;
026: import org.ontoware.rdf2go.model.node.Node;
027: import org.ontoware.rdf2go.model.node.Resource;
028: import org.ontoware.rdf2go.model.node.URI;
029: import org.slf4j.Logger;
030: import org.slf4j.LoggerFactory;
031:
032: public class DiffImpl extends AbstractModelAddRemove implements Diff {
033:
034: private static final Logger log = LoggerFactory
035: .getLogger(DiffImpl.class);
036:
037: private Set<Statement> addedSet;
038:
039: private Set<Statement> removedSet;
040:
041: public DiffImpl() {
042: this .addedSet = new HashSet<Statement>();
043: this .removedSet = new HashSet<Statement>();
044: }
045:
046: public DiffImpl(Iterator<? extends Statement> added,
047: Iterator<? extends Statement> removed) {
048: this ();
049: while (added.hasNext()) {
050: this .addedSet.add(added.next());
051: }
052: while (removed.hasNext()) {
053: Statement stmt = removed.next();
054: if (this .addedSet.contains(stmt)) {
055: // adding and removing the same statement is a do-nothing-operation
056: this .addedSet.remove(stmt);
057: } else {
058: this .removedSet.add(stmt);
059: }
060: }
061: }
062:
063: public Diff create(Iterator<? extends Statement> added,
064: Iterator<? extends Statement> removed) {
065: return new DiffImpl(added, removed);
066: }
067:
068: public Iterable<Statement> getAdded() {
069: return this .addedSet;
070: }
071:
072: public Iterable<Statement> getRemoved() {
073: return this .removedSet;
074: }
075:
076: @Override
077: public void removeStatement(Statement statement)
078: throws ModelRuntimeException {
079: removedSet.add(statement);
080: }
081:
082: @Override
083: public void removeAll(Iterator<? extends Statement> other)
084: throws ModelRuntimeException {
085: while (other.hasNext()) {
086: removeStatement(other.next());
087: }
088: }
089:
090: @Override
091: public void removeAll() throws ModelRuntimeException {
092: throw new UnsupportedOperationException(
093: "It doesn't make sense to 'remove all' on a Diff");
094: }
095:
096: public ClosableIterator<Statement> iterator() {
097: throw new UnsupportedOperationException(
098: "Please iterate over getAdded or getRemoved instead");
099: }
100:
101: @Override
102: public void addStatement(Statement statement)
103: throws ModelRuntimeException {
104: this .addedSet.add(statement);
105: }
106:
107: @Override
108: public void addAll(Iterator<? extends Statement> other)
109: throws ModelRuntimeException {
110: while (other.hasNext()) {
111: addStatement(other.next());
112: }
113: }
114:
115: public Diff getDiff(Iterator<? extends Statement> statements)
116: throws ModelRuntimeException {
117: throw new UnsupportedOperationException(
118: "Doens't make sense for a diff");
119: }
120:
121: @Override
122: public void update(DiffReader diff) throws ModelRuntimeException {
123: addAll(diff.getAdded().iterator());
124: removeAll(diff.getRemoved().iterator());
125: }
126:
127: public void lock() throws LockException {
128: throw new UnsupportedOperationException(
129: "Doens't make sense for a diff");
130: }
131:
132: public boolean isLocked() {
133: throw new UnsupportedOperationException(
134: "Doens't make sense for a diff");
135: }
136:
137: public void unlock() {
138: throw new UnsupportedOperationException(
139: "Doens't make sense for a diff");
140: }
141:
142: @Override
143: public void addStatement(Resource subject, URI predicate,
144: Node object) throws ModelRuntimeException {
145: addStatement(new StatementImpl(null, subject, predicate, object));
146: }
147:
148: @Override
149: public void removeStatement(Resource subject, URI predicate,
150: Node object) throws ModelRuntimeException {
151: removeStatement(new StatementImpl(null, subject, predicate,
152: object));
153: }
154:
155: public void dump() {
156: log.debug("Dumping diff to System.out");
157: List<Statement> added = new ArrayList<Statement>();
158: for (Statement s : getAdded()) {
159: added.add(s);
160: }
161: Collections.sort(added);
162: for (Statement s : added) {
163: System.out.println("[+] " + s);
164: }
165:
166: // removed
167: List<Statement> removed = new ArrayList<Statement>();
168: for (Statement s : getRemoved()) {
169: removed.add(s);
170: }
171: Collections.sort(removed);
172: for (Statement s : removed) {
173: System.out.println("[-] " + s);
174: }
175: }
176:
177: public static final boolean equals(Set<Statement> a,
178: Set<Statement> b) {
179: if (a.size() == b.size()) {
180: for (Statement s : a) {
181: if (!b.contains(s))
182: return false;
183: }
184: return true;
185: }
186: // else
187: return false;
188: }
189:
190: @Override
191: public boolean equals(Object other) {
192: if (other instanceof Diff) {
193:
194: Diff diff = (Diff) other;
195:
196: try {
197: log.debug("Comparing two diffs");
198: // IMPROVE compare less expensive
199: ModelAddRemoveMemoryImpl otherAdded = new ModelAddRemoveMemoryImpl();
200: otherAdded.addAll(diff.getAdded().iterator());
201:
202: ModelAddRemoveMemoryImpl otherRemoved = new ModelAddRemoveMemoryImpl();
203: otherRemoved.addAll(diff.getRemoved().iterator());
204:
205: log.debug("This diff: " + this .addedSet.size()
206: + " added and " + this .removedSet.size()
207: + " removed");
208: log.debug("Other diff: " + otherAdded.set.size()
209: + " added and " + otherRemoved.set.size()
210: + " removed");
211:
212: // now compare the sets of statements
213:
214: return equals(this .addedSet, otherAdded.getSet())
215: && equals(this .removedSet, otherRemoved
216: .getSet());
217:
218: } catch (ModelRuntimeException e) {
219: throw new RuntimeException(e);
220: }
221: }
222: // else
223: if (other == null) {
224: log.debug("other is null, but not a DiffImpl");
225: } else {
226: log.debug("other is not a diff but " + other.getClass());
227: }
228: return false;
229: }
230:
231: @Override
232: public int hashCode() {
233: return this.addedSet.hashCode() + this.removedSet.hashCode();
234: }
235:
236: }
|