/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
*
* Licensed under the Aduna BSD-style license.
*/
package net.enilink.komma.core;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import net.enilink.commons.iterator.Filter;
import net.enilink.commons.iterator.FilterIterator;
/**
* Implementation of the {@link IGraph} interface using an underlying
* {@link LinkedHashSet}.
*/
public class LinkedHashGraph extends AbstractSet<IStatement> implements IGraph {
private static final long serialVersionUID = -9161104123818983614L;
static final IReference[] NULL_CTX = new IReference[] { null };
transient Map<Object, GraphNode<Object>> values;
transient Set<GraphStatement> statements;
public LinkedHashGraph() {
values = new HashMap<>();
statements = new LinkedHashSet<>();
}
public LinkedHashGraph(Collection<? extends IStatement> c) {
values = new HashMap<>(c.size() * 2);
statements = new LinkedHashSet<>(c.size());
addAll(c);
}
public LinkedHashGraph(int size) {
values = new HashMap<>(size * 2);
statements = new LinkedHashSet<>(size);
}
@Override
public int size() {
return statements.size();
}
@Override
public boolean add(IStatement st) {
return add(st.getSubject(), st.getPredicate(), st.getObject(),
st.getContext());
}
public boolean add(IReference subj, IReference pred, Object obj,
IReference... contexts) {
IReference[] ctxs = notNull(contexts);
if (ctxs.length == 0) {
ctxs = NULL_CTX;
}
boolean changed = false;
for (IReference ctx : ctxs) {
GraphNode<IReference> s = asNode(subj);
GraphNode<IReference> p = asNode(pred);
GraphNode<Object> o = asNode(obj);
GraphNode<IReference> c = asNode(ctx);
GraphStatement st = new GraphStatement(s, p, o, c, false);
changed |= addGraphStatement(st);
}
return changed;
}
@Override
public void clear() {
values.clear();
statements.clear();
}
@Override
public boolean remove(Object o) {
if (o instanceof Statement) {
Iterator<?> iter = find((Statement) o);
if (iter.hasNext()) {
iter.next();
iter.remove();
return true;
}
}
return false;
}
@Override
public boolean contains(Object o) {
if (o instanceof Statement) {
return find((Statement) o).hasNext();
}
return false;
}
@Override
public Iterator<IStatement> iterator() {
return match(null, null, null);
}
public boolean contains(IReference subj, IReference pred, Object obj,
IReference... contexts) {
return match(subj, pred, obj, contexts).hasNext();
}
public boolean remove(IReference subj, IReference pred, Object obj,
IReference... contexts) {
Iterator<?> iter = match(subj, pred, obj, contexts);
if (!iter.hasNext()) {
return false;
}
while (iter.hasNext()) {
iter.next();
iter.remove();
}
return true;
}
public boolean clear(IReference... contexts) {
return remove(null, null, null, contexts);
}
public IGraph filter(IReference subj, IReference pred, Object obj,
IReference... contexts) {
return new FilteredGraph(subj, pred, obj, contexts);
}
public Set<IReference> subjects() {
return subjects(null, null);
}
public Set<IReference> predicates() {
return predicates(null, null);
}
public Set<Object> objects() {
return objects(null, null);
}
public Set<IReference> contexts() {
return contexts(null, null, null);
}
public Object objectValue() throws KommaException {
Iterator<Object> iter = objects().iterator();
if (iter.hasNext()) {
Object obj = iter.next();
if (iter.hasNext()) {
throw new KommaException();
}
return obj;
}
return null;
}
public ILiteral objectLiteral() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof ILiteral) {
return (ILiteral) obj;
}
throw new KommaException();
}
public IReference objectReference() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof IReference) {
return (IReference) obj;
}
throw new KommaException();
}
public String objectString() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof ILiteral) {
return ((ILiteral) obj).getLabel();
}
return obj.toString();
}
@Override
public void rename(IReference source, IReference target) {
LinkedHashGraph.rename(this, source, target);
}
static void rename(IGraph graph, IReference source, IReference target) {
Iterator<IStatement> it = graph.iterator();
List<IStatement> newStatements = new ArrayList<>();
while (it.hasNext()) {
IStatement stmt = it.next();
IReference s = stmt.getSubject();
IReference p = stmt.getPredicate();
Object o = stmt.getObject();
boolean changed = false;
if (source.equals(s)) {
s = target;
changed = true;
}
if (source.equals(p)) {
p = target;
changed = true;
}
if (source.equals(o)) {
o = target;
changed = true;
}
if (changed) {
it.remove();
}
newStatements.add(new Statement(s, p, o, stmt.getContext()));
}
graph.addAll(newStatements);
}
@Override
public int hashCode() {
return size();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof IGraph) {
IGraph graph = (IGraph) o;
return GraphUtil.equals(this, graph);
}
return false;
}
Set<IReference> contexts(final IReference subj, final IReference pred,
final Object obj) {
return new ObjectSet<IReference>() {
@Override
public boolean contains(Object o) {
if (o instanceof IReference || o == null) {
return LinkedHashGraph.this.contains(subj, pred, obj,
(IReference) o);
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof IReference || o == null) {
return LinkedHashGraph.this.remove(subj, pred, obj,
(IReference) o);
}
return false;
}
@Override
public boolean add(IReference ctx) {
if (subj == null || pred == null || obj == null) {
throw new UnsupportedOperationException(
"Incomplete statement");
}
if (contains(ctx)) {
return false;
}
return LinkedHashGraph.this.add(subj, pred, obj, ctx);
}
@Override
public void clear() {
LinkedHashGraph.this.remove(subj, pred, obj);
}
@Override
protected GraphIterator statementIterator() {
return match(subj, pred, obj);
}
@Override
protected GraphNode<IReference> node(GraphStatement st) {
return st.ctx;
}
@Override
protected Set<GraphStatement> set(GraphNode<IReference> node) {
return node.contexts;
}
};
}
Set<Object> objects(final IReference subj, final IReference pred,
final IReference... contexts) {
return new ObjectSet<Object>() {
@Override
public boolean contains(Object o) {
if (o instanceof Object) {
return LinkedHashGraph.this.contains(subj, pred,
(Object) o, contexts);
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof Object) {
return LinkedHashGraph.this.remove(subj, pred, (Object) o,
contexts);
}
return false;
}
@Override
public boolean add(Object obj) {
if (subj == null || pred == null) {
throw new UnsupportedOperationException(
"Incomplete statement");
}
if (contains(obj)) {
return false;
}
return LinkedHashGraph.this.add(subj, pred, obj, contexts);
}
@Override
public void clear() {
LinkedHashGraph.this.remove(subj, pred, null, contexts);
}
@Override
protected GraphIterator statementIterator() {
return match(subj, pred, null, contexts);
}
@Override
protected GraphNode<Object> node(GraphStatement st) {
return st.obj;
}
@Override
protected Set<GraphStatement> set(GraphNode<Object> node) {
return node.objects;
}
};
}
Set<IReference> predicates(final IReference subj, final Object obj,
final IReference... contexts) {
return new ObjectSet<IReference>() {
@Override
public boolean contains(Object o) {
if (o instanceof IReference) {
return LinkedHashGraph.this.contains(subj, (IReference) o,
obj, contexts);
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof IReference) {
return LinkedHashGraph.this.remove(subj, (IReference) o,
obj, contexts);
}
return false;
}
@Override
public boolean add(IReference pred) {
if (subj == null || obj == null) {
throw new UnsupportedOperationException(
"Incomplete statement");
}
if (contains(pred)) {
return false;
}
return LinkedHashGraph.this.add(subj, pred, obj, contexts);
}
@Override
public void clear() {
LinkedHashGraph.this.remove(subj, null, obj, contexts);
}
@Override
protected GraphIterator statementIterator() {
return match(subj, null, obj, contexts);
}
@Override
protected GraphNode<IReference> node(GraphStatement st) {
return st.pred;
}
@Override
protected Set<GraphStatement> set(GraphNode<IReference> node) {
return node.predicates;
}
};
}
Set<IReference> subjects(final IReference pred, final Object obj,
final IReference... contexts) {
return new ObjectSet<IReference>() {
@Override
public boolean contains(Object o) {
if (o instanceof IReference) {
return LinkedHashGraph.this.contains((IReference) o, pred,
obj, contexts);
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof IReference) {
return LinkedHashGraph.this.remove((IReference) o, pred,
obj, contexts);
}
return false;
}
@Override
public boolean add(IReference subj) {
if (pred == null || obj == null) {
throw new UnsupportedOperationException(
"Incomplete statement");
}
if (contains(subj)) {
return false;
}
return LinkedHashGraph.this.add(subj, pred, obj, contexts);
}
@Override
public void clear() {
LinkedHashGraph.this.remove(null, pred, obj, contexts);
}
@Override
protected GraphIterator statementIterator() {
return match(null, pred, obj, contexts);
}
@Override
protected GraphNode<IReference> node(GraphStatement st) {
return st.subj;
}
@Override
protected Set<GraphStatement> set(GraphNode<IReference> node) {
return node.subjects;
}
};
}
protected GraphIterator match(IReference subj, IReference pred, Object obj,
IReference... contexts) {
assert contexts != null;
Set<GraphStatement> s = null;
Set<GraphStatement> p = null;
Set<GraphStatement> o = null;
if (subj != null) {
if (!values.containsKey(subj)) {
return emptyGraphIterator();
}
s = values.get(subj).subjects;
}
if (pred != null) {
if (!values.containsKey(pred)) {
return emptyGraphIterator();
}
p = values.get(pred).predicates;
}
if (obj != null) {
if (!values.containsKey(obj)) {
return emptyGraphIterator();
}
o = values.get(obj).objects;
}
Set<GraphStatement> set;
contexts = notNull(contexts);
if (contexts.length == 1) {
if (!values.containsKey(contexts[0])) {
return emptyGraphIterator();
}
Set<GraphStatement> c = values.get(contexts[0]).contexts;
set = smallest(statements, s, p, o, c);
} else {
set = smallest(statements, s, p, o);
}
return new GraphIterator(new PatternIterator<>(set.iterator(), subj,
pred, obj, contexts), set);
}
boolean matches(IStatement st, IReference subj, IReference pred,
Object obj, IReference... contexts) {
if (subj != null && !subj.equals(st.getSubject())) {
return false;
}
if (pred != null && !pred.equals(st.getPredicate())) {
return false;
}
if (obj != null && !obj.equals(st.getObject())) {
return false;
}
return matches(st.getContext(), contexts);
}
boolean matches(IReference[] stContext, IReference... contexts) {
if (stContext != null && stContext.length > 0) {
for (IReference c : stContext) {
if (!matches(c, contexts)) {
return false;
}
}
}
return true;
}
boolean matches(IReference stContext, IReference... contexts) {
if (contexts != null && contexts.length == 0) {
// Any context matches
return true;
} else {
// Accept if one of the contexts from the pattern matches
for (IReference context : notNull(contexts)) {
if (context == null && stContext == null) {
return true;
}
if (context != null && context.equals(stContext)) {
return true;
}
}
return false;
}
}
IGraph emptyGraph = new EmptyGraph();
protected IGraph emptyGraph() {
return emptyGraph;
}
GraphIterator emptyGraphIterator() {
Set<GraphStatement> set = Collections.emptySet();
return new GraphIterator(set.iterator(), set);
}
protected class EmptyGraph extends AbstractSet<IStatement> implements
IGraph {
private static final long serialVersionUID = 3123007631452759092L;
private Set<IStatement> emptySet = Collections.emptySet();
@Override
public Iterator<IStatement> iterator() {
return emptySet.iterator();
}
@Override
public int size() {
return 0;
}
@Override
public boolean add(IStatement e) {
throw new UnsupportedOperationException(
"All statements are filtered out of view");
}
public boolean add(IReference subj, IReference pred, Object obj,
IReference... contexts) {
throw new UnsupportedOperationException(
"All statements are filtered out of view");
}
public boolean clear(IReference... context) {
return false;
}
public boolean contains(IReference subj, IReference pred, Object obj,
IReference... contexts) {
return false;
}
public Set<IReference> contexts() {
return Collections.emptySet();
}
public IGraph filter(IReference subj, IReference pred, Object obj,
IReference... contexts) {
return emptyGraph();
}
public Set<Object> objects() {
return Collections.emptySet();
}
public Set<IReference> predicates() {
return Collections.emptySet();
}
public boolean remove(IReference subj, IReference pred, Object obj,
IReference... contexts) {
return false;
}
public Set<IReference> subjects() {
return Collections.emptySet();
}
public ILiteral objectLiteral() {
return null;
}
public Object objectValue() {
return null;
}
public IReference objectReference() {
return null;
}
public String objectString() {
return null;
}
@Override
public void rename(IReference source, IReference target) {
}
@Override
public int hashCode() {
return size();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof IGraph) {
IGraph model = (IGraph) o;
return model.isEmpty();
}
return false;
}
}
protected class FilteredGraph extends AbstractSet<IStatement> implements
IGraph {
private static final long serialVersionUID = -2353344619836326934L;
protected IReference subj;
protected IReference pred;
protected Object obj;
protected IReference[] contexts;
public FilteredGraph(IReference subj, IReference pred, Object obj,
IReference... contexts) {
this.subj = subj;
this.pred = pred;
this.obj = obj;
this.contexts = notNull(contexts);
}
@Override
public Iterator<IStatement> iterator() {
return match(subj, pred, obj, contexts);
}
@Override
public int size() {
int size = 0;
Iterator<IStatement> iter = iterator();
while (iter.hasNext()) {
size++;
iter.next();
}
return size;
}
@Override
public boolean contains(Object o) {
if (o instanceof Statement) {
Statement st = (Statement) o;
if (accept(st)) {
return LinkedHashGraph.this.contains(o);
}
}
return false;
}
@Override
public boolean add(IStatement st) {
if (accept(st)) {
return LinkedHashGraph.this.add(st);
}
throw new IllegalArgumentException(
"Statement is filtered out of view: " + st);
}
public boolean add(IReference s, IReference p, Object o,
IReference... c) {
if (!accept(s, p, o, c)) {
throw new IllegalArgumentException(
"Statement is filtered out of view");
}
if (s == null) {
s = subj;
}
if (p == null) {
p = pred;
}
if (o == null) {
o = obj;
}
if (c != null && c.length == 0) {
c = contexts;
}
return LinkedHashGraph.this.add(s, p, o, c);
}
@Override
public void clear() {
LinkedHashGraph.this.remove(subj, pred, obj, contexts);
}
public boolean clear(IReference... c) {
c = notNull(c);
if (c.length == 0) {
return remove(subj, pred, obj, contexts);
} else if (matches(c, contexts)) {
return LinkedHashGraph.this.remove(subj, pred, obj, c);
} else {
return false;
}
}
public boolean remove(IReference s, IReference p, Object o,
IReference... c) {
if (!accept(s, p, o, c)) {
return false;
}
if (s == null) {
s = subj;
}
if (p == null) {
p = pred;
}
if (o == null) {
o = obj;
}
if (c != null && c.length == 0) {
c = contexts;
}
return LinkedHashGraph.this.remove(s, p, o, c);
}
public boolean contains(IReference s, IReference p, Object o,
IReference... c) {
if (!accept(s, p, o, c)) {
return false;
}
if (s == null) {
s = subj;
}
if (p == null) {
p = pred;
}
if (o == null) {
o = obj;
}
if (c != null && c.length == 0) {
c = contexts;
}
return LinkedHashGraph.this.contains(s, p, o, c);
}
public IGraph filter(IReference s, IReference p, Object o,
IReference... c) {
if (!accept(s, p, o, c)) {
return emptyGraph();
}
if (s == null) {
s = subj;
}
if (p == null) {
p = pred;
}
if (o == null) {
o = obj;
}
if (c != null && c.length == 0) {
c = contexts;
}
return LinkedHashGraph.this.filter(s, p, o, c);
}
public Set<IReference> contexts() {
if (contexts != null && contexts.length > 0) {
return unmodifiableSet(new LinkedHashSet<IReference>(
asList(contexts)));
}
return LinkedHashGraph.this.contexts(subj, pred, obj);
}
public Set<Object> objects() {
if (obj != null) {
return Collections.singleton(obj);
}
return LinkedHashGraph.this.objects(subj, pred, contexts);
}
public Set<IReference> predicates() {
if (pred != null) {
return Collections.singleton(pred);
}
return LinkedHashGraph.this.predicates(subj, obj, contexts);
}
public Set<IReference> subjects() {
if (subj != null) {
return Collections.singleton(subj);
}
return LinkedHashGraph.this.subjects(pred, obj, contexts);
}
public Object objectValue() throws KommaException {
Iterator<Object> iter = objects().iterator();
if (iter.hasNext()) {
Object obj = iter.next();
if (iter.hasNext()) {
throw new KommaException();
}
return obj;
}
return null;
}
public ILiteral objectLiteral() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof ILiteral) {
return (ILiteral) obj;
}
throw new KommaException();
}
public IReference objectReference() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof IReference) {
return (IReference) obj;
}
throw new KommaException();
}
public String objectString() throws KommaException {
Object obj = objectValue();
if (obj == null) {
return null;
}
if (obj instanceof ILiteral) {
return ((ILiteral) obj).getLabel();
}
return obj.toString();
}
@Override
public void rename(IReference source, IReference target) {
LinkedHashGraph.rename(this, source, target);
}
@Override
public int hashCode() {
return size();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof IGraph) {
IGraph model = (IGraph) o;
return GraphUtil.equals(this, model);
}
return false;
}
private boolean accept(IStatement st) {
return matches(st, subj, pred, obj, contexts);
}
private boolean accept(IReference s, IReference p, Object o,
IReference... c) {
if (subj != null && !subj.equals(s)) {
return false;
}
if (pred != null && !pred.equals(p)) {
return false;
}
if (obj != null && !obj.equals(o)) {
return false;
}
if (!matches(notNull(c), contexts)) {
return false;
}
return true;
}
}
abstract protected class ObjectSet<V> extends AbstractSet<V> {
@Override
public Iterator<V> iterator() {
final Set<V> set = new LinkedHashSet<V>();
final GraphIterator iter = statementIterator();
return new Iterator<V>() {
private GraphStatement current;
private GraphStatement next;
public boolean hasNext() {
if (next == null) {
next = findNext();
}
return next != null;
}
public V next() {
if (next == null) {
next = findNext();
if (next == null) {
throw new NoSuchElementException();
}
}
current = next;
next = null;
V value = convert(current);
set.add(value);
return value;
}
public void remove() {
if (current == null) {
throw new IllegalStateException();
}
removeAll(set(node(current)), iter.getOwner());
current = null;
}
private GraphStatement findNext() {
while (iter.hasNext()) {
GraphStatement st = iter.next();
if (accept(st)) {
return st;
}
}
return null;
}
private boolean accept(GraphStatement st) {
return !set.contains(convert(st));
}
private V convert(GraphStatement st) {
return node(st).getObject();
}
};
}
@Override
public int size() {
Set<V> set = new LinkedHashSet<V>();
Iterator<IStatement> iter = statementIterator();
while (iter.hasNext()) {
set.add(node((GraphStatement) iter.next()).getObject());
}
return set.size();
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o) {
if (values.containsKey(o)) {
return removeAll(set((GraphNode<V>) values.get(o)), null);
}
return false;
}
protected abstract GraphIterator statementIterator();
protected abstract GraphNode<V> node(GraphStatement st);
protected abstract Set<GraphStatement> set(GraphNode<V> node);
boolean removeAll(Set<GraphStatement> remove, Set<GraphStatement> owner) {
if (remove.isEmpty()) {
return false;
}
for (GraphStatement st : remove) {
GraphNode<IReference> subj = st.subj;
Set<GraphStatement> subjects = subj.subjects;
if (subjects == owner) {
subj.subjects = new LinkedHashSet<GraphStatement>(owner);
subj.subjects.removeAll(remove);
} else if (subjects != remove) {
subjects.remove(st);
}
GraphNode<IReference> pred = st.pred;
Set<GraphStatement> predicates = pred.predicates;
if (predicates == owner) {
pred.predicates = new LinkedHashSet<GraphStatement>(owner);
pred.predicates.removeAll(remove);
} else if (predicates != remove) {
predicates.remove(st);
}
GraphNode<Object> obj = st.obj;
Set<GraphStatement> objects = obj.objects;
if (objects == owner) {
obj.objects = new LinkedHashSet<GraphStatement>(owner);
obj.objects.removeAll(remove);
} else if (objects != remove) {
objects.remove(st);
}
GraphNode<IReference> ctx = st.ctx;
Set<GraphStatement> contexts = ctx.contexts;
if (contexts == owner) {
ctx.contexts = new LinkedHashSet<GraphStatement>(owner);
ctx.contexts.removeAll(remove);
} else if (contexts != remove) {
contexts.remove(st);
}
if (statements == owner) {
statements = new LinkedHashSet<GraphStatement>(statements);
statements.removeAll(remove);
} else if (statements != remove && statements != owner) {
statements.remove(st);
}
}
remove.clear();
return true;
}
}
protected class GraphIterator implements Iterator<IStatement> {
private Iterator<GraphStatement> iter;
private Set<GraphStatement> owner;
private GraphStatement last;
public GraphIterator(Iterator<GraphStatement> iter,
Set<GraphStatement> owner) {
this.iter = iter;
this.owner = owner;
}
public Set<GraphStatement> getOwner() {
return owner;
}
public boolean hasNext() {
return iter.hasNext();
}
public GraphStatement next() {
return last = iter.next();
}
public void remove() {
if (last == null) {
throw new IllegalStateException();
}
removeIfNotOwner(statements);
removeIfNotOwner(last.subj.subjects);
removeIfNotOwner(last.pred.predicates);
removeIfNotOwner(last.obj.objects);
removeIfNotOwner(last.ctx.contexts);
iter.remove(); // remove from owner
}
private void removeIfNotOwner(Set<GraphStatement> subjects) {
if (subjects != owner) {
subjects.remove(last);
}
}
}
protected class GraphNode<V extends Object> implements Serializable {
private static final long serialVersionUID = -1205676084606998540L;
Set<GraphStatement> subjects = new LinkedHashSet<GraphStatement>();
Set<GraphStatement> predicates = new LinkedHashSet<GraphStatement>();
Set<GraphStatement> objects = new LinkedHashSet<GraphStatement>();
Set<GraphStatement> contexts = new LinkedHashSet<GraphStatement>();
private V value;
public GraphNode(V value) {
this.value = value;
}
public V getObject() {
return value;
}
public boolean isNull() {
return value == null;
}
}
protected class GraphStatement implements IStatement {
GraphNode<IReference> subj;
GraphNode<IReference> pred;
GraphNode<Object> obj;
GraphNode<IReference> ctx;
boolean isInferred;
public GraphStatement(GraphNode<IReference> subj,
GraphNode<IReference> pred, GraphNode<Object> obj,
GraphNode<IReference> ctx, boolean isInferred) {
assert subj != null;
assert pred != null;
assert obj != null;
assert ctx != null;
this.subj = subj;
this.pred = pred;
this.obj = obj;
this.ctx = ctx;
this.isInferred = isInferred;
}
public IReference getSubject() {
return subj.getObject();
}
public IReference getPredicate() {
return pred.getObject();
}
public Object getObject() {
return obj.getObject();
}
public IReference getContext() {
return ctx.getObject();
}
@Override
public boolean isInferred() {
return isInferred;
}
@Override
public boolean equalsIgnoreContext(IStatementPattern other) {
return Statements.equalsIgnoreContext(this, other);
}
@Override
public boolean equals(Object obj) {
return Statements.equals(this, obj);
}
@Override
public int hashCode() {
return Statements.hashCode(this);
}
@Override
public String toString() {
return Statements.toString(this);
}
@Override
public Iterator<IStatement> iterator() {
return Collections.<IStatement> singleton(this).iterator();
}
}
protected class PatternIterator<S extends IStatement> extends
FilterIterator<S> {
public PatternIterator(Iterator<S> iter, final IReference subj,
final IReference pred, final Object obj,
final IReference... contexts) {
super(new Filter<S>() {
IReference[] ctxs = notNull(contexts);
public boolean accept(S st) {
return matches(st, subj, pred, obj, ctxs);
}
}, iter);
}
}
private void writeObject(ObjectOutputStream s) throws IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write in size
s.writeInt(statements.size());
// Write in all elements
for (GraphStatement st : statements) {
IReference subj = st.getSubject();
IReference pred = st.getPredicate();
Object obj = st.getObject();
IReference ctx = st.getContext();
s.writeObject(new Statement(subj, pred, obj, ctx));
}
}
private void readObject(ObjectInputStream s) throws IOException,
ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
values = new HashMap<>(size * 2);
statements = new LinkedHashSet<>(size);
// Read in all elements
for (int i = 0; i < size; i++) {
Statement st = (Statement) s.readObject();
add(st);
}
}
private Iterator<?> find(Statement st) {
IReference subj = st.getSubject();
IReference pred = st.getPredicate();
Object obj = st.getObject();
IReference ctx = st.getContext();
return match(subj, pred, obj, ctx);
}
private boolean addGraphStatement(GraphStatement st) {
Set<GraphStatement> subj = st.subj.subjects;
Set<GraphStatement> pred = st.pred.predicates;
Set<GraphStatement> obj = st.obj.objects;
Set<GraphStatement> ctx = st.ctx.contexts;
if (smallest(subj, pred, obj, ctx).contains(st)) {
return false;
}
statements.add(st);
subj.add(st);
pred.add(st);
obj.add(st);
ctx.add(st);
return true;
}
@SafeVarargs
private final <V> Set<V> smallest(Set<V>... sets) {
int minSize = Integer.MAX_VALUE;
Set<V> minSet = null;
for (Set<V> set : sets) {
if (set != null && set.size() < minSize) {
minSet = set;
}
}
return minSet;
}
@SuppressWarnings("unchecked")
private <V> GraphNode<V> asNode(V value) {
if (values.containsKey(value)) {
return (GraphNode<V>) values.get(value);
}
GraphNode<V> node = new GraphNode<>(value);
values.put(value, (GraphNode<Object>) node);
return node;
}
private static final IReference[] DEFAULT_CONTEXTS = new IReference[] { null };
/**
* Verifies that the supplied contexts parameter is not <tt>null</tt>,
* returning the default context if it is.
*
* @param contexts
* The parameter to check.
* @return a non-null array
*/
public static IReference[] notNull(IReference... contexts) {
if (contexts == null) {
return DEFAULT_CONTEXTS;
}
return contexts;
}
}