clerezza-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [03/14] clerezza git commit: CLEREZZA-966: moved rdf.utils into the hierarchy
Date Sun, 22 Mar 2015 22:04:46 GMT
http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphNode.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphNode.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphNode.java
new file mode 100644
index 0000000..8a1365f
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphNode.java
@@ -0,0 +1,722 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import org.apache.commons.rdf.impl.*;
+import org.apache.commons.rdf.impl.utils.*;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import org.apache.clerezza.rdf.core.LiteralFactory;
+import org.apache.commons.rdf.*;
+
+/**
+ * This class represents a node in the context of a graph. It provides
+ * utility methods to explore and modify its neighbourhood. The method
+ * modifying the graph will throw an {@link UnsupportedOperationException}
+ * it the underlying Graph in immutable (i.e. is a {@link ImmutableGraph}.
+ *
+ * @since 0.2
+ * @author reto, mir
+ */
+public class GraphNode {
+
+    private final RdfTerm resource;
+    private final Graph graph;
+
+    /**
+     * Create a GraphNode representing resource within graph.
+     *
+     * @param resource the resource this GraphNode represents
+     * @param graph the Graph that describes the resource
+     */
+    public GraphNode(RdfTerm resource, Graph graph) {
+        if (resource == null) {
+            throw new IllegalArgumentException("resource may not be null");
+        }
+        if (graph == null) {
+            throw new IllegalArgumentException("graph may not be null");
+        }
+        this.resource = resource;
+        this.graph = graph;
+    }
+
+    /**
+     * Gets the graph the node represented by this instance is in
+     *
+     * @return the graph of this GraphNode
+     */
+    public Graph getGraph() {
+        return graph;
+    }
+
+    /**
+     * Gets the unwrapped node
+     *
+     * @return the node represented by this GraphNode
+     */
+    public RdfTerm getNode() {
+        return resource;
+    }
+
+    /**
+     * Deletes the context of a node
+     * @see getNodeContext()
+     */
+    public void deleteNodeContext() {
+        for (Triple triple : getNodeContext()) {
+            graph.remove(triple);
+        }
+    }
+
+    /**
+     * The context of a node are the triples containing a node
+     * as subject or object and recursively the context of the b-nodes in any
+     * of these statements.
+     *
+     * The triples in the ImmutableGraph returned by this method contain the same bnode
+     * instances as in the original graph.
+     *
+     * @return the context of the node represented by the instance
+     */
+    public ImmutableGraph getNodeContext() {
+        Lock l = readLock();
+        l.lock();
+        try {
+            final HashSet<RdfTerm> dontExpand = new HashSet<RdfTerm>();
+            dontExpand.add(resource);
+            if (resource instanceof Iri) {
+                return getContextOf((Iri) resource, dontExpand).getImmutableGraph();
+            }
+            return getContextOf(resource, dontExpand).getImmutableGraph();
+        } finally {
+            l.unlock();
+        }
+
+    }
+
+    private Graph getContextOf(Iri node, final Set<RdfTerm> dontExpand) {
+        final String uriPrefix = node.getUnicodeString()+'#';
+        return getContextOf(node, dontExpand, new Acceptor() {
+
+            @Override
+            public boolean expand(RdfTerm resource) {
+                if (resource instanceof BlankNode) {
+                    return true;
+                }
+                if (resource instanceof Iri) {
+                    return ((Iri)resource).getUnicodeString().startsWith(uriPrefix);
+                }
+                return false;
+            }
+        });
+    }
+
+    /**
+     * Returns the context of a <code>BlankNodeOrIri</code>
+     *
+     * @param node
+     * @param dontExpand a list of bnodes at which to stop expansion, if node
+     * is a BlankNode it should be contained (potentially faster)
+     * @return the context of a node
+     */
+    private Graph getContextOf(RdfTerm node, final Set<RdfTerm> dontExpand) {
+        return getContextOf(node, dontExpand, new Acceptor() {
+
+            @Override
+            public boolean expand(RdfTerm resource) {
+                if (resource instanceof BlankNode) {
+                    return true;
+                }
+                return false;
+            }
+        });
+    }
+
+    private interface Acceptor {
+        boolean expand(RdfTerm resource);
+    }
+    private Graph getContextOf(RdfTerm node, final Set<RdfTerm> dontExpand, Acceptor acceptor) {
+        Graph result = new SimpleGraph();
+        if (node instanceof BlankNodeOrIri) {
+            Iterator<Triple> forwardProperties = graph.filter((BlankNodeOrIri) node, null, null);
+            while (forwardProperties.hasNext()) {
+                Triple triple = forwardProperties.next();
+                result.add(triple);
+                RdfTerm object = triple.getObject();
+                if (acceptor.expand(object) && !dontExpand.contains(object)) {
+                    dontExpand.add(object);
+                    result.addAll(getContextOf(object, dontExpand, acceptor));
+                }
+            }
+        }
+        Iterator<Triple> backwardProperties = graph.filter(null, null, node);
+        while (backwardProperties.hasNext()) {
+            Triple triple = backwardProperties.next();
+            result.add(triple);
+            BlankNodeOrIri subject = triple.getSubject();
+            if (acceptor.expand(subject) && !dontExpand.contains(subject)) {
+                dontExpand.add(subject);
+                result.addAll(getContextOf(subject, dontExpand, acceptor));
+            }
+        }
+        return result;
+    }
+
+    private <T> Iterator<T> getTypeSelectedObjects(Iri property, final Class<T> type) {
+        final Iterator<RdfTerm> objects = getObjects(property);
+        return new Iterator<T>() {
+
+            T next = prepareNext();
+
+            @Override
+            public boolean hasNext() {
+                return next != null;
+            }
+
+            @Override
+            public T next() {
+                T result = next;
+                next = prepareNext();
+                return result;
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+
+            private T prepareNext() {
+                while (objects.hasNext()) {
+                    RdfTerm nextObject = objects.next();
+                    if (type.isAssignableFrom(nextObject.getClass())) {
+                        return (T) nextObject;
+                    }
+                }
+                return null;
+            }
+        };
+    }
+
+    public Iterator<Literal> getLiterals(Iri property) {
+        final Iterator<RdfTerm> objects = getObjects(property);
+        return new Iterator<Literal>() {
+
+            Literal next = prepareNext();
+
+            @Override
+            public boolean hasNext() {
+                return next != null;
+            }
+
+            @Override
+            public Literal next() {
+                Literal result = next;
+                next = prepareNext();
+                return result;
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+
+            private Literal prepareNext() {
+                while (objects.hasNext()) {
+                    RdfTerm nextObject = objects.next();
+                    if (nextObject instanceof Literal) {
+                        return (Literal) nextObject;
+                    }
+                }
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Count the number of triples in the underlying triple-collection
+     * with this node as subject and a specified property as predicate.
+     *
+     * @param property the property to be examined
+     * @return the number of triples in the underlying triple-collection
+     *        which meet the specified condition
+     */
+    public int countObjects(Iri property) {
+        return countTriples(graph.filter((BlankNodeOrIri) resource, property, null));
+    }
+
+    private int countTriples(final Iterator<Triple> triples) {
+        int count = 0;
+        while (triples.hasNext()) {
+            triples.next();
+            count++;
+        }
+        return count;
+    }
+
+    /**
+     * Get the objects of statements with this node as subject and a specified
+     * property as predicate.
+     *
+     * @param property the property
+     * @return
+     */
+    public Iterator<RdfTerm> getObjects(Iri property) {
+        if (resource instanceof BlankNodeOrIri) {
+            final Iterator<Triple> triples = graph.filter((BlankNodeOrIri) resource, property, null);
+            return new Iterator<RdfTerm>() {
+
+                @Override
+                public boolean hasNext() {
+                    return triples.hasNext();
+                }
+
+                @Override
+                public RdfTerm next() {
+                    final Triple triple = triples.next();
+                    if (triple != null) {
+                        return triple.getObject();
+                    } else {
+                        return null;
+                    }
+                }
+
+                @Override
+                public void remove() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+            };
+        } else {
+            return new Iterator<RdfTerm>() {
+
+                @Override
+                public boolean hasNext() {
+                    return false;
+                }
+
+                @Override
+                public RdfTerm next() {
+                    return null;
+                }
+
+                @Override
+                public void remove() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+            };
+        }
+    }
+
+    /**
+     * Checks wether this node has the given property with the given value.
+     * If the given value is null, then it is checked if this node has the
+     * specified property regardless of its value.
+     *
+     * @param property
+     * @param object
+     * @return true if the node represented by this object is the subject of a
+     *         statement with the given prediate and object, false otherwise
+     */
+    public boolean hasProperty(Iri property, RdfTerm object) {
+        Lock l = readLock();
+        l.lock();
+        try {
+            Iterator<RdfTerm> objects = getObjects(property);
+            if (object == null) {
+                return objects.hasNext();
+            }
+            while (objects.hasNext()) {
+                if (objects.next().equals(object)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            l.unlock();
+        }
+    }
+
+    /**
+     * Count the number of triples in the underlying triple-collection
+     * with this node as object and a specified property as predicate.
+     *
+     * @param property the property to be examined
+     * @return the number of triples in the underlying triple-collection
+     *        which meet the specified condition
+     */
+    public int countSubjects(Iri property) {
+        Lock l = readLock();
+        l.lock();
+        try {
+            return countTriples(graph.filter(null, property, resource));
+        } finally {
+            l.unlock();
+        }
+    }
+
+    /**
+     * Get the subjects of statements with this node as object and a specified
+     * property as predicate.
+     *
+     * @param property the property
+     * @return
+     */
+    public Iterator<BlankNodeOrIri> getSubjects(Iri property) {
+        final Iterator<Triple> triples = graph.filter(null, property, resource);
+        return new Iterator<BlankNodeOrIri>() {
+
+            @Override
+            public boolean hasNext() {
+                return triples.hasNext();
+            }
+
+            @Override
+            public BlankNodeOrIri next() {
+                return triples.next().getSubject();
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        };
+    }
+
+    public Iterator<Iri> getIriObjects(Iri property) {
+        return getTypeSelectedObjects(property, Iri.class);
+
+    }
+
+    /**
+     * Get all available properties as an {@link Iterator}<{@link Iri}>.
+     * You can use <code>getObjects(Iri property)</code> to get the values of
+     * each property
+     *
+     * @return an iterator over properties of this node
+     */
+    public Iterator<Iri> getProperties() {
+        if (resource instanceof BlankNodeOrIri) {
+            final Iterator<Triple> triples = graph.filter((BlankNodeOrIri) resource, null, null);
+            return getUniquePredicates(triples);
+        } else {
+            return new Iterator<Iri>() {
+
+                @Override
+                public boolean hasNext() {
+                    return false;
+                }
+
+                @Override
+                public Iri next() {
+                    return null;
+                }
+
+                @Override
+                public void remove() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+            };
+        }
+    }
+
+    /**
+     * Get all inverse properties as an {@link Iterator}<{@link Iri}>.
+     * You can use <code>getSubject(Iri property)</code> to get the values of
+     * each inverse property
+     *
+     * @return an iterator over properties pointing to this node
+     */
+    public Iterator<Iri> getInverseProperties() {
+        final Iterator<Triple> triples = graph.filter(null, null, resource);
+        return getUniquePredicates(triples);
+    }
+
+    /**
+     *
+     * @param triples
+     * @returnan {@link Iterator}<{@link Iri}> containing the predicates from
+     * an {@link Iterator}<{@link Triple}>
+     */
+    private Iterator<Iri> getUniquePredicates(final Iterator<Triple> triples) {
+        final Set<Iri> resultSet = new HashSet<Iri>();
+        while (triples.hasNext()) {
+            resultSet.add(triples.next().getPredicate());
+        }
+        return resultSet.iterator();
+    }
+
+    /**
+     * Adds a property to the node with the specified predicate and object
+     *
+     * @param predicate
+     * @param object
+     */
+    public void addProperty(Iri predicate, RdfTerm object) {
+        if (resource instanceof BlankNodeOrIri) {
+            graph.add(new TripleImpl((BlankNodeOrIri) resource, predicate, object));
+        } else {
+            throw new RuntimeException("Literals cannot be the subject of a statement");
+        }
+    }
+
+
+    /**
+     * Coverts the value into a typed literals and sets it as object of the
+     * specified property
+     *
+     * @param property the predicate of the triple to be created
+     * @param value the value of the typed literal object
+     */
+    public void addPropertyValue(Iri property, Object value) {
+        addProperty(property,
+                LiteralFactory.getInstance().createTypedLiteral(value));
+    }
+
+    /**
+     * Adds a property to the node with the inverse of the specified predicate and object
+     * In other words <code>subject</code> will be related via the property <code>relation</code> to this node.
+     *
+     * @param predicate
+     * @param subject
+     */
+    public void addInverseProperty(Iri predicate, RdfTerm subject) {
+        if (subject instanceof BlankNodeOrIri) {
+            graph.add(new TripleImpl((BlankNodeOrIri) subject, predicate, resource));
+        } else {
+            throw new RuntimeException("Literals cannot be the subject of a statement");
+        }
+    }
+
+
+    /**
+     * creates and returns an <code>RdfList</code> for the node and
+     * Graph represented by this object.
+     *
+     * @return a List to easy access the rdf:List represented by this node
+     */
+    public List<RdfTerm> asList() {
+        if (resource instanceof BlankNodeOrIri) {
+            return new RdfList((BlankNodeOrIri) resource, graph);
+        } else {
+            throw new RuntimeException("Literals cannot be the subject of a List");
+        }
+    }
+
+    /**
+     * Deletes all statement with the current node as subject and the specified
+     * predicate
+     *
+     * @param predicate
+     */
+    public void deleteProperties(Iri predicate) {
+        if (resource instanceof BlankNodeOrIri) {
+            Iterator<Triple> tripleIter = graph.filter((BlankNodeOrIri) resource, predicate, null);
+            Collection<Triple> toDelete = new ArrayList<Triple>();
+            while (tripleIter.hasNext()) {
+                Triple triple = tripleIter.next();
+                toDelete.add(triple);
+            }
+            for (Triple triple : toDelete) {
+                graph.remove(triple);
+            }
+        }
+    }
+
+    /**
+     * Delete property to the node with the specified predicate and object
+     *
+     * @param predicate
+     * @param object
+     */
+    public void deleteProperty(Iri predicate, RdfTerm object) {
+        if (resource instanceof BlankNodeOrIri) {
+            graph.remove(new TripleImpl((BlankNodeOrIri) resource, predicate, object));
+        }
+    }
+
+    @Override
+    public String toString() {
+        return resource.toString();
+    }
+
+    /**
+     * Replaces the graph node resouce with the specified <code>BlankNodeOrIri</code>.
+     * The resource is only replaced where it is either subject or object.
+     * @param replacement
+     * @return a GraphNode representing the replecement node
+     */
+    public GraphNode replaceWith(BlankNodeOrIri replacement) {
+        return replaceWith(replacement, false);
+    }
+
+    /**
+     * Replaces the graph node resouce with the specified <code>BlankNodeOrIri</code>.
+     * Over the boolean <code>checkPredicate</code> it can be specified if the
+     * resource should also be replaced where it is used as predicate.
+     * @param replacement
+     * @param checkPredicates
+     * @return a GraphNode representing the replecement node
+     */
+    public GraphNode replaceWith(BlankNodeOrIri replacement, boolean checkPredicates) {
+        Graph newTriples = new SimpleGraph();
+        if (!(resource instanceof Literal)) {
+            Iterator<Triple> subjectTriples = graph.filter((BlankNodeOrIri) resource, null,
+                    null);
+            while (subjectTriples.hasNext()) {
+                Triple triple = subjectTriples.next();
+                Triple newTriple = new TripleImpl(replacement, triple.getPredicate(),
+                        triple.getObject());
+                subjectTriples.remove();
+                newTriples.add(newTriple);
+            }
+            graph.addAll(newTriples);
+            newTriples.clear();
+        }
+
+        Iterator<Triple> objectTriples = graph.filter(null, null, resource);
+        while (objectTriples.hasNext()) {
+            Triple triple = objectTriples.next();
+            Triple newTriple = new TripleImpl(triple.getSubject(),
+                    triple.getPredicate(), replacement);
+            objectTriples.remove();
+            newTriples.add(newTriple);
+        }
+        graph.addAll(newTriples);
+        newTriples.clear();
+
+        if (checkPredicates && replacement instanceof Iri
+                && resource instanceof Iri) {
+            Iterator<Triple> predicateTriples = graph.filter(null,
+                    (Iri) resource, null);
+            while (predicateTriples.hasNext()) {
+                Triple triple = predicateTriples.next();
+                Triple newTriple = new TripleImpl(triple.getSubject(),
+                        (Iri) replacement, triple.getObject());
+                predicateTriples.remove();
+                newTriples.add(newTriple);
+            }
+            graph.addAll(newTriples);
+        }
+        return new GraphNode(replacement, graph);
+    }
+
+    /**
+     * Returns a iterator containing all objects of the triples where this
+     * graph node is the subject and has the specified property. The objects
+     * are returned as <code>GraphNode</code>s.
+     *
+     * @param property
+     * @return
+     */
+    public Iterator<GraphNode> getObjectNodes(Iri property) {
+        final Iterator<RdfTerm> objects = this.getObjects(property);
+        return new Iterator<GraphNode>() {
+
+            @Override
+            public boolean hasNext() {
+                return objects.hasNext();
+            }
+
+            @Override
+            public GraphNode next() {
+                RdfTerm object = objects.next();
+                return new GraphNode(object, graph);
+
+            }
+
+            @Override
+            public void remove() {
+                objects.remove();
+            }
+        };
+    }
+
+    /**
+     * Returns a iterator containing all subjects of the triples where this
+     * graph node is the object and has the specified property. The subjects
+     * are returned as <code>GraphNode</code>s.
+     *
+     * @param property
+     * @return
+     */
+    public Iterator<GraphNode> getSubjectNodes(Iri property) {
+        final Iterator<BlankNodeOrIri> subjects = this.getSubjects(property);
+        return new Iterator<GraphNode>() {
+
+            @Override
+            public boolean hasNext() {
+                return subjects.hasNext();
+            }
+
+            @Override
+            public GraphNode next() {
+                RdfTerm object = subjects.next();
+                return new GraphNode(object, graph);
+
+            }
+
+            @Override
+            public void remove() {
+                subjects.remove();
+            }
+        };
+    }
+
+    /**
+     *
+     * @param obj
+     * @return true if obj is an instance of the same class represening the same
+     * node in the same graph, subclasses may have different identity criteria.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || !(obj.getClass().equals(getClass()))) {
+            return false;
+        }
+        GraphNode other = (GraphNode) obj;
+        return getNode().equals(other.getNode())
+                && getGraph().equals(other.getGraph());
+    }
+
+    @Override
+    public int hashCode() {
+        return 13 * getNode().hashCode() + getGraph().hashCode();
+    }
+
+    /**
+     * @return a ReadLock if the underlying ImmutableGraph is a LockableGraph it returns its lock, otherwise null
+     */
+    public Lock readLock() {
+
+            return getGraph().getLock().readLock();
+
+    }
+
+    /**
+     *
+     * @return
+     */
+    public Lock writeLock() {
+
+            return (getGraph()).getLock().writeLock();
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphUtils.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphUtils.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphUtils.java
new file mode 100644
index 0000000..dc3943b
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/GraphUtils.java
@@ -0,0 +1,163 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
+
+/**
+ * Utility methods to manipulate <code>Graph</code>s
+ *
+ * @author reto
+ */
+public class GraphUtils {
+
+    /**
+     * Removes a subGraph from an Graph. The subGraph must match a subgraph of
+     * Graph so that for every node in <code>subGraph</code>
+     * each triple it appears in is also present in <code>mGraph</code>. Two
+     * bnodes are considered equals if their contexts (as returned by
+     * <code>GraphNode.getNodeContext</code> are equals.
+     *
+     * @param mGraph
+     * @param subGraph
+     * @throws org.apache.clerezza.rdf.utils.GraphUtils.NoSuchSubGraphException
+     */
+    public static void removeSubGraph(Graph mGraph, Graph subGraph)
+            throws NoSuchSubGraphException {
+        //point to triples of mGraph that are to be removed (if something is removed)
+        final Set<Triple> removingTriples = new HashSet<Triple>();
+        //we first check only the grounded triples and put the non-grounded in here:
+        final Graph unGroundedTriples = new SimpleGraph();
+        for (Triple triple : subGraph) {
+            if (isGrounded(triple)) {
+                if (!mGraph.contains(triple)) {
+                    throw new NoSuchSubGraphException();
+                }
+                removingTriples.add(triple);
+            } else {
+                unGroundedTriples.add(triple);
+            }
+        }
+
+        //we first remove the context of bnodes we find in object position
+        OBJ_BNODE_LOOP: while (true) {
+            final Triple triple = getTripleWithBlankNodeObject(unGroundedTriples);
+            if (triple == null) {
+                break;
+            }
+            final GraphNode objectGN = new GraphNode(triple.getObject(), unGroundedTriples);
+            BlankNodeOrIri subject = triple.getSubject();
+            ImmutableGraph context = objectGN.getNodeContext();
+            Iterator<Triple> potentialIter = mGraph.filter(subject, triple.getPredicate(), null);
+            while (potentialIter.hasNext()) {
+                try {
+                    final Triple potentialTriple = potentialIter.next();
+                    BlankNode potentialMatch = (BlankNode)potentialTriple.getObject();
+                    final ImmutableGraph potentialContext = new GraphNode(potentialMatch, mGraph).getNodeContext();
+                    if (potentialContext.equals(context)) {
+                        removingTriples.addAll(potentialContext);
+                        unGroundedTriples.removeAll(context);
+                        continue OBJ_BNODE_LOOP;
+                    }
+                } catch (ClassCastException e) {
+                    continue;
+                }
+            }
+            throw new NoSuchSubGraphException();
+        }
+        SUBJ_BNODE_LOOP: while (true) {
+            final Triple triple = getTripleWithBlankNodeSubject(unGroundedTriples);
+            if (triple == null) {
+                break;
+            }
+            final GraphNode subjectGN = new GraphNode(triple.getSubject(), unGroundedTriples);
+            RdfTerm object = triple.getObject();
+            if (object instanceof BlankNode) {
+                object = null;
+            }
+            ImmutableGraph context = subjectGN.getNodeContext();
+            Iterator<Triple> potentialIter = mGraph.filter(null, triple.getPredicate(), object);
+            while (potentialIter.hasNext()) {
+                try {
+                    final Triple potentialTriple = potentialIter.next();
+                    BlankNode potentialMatch = (BlankNode)potentialTriple.getSubject();
+                    final ImmutableGraph potentialContext = new GraphNode(potentialMatch, mGraph).getNodeContext();
+                    if (potentialContext.equals(context)) {
+                        removingTriples.addAll(potentialContext);
+                        unGroundedTriples.removeAll(context);
+                        continue SUBJ_BNODE_LOOP;
+                    }
+                } catch (ClassCastException e) {
+                    continue;
+                }
+            }
+            throw new NoSuchSubGraphException();
+        }
+        mGraph.removeAll(removingTriples);
+    }
+
+    private static boolean isGrounded(Triple triple) {
+        if (triple.getSubject() instanceof BlankNode) {
+            return false;
+        }
+        if (triple.getObject() instanceof BlankNode) {
+            return false;
+        }
+        return true;
+    }
+
+    /** retrun triples with a bnode only at object position
+     *
+     * @param triples
+     * @return
+     */
+    private static Triple getTripleWithBlankNodeObject(Graph triples) {
+        for (Triple triple : triples) {
+            if (triple.getSubject() instanceof BlankNode) {
+                continue;
+            }
+            if (triple.getObject() instanceof BlankNode) {
+                return triple;
+            }
+        }
+        return null;
+    }
+    private static Triple getTripleWithBlankNodeSubject(Graph triples) {
+        for (Triple triple : triples) {
+            if (triple.getSubject() instanceof BlankNode) {
+                return triple;
+            }
+        }
+        return null;
+    }
+
+    public static class NoSuchSubGraphException extends Exception {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/IriUtil.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/IriUtil.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/IriUtil.java
new file mode 100644
index 0000000..323c9f2
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/IriUtil.java
@@ -0,0 +1,63 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+
+/**
+ * A utility class for Iri and String manipulations.
+ *
+ * @author tio
+ */
+public class IriUtil {
+
+    /**
+     * Strips #x00 - #x1F and #x7F-#x9F from a Unicode string
+     * @see <a href="http://www.w3.org/TR/rdf-concepts/#dfn-URI-reference">
+     * http://www.w3.org/TR/rdf-concepts/#dfn-URI-reference</a> and
+     * replaces all US-ASCII space character with a "+".
+     *
+     * @param inputChars
+     * @return the stripped string
+     * 
+     */
+    public static String stripNonIriChars(CharSequence inputChars) {
+
+        if (inputChars == null) {
+            return "";
+        }
+
+        StringBuffer buffer = new StringBuffer();
+
+        for (int i = 0; i < inputChars.length(); i++) {
+            char c = inputChars.charAt(i);
+
+            if (!isIllegal(c)) {
+                buffer.append(c);
+            }
+        }
+        return buffer.toString().replaceAll("\\s+", "+");
+    }
+
+    private static boolean isIllegal(char ch) {
+        if ((ch >= 0x7F) && (ch <= 0x9F)) {
+            return true;
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/RdfList.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/RdfList.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/RdfList.java
new file mode 100644
index 0000000..db994e9
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/RdfList.java
@@ -0,0 +1,358 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import java.io.FileOutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.clerezza.rdf.core.serializedform.Serializer;
+import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
+import org.apache.clerezza.rdf.ontologies.OWL;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.commons.rdf.Graph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An implementation of an <code>java.util.List</code> backed by an RDF
+ * collection (rdf:List). The list allows modification that are reflected
+ * to the underlying <code>Graph</code>. It reads the data from the
+ * <code>Graph</code> when it is first needed, so changes to the
+ * Graph affecting the rdf:List may or may not have an effect on the
+ * values returned by instances of this class. For that reason only one
+ * instance of this class should be used for accessing an rdf:List of sublists
+ * thereof when the lists are being modified, having multiple lists exclusively
+ * for read operations (such as for immutable <code>Graph</code>s) is
+ * not problematic.
+ *
+ * @author rbn, mir
+ */
+public class RdfList extends AbstractList<RdfTerm> {
+
+    private static final Logger logger = LoggerFactory.getLogger(RdfList.class);
+
+    private final static Iri RDF_NIL =
+            new Iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
+    /**
+     * a list of the linked rdf:List elements in order
+     */
+    private List<BlankNodeOrIri> listList = new ArrayList<BlankNodeOrIri>();
+    private List<RdfTerm> valueList = new ArrayList<RdfTerm>();
+    private BlankNodeOrIri firstList;
+    private Graph tc;
+    private boolean totallyExpanded = false;
+
+    /**
+     * Get a list for the specified resource.
+     *
+     * If the list is modified using the created instance
+     * <code>listRdfTerm</code> will always be the first list.
+     *
+     * @param listRdfTerm
+     * @param tc
+     */
+    public RdfList(BlankNodeOrIri listRdfTerm, Graph tc) {
+        firstList = listRdfTerm;
+        this.tc = tc;
+
+    }
+
+    /**
+     * Get a list for the specified resource node.
+     *
+     * @param listNode
+     */
+    public RdfList(GraphNode listNode) {
+        this((BlankNodeOrIri)listNode.getNode(), listNode.getGraph());
+    }
+
+    /**
+     * Creates an empty RdfList by writing a triple
+     * "{@code listRdfTerm} owl:sameAs rdf.nil ." to {@code tc}.
+     *
+     * @param listRdfTerm
+     * @param tc
+     * @return    an empty rdf:List.
+     * @throws IllegalArgumentException
+     *        if the provided {@code  listRdfTerm} is a non-empty rdf:List.
+     */
+    public static RdfList createEmptyList(BlankNodeOrIri listRdfTerm, Graph tc)
+            throws IllegalArgumentException {
+
+        if (!tc.filter(listRdfTerm, RDF.first, null).hasNext()) {
+            RdfList list = new RdfList(listRdfTerm, tc);
+            list.tc.add(new TripleImpl(listRdfTerm, OWL.sameAs, RDF_NIL));
+            return list;
+        } else {
+            throw new IllegalArgumentException(listRdfTerm + "is a non-empty rdf:List.");
+        }
+    }
+
+    private void expandTill(int pos) {
+        if (totallyExpanded) {
+            return;
+        }
+        BlankNodeOrIri currentList;
+        if (listList.size() > 0) {
+            currentList = listList.get(listList.size()-1);
+        } else {
+            currentList = firstList;
+            if (!tc.filter(currentList, RDF.first, null).hasNext()) {
+                return;
+            }
+            listList.add(currentList);
+            valueList.add(getFirstEntry(currentList));
+        }
+        if (listList.size() >= pos) {
+            return;
+        }
+        while (true) {                
+            currentList = getRest(currentList);
+            if (currentList.equals(RDF_NIL)) {
+                totallyExpanded = true;
+                break;
+            }
+            if (listList.size() == pos) {
+                break;
+            }
+            valueList.add(getFirstEntry(currentList));
+            listList.add(currentList);
+        }
+    }
+
+
+
+    @Override
+    public RdfTerm get(int index) {
+        expandTill(index + 1);
+        return valueList.get(index);
+    }
+
+    @Override
+    public int size() {
+        expandTill(Integer.MAX_VALUE);        
+        return valueList.size();
+    }
+
+    @Override
+    public void add(int index, RdfTerm element) {
+        expandTill(index);
+        if (index == 0) {
+            //special casing to make sure the first list remains the same resource
+            if (listList.size() == 0) {
+                tc.remove(new TripleImpl(firstList, OWL.sameAs, RDF_NIL));
+                tc.add(new TripleImpl(firstList, RDF.rest, RDF_NIL));
+                tc.add(new TripleImpl(firstList, RDF.first, element));
+                listList.add(firstList);
+            } else {
+                tc.remove(new TripleImpl(listList.get(0), RDF.first, valueList.get(0)));
+                tc.add(new TripleImpl(listList.get(0), RDF.first, element));
+                addInRdfList(1, valueList.get(0));
+            }
+        } else {
+            addInRdfList(index, element);
+        }
+        valueList.add(index, element);
+    }
+    
+    /**
+     *
+     * @param index is > 0
+     * @param element
+     */
+    private void addInRdfList(int index, RdfTerm element) {
+        expandTill(index+1);
+        BlankNodeOrIri newList = new BlankNode() {
+        };
+        tc.add(new TripleImpl(newList, RDF.first, element));
+        if (index < listList.size()) {
+            tc.add(new TripleImpl(newList, RDF.rest, listList.get(index)));
+            tc.remove(new TripleImpl(listList.get(index - 1), RDF.rest, listList.get(index)));
+        } else {
+            tc.remove(new TripleImpl(listList.get(index - 1), RDF.rest, RDF_NIL));
+            tc.add(new TripleImpl(newList, RDF.rest, RDF_NIL));
+
+        }
+        tc.add(new TripleImpl(listList.get(index - 1), RDF.rest, newList));
+        listList.add(index, newList);
+    }
+
+    @Override
+    public RdfTerm remove(int index) {
+        //keeping the first list resource
+        tc.remove(new TripleImpl(listList.get(index), RDF.first, valueList.get(index)));
+        if (index == (listList.size() - 1)) {
+            tc.remove(new TripleImpl(listList.get(index), RDF.rest, RDF_NIL));    
+            if (index > 0) {
+                tc.remove(new TripleImpl(listList.get(index - 1), RDF.rest, listList.get(index)));
+                tc.add(new TripleImpl(listList.get(index - 1), RDF.rest, RDF_NIL));
+            } else {
+                tc.add(new TripleImpl(listList.get(index), OWL.sameAs, RDF_NIL));
+            }
+            listList.remove(index);
+        } else {
+            tc.add(new TripleImpl(listList.get(index), RDF.first, valueList.get(index+1)));
+            tc.remove(new TripleImpl(listList.get(index), RDF.rest, listList.get(index + 1)));
+            tc.remove(new TripleImpl(listList.get(index + 1), RDF.first, valueList.get(index + 1)));
+            if (index == (listList.size() - 2)) {
+                tc.remove(new TripleImpl(listList.get(index + 1), RDF.rest, RDF_NIL));
+                tc.add(new TripleImpl(listList.get(index), RDF.rest, RDF_NIL));
+            } else {
+                tc.remove(new TripleImpl(listList.get(index + 1), RDF.rest, listList.get(index + 2)));
+                tc.add(new TripleImpl(listList.get(index), RDF.rest, listList.get(index + 2)));
+            }
+            listList.remove(index+1);
+        }
+        return valueList.remove(index);
+    }
+
+    private BlankNodeOrIri getRest(BlankNodeOrIri list) {
+        return (BlankNodeOrIri) tc.filter(list, RDF.rest, null).next().getObject();
+    }
+
+    private RdfTerm getFirstEntry(final BlankNodeOrIri listRdfTerm) {
+        try {
+            return tc.filter(listRdfTerm, RDF.first, null).next().getObject();
+        } catch (final NullPointerException e) {
+            RuntimeException runtimeEx = AccessController.doPrivileged(new PrivilegedAction<RuntimeException>() {
+                @Override
+                public RuntimeException run(){
+                    try {
+                        final FileOutputStream fileOutputStream = new FileOutputStream("/tmp/broken-list.nt");
+                        final GraphNode graphNode = new GraphNode(listRdfTerm, tc);
+                        Serializer.getInstance().serialize(fileOutputStream, graphNode.getNodeContext(), SupportedFormat.N_TRIPLE);
+                        fileOutputStream.flush();
+                        logger.warn("GraphNode: " + graphNode);
+                        final Iterator<Iri> properties = graphNode.getProperties();
+                        while (properties.hasNext()) {
+                            logger.warn("available: " + properties.next());
+                        }
+                        return new RuntimeException("broken list " + listRdfTerm, e);
+                    } catch (Exception ex) {
+                        return new RuntimeException(ex);
+                    }
+
+                }
+            });
+            throw runtimeEx;
+        }
+    }
+
+    public BlankNodeOrIri getListRdfTerm() {
+        return firstList;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final RdfList other = (RdfList) obj;
+
+        if (!other.firstList.equals(this.firstList)) {
+            return false;
+        }
+
+        if (!other.tc.equals(this.tc)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return 17 * this.firstList.hashCode() + this.tc.hashCode();
+    }
+
+    /**
+     * Returns the rdf lists of which the specified <code>GraphNode</code> is
+     * an element of. Sublists of other lists are not returned.
+     *
+     * @param element
+     * @return
+     */
+    public static Set<RdfList> findContainingLists(GraphNode element) {
+        Set<GraphNode> listNodes = findContainingListNodes(element);
+        if (listNodes.isEmpty()) {
+            return null;
+        }
+
+        Set<RdfList> rdfLists = new HashSet<RdfList>();
+        for (Iterator<GraphNode> it = listNodes.iterator(); it.hasNext();) {
+            GraphNode listNode = it.next();
+            rdfLists.add(new RdfList(listNode));
+        }
+        return rdfLists;
+    }
+
+    /**
+     * Returns a set of <code>GraphNode</code>S which are the first list nodes (meaning
+     * they are not the beginning of a sublist) of the list containing the specified
+     * <code>GraphNode</code> as an element.
+     *
+     * @param element
+     * @return
+     */
+    public static Set<GraphNode> findContainingListNodes(GraphNode element) {
+        Iterator<GraphNode> partOfaListNodesIter = element.getSubjectNodes(RDF.first);
+        if (!partOfaListNodesIter.hasNext()) {
+            return null;
+        }
+        Set<GraphNode> listNodes = new HashSet<GraphNode>();
+
+        while (partOfaListNodesIter.hasNext()) {
+            listNodes.addAll(findAllListNodes(partOfaListNodesIter.next()));
+        }
+        return listNodes;
+    }
+    
+    private static Set<GraphNode> findAllListNodes(GraphNode listPart) {
+        Iterator<GraphNode> invRestNodesIter;
+        Set<GraphNode> listNodes = new HashSet<GraphNode>();
+        do {
+            invRestNodesIter = listPart.getSubjectNodes(RDF.rest);
+            if (invRestNodesIter.hasNext()) {
+                listPart = invRestNodesIter.next();
+                while (invRestNodesIter.hasNext()) {
+                    GraphNode graphNode = invRestNodesIter.next();
+                    listNodes.addAll(findAllListNodes(graphNode));
+                }
+            } else {
+                listNodes.add(listPart);
+                break;
+            }
+        } while (true);
+        return listNodes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/SeeAlsoExpander.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/SeeAlsoExpander.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/SeeAlsoExpander.java
new file mode 100644
index 0000000..fef7e4b
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/SeeAlsoExpander.java
@@ -0,0 +1,113 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.ontologies.RDFS;
+
+/**
+ * Expands a GraphNode expanding SeeAlso-References of the node.
+ *
+ * @author reto
+ */
+public class SeeAlsoExpander {
+    /**
+     * using TcManger instead of TcProvider as this ensures LockableGraphs
+     */
+    private final TcManager tcManager;
+    public SeeAlsoExpander(TcManager tcManager) {
+        this.tcManager = tcManager;
+
+    }
+
+    /**
+     * expands a node dereferencing its rdfs:seeAlso references using the
+     * tcManager associated to this instance. If the added TripleCollections
+     * also associate rdfs:seeAlso properties to node this are expanded till
+     * the maximum recursion depth specified.
+     *
+     * @param node the node to be expanded
+     * @param recursion the maximum recursion depth
+     * @return a new GraphNode over the union of the original and all expansion graphs
+     */
+    public GraphNode expand(GraphNode node, int recursion) {
+        Set<Iri> alreadyVisited = new HashSet();
+        Set<Graph> resultTripleCollections = new HashSet<Graph>();
+        resultTripleCollections.add(node.getGraph());
+        for (Iri uriRef : expand(node, alreadyVisited, recursion)) {
+            try {
+                resultTripleCollections.add(tcManager.getGraph(uriRef));
+            } catch (NoSuchEntityException e) {
+                //ignore
+            }
+        }
+        return new GraphNode(node.getNode(),
+                new UnionGraph(resultTripleCollections.toArray(
+                new Graph[resultTripleCollections.size()])));
+
+    }
+
+    private Set<Iri> getSeeAlsoObjectUris(GraphNode node) {
+        Set<Iri> result = new HashSet<Iri>();
+        Lock l = node.readLock();
+        l.lock();
+        try {
+            Iterator<RdfTerm> objects = node.getObjects(RDFS.seeAlso);
+            while (objects.hasNext()) {
+                RdfTerm next = objects.next();
+                if (next instanceof Iri) {
+                    result.add((Iri)next);
+                }
+            }
+        } finally {
+            l.unlock();
+        }
+        return result;
+    }
+
+    private Set<Iri> expand(GraphNode node, Set<Iri> alreadyVisited, int recursion) {
+        Set<Iri> rdfSeeAlsoTargets = getSeeAlsoObjectUris(node);
+        Set<Iri> result = new HashSet<Iri>();
+        result.addAll(rdfSeeAlsoTargets);
+        recursion++;
+        if (recursion > 0) {
+            rdfSeeAlsoTargets.removeAll(alreadyVisited);
+            alreadyVisited.addAll(rdfSeeAlsoTargets);
+            for (Iri target : rdfSeeAlsoTargets) {
+                try {
+                    result.addAll(expand(new GraphNode(node.getNode(),
+                        tcManager.getGraph(target)), alreadyVisited, recursion));
+                } catch (NoSuchEntityException e) {
+                    //ignore
+                }
+            }
+        }
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/Smusher.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/Smusher.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/Smusher.java
new file mode 100644
index 0000000..8d0ea45
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/Smusher.java
@@ -0,0 +1,61 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import org.apache.commons.rdf.Graph;
+import org.apache.clerezza.rdf.utils.smushing.IfpSmusher;
+import org.apache.clerezza.rdf.utils.smushing.SameAsSmusher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A utility to smush equivalent resources. For greater flexibility use the 
+ * classes in the smushing package.
+ * 
+ * @author reto
+ */
+public class Smusher {
+
+    static final Logger log = LoggerFactory.getLogger(Smusher.class);
+
+    /**
+     * smush mGaph given the ontological facts. Currently it does only one step
+     * ifp smushin, i.e. only ifps are taken in account and only nodes that have
+     * the same node as ifp object in the orignal graph are equates. (calling
+     * the method a second time might lead to additional smushings.)
+     *
+     * @param mGraph
+     * @param tBox
+     */
+    public static void smush(Graph mGraph, Graph tBox) {
+        new IfpSmusher().smush(mGraph, tBox);
+    }
+
+    /**
+     * Smushes the specified graph adding owl:sameAs statements pointing to the new canonical IRI
+     * 
+     * @param mGraph
+     * @param owlSameStatements 
+     */
+    public static void sameAsSmush(Graph mGraph, Graph owlSameStatements) {
+        new SameAsSmusher().smush(mGraph, owlSameStatements, true);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionGraph.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionGraph.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionGraph.java
new file mode 100644
index 0000000..a928f79
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionGraph.java
@@ -0,0 +1,286 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.AbstractGraph;
+
+/**
+ *
+ * This class represents the union of multiple triple collections. A UnionGraph
+ * appears like a merge of the different graphs (see.
+ * http://www.w3.org/TR/rdf-mt/#graphdefs).
+ *
+ * @author hasan
+ */
+public class UnionGraph extends AbstractGraph {
+
+    protected Graph[] baseTripleCollections;
+    private Lock readLock;
+    private Lock writeLock;
+
+    /**
+     * Constructs a UnionGraph over the specified baseTripleCollections. Write
+     * and delete operations are forwarded to the first baseTripleCollections.
+     *
+     * @param baseTripleCollections the baseTripleCollections
+     */
+    public UnionGraph(Graph... baseTripleCollections) {
+        this.baseTripleCollections = baseTripleCollections;
+        readLock = getPartialReadLock(0);
+        writeLock = createWriteLock();
+    }
+
+    @Override
+    public int performSize() {
+        int size = 0;
+        for (Graph graph : baseTripleCollections) {
+            size += graph.size();
+        }
+        return size;
+    }
+
+    @Override
+    public Iterator<Triple> performFilter(final BlankNodeOrIri subject,
+            final Iri predicate, final RdfTerm object) {
+        if (baseTripleCollections.length == 0) {
+            return new HashSet<Triple>(0).iterator();
+        }
+        return new Iterator<Triple>() {
+
+            int currentBaseTC = 0;
+            Iterator<Triple> currentBaseIter = baseTripleCollections[0].filter(
+                    subject, predicate, object);
+            private Triple lastReturned;
+
+            @Override
+            public boolean hasNext() {
+                if (currentBaseIter.hasNext()) {
+                    return true;
+                }
+                if (currentBaseTC == baseTripleCollections.length - 1) {
+                    return false;
+                }
+                currentBaseTC++;
+                currentBaseIter = baseTripleCollections[currentBaseTC].filter(
+                        subject, predicate, object);
+                return hasNext();
+            }
+
+            @Override
+            public Triple next() {
+                lastReturned = hasNext() ? currentBaseIter.next() : null;
+                return lastReturned;
+            }
+
+            @Override
+            public void remove() {
+                if (lastReturned == null) {
+                    throw new IllegalStateException();
+                }
+                if (currentBaseTC == 0) {
+                    currentBaseIter.remove();
+                }
+                lastReturned = null;
+            }
+        };
+    }
+
+    @Override
+    public boolean add(Triple e) {
+        if (baseTripleCollections.length == 0) {
+            throw new RuntimeException("no base graph for adding triples");
+        }
+        return baseTripleCollections[0].add(e);
+    }
+
+    @Override
+    public boolean remove(Object e) {
+        if (baseTripleCollections.length == 0) {
+            throw new RuntimeException("no base graph for removing triples");
+        }
+        return baseTripleCollections[0].remove(e);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj.getClass().equals(getClass()))) {
+            return false;
+        }
+        UnionGraph other = (UnionGraph) obj;
+        Set<Graph> otherGraphs
+                = new HashSet(Arrays.asList(other.baseTripleCollections));
+        Set<Graph> thisGraphs
+                = new HashSet(Arrays.asList(baseTripleCollections));
+        return thisGraphs.equals(otherGraphs)
+                && baseTripleCollections[0].equals(other.baseTripleCollections[0]);
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        for (Graph graph : baseTripleCollections) {
+            hash += graph.hashCode();
+        }
+        hash *= baseTripleCollections[0].hashCode();
+        return hash;
+    }
+
+    @Override
+    public ReadWriteLock getLock() {
+        return readWriteLock;
+    }
+    private ReadWriteLock readWriteLock = new ReadWriteLock() {
+
+        @Override
+        public Lock readLock() {
+            return readLock;
+        }
+
+        @Override
+        public Lock writeLock() {
+            return writeLock;
+        }
+    };
+
+    private Lock getPartialReadLock(int startPos) {
+        ArrayList<Lock> resultList = new ArrayList<Lock>();
+        for (int i = startPos; i < baseTripleCollections.length; i++) {
+            Graph graph = baseTripleCollections[i];
+
+            final Lock lock = graph.getLock().readLock();
+            resultList.add(lock);
+        }
+        return new UnionLock(resultList.toArray(new Lock[resultList.size()]));
+    }
+
+    private Lock createWriteLock() {
+        Lock partialReadLock = getPartialReadLock(1);
+
+        Lock baseWriteLock
+                = (baseTripleCollections[0]).getLock().writeLock();
+        return new UnionLock(baseWriteLock, partialReadLock);
+
+    }
+
+    ;
+
+
+    private static class UnionLock implements Lock {
+
+        Lock[] locks;
+
+        public UnionLock(Lock... locks) {
+            this.locks = locks;
+        }
+
+        @Override
+        public void lock() {
+            boolean isLocked = false;
+            while (!isLocked) {
+                try {
+                    isLocked = tryLock(10000, TimeUnit.NANOSECONDS);
+                } catch (InterruptedException ex) {
+
+                }
+            }
+        }
+
+        @Override
+        public void lockInterruptibly() throws InterruptedException {
+            Set<Lock> aquiredLocks = new HashSet<Lock>();
+            try {
+                for (Lock lock : locks) {
+                    lock.lockInterruptibly();
+                    aquiredLocks.add(lock);
+                }
+            } catch (InterruptedException e) {
+                for (Lock lock : aquiredLocks) {
+                    lock.unlock();
+                }
+                throw e;
+            }
+        }
+
+        @Override
+        public boolean tryLock() {
+            Set<Lock> aquiredLocks = new HashSet<Lock>();
+            for (Lock lock : locks) {
+                if (!lock.tryLock()) {
+                    for (Lock aquiredLock : aquiredLocks) {
+                        aquiredLock.unlock();
+                    }
+                    return false;
+                }
+                aquiredLocks.add(lock);
+            }
+            return true;
+        }
+
+        @Override
+        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
+            Set<Lock> aquiredLocks = new HashSet<Lock>();
+            long timeInNanos = unit.convert(time, TimeUnit.NANOSECONDS);
+            long startTime = System.nanoTime();
+            try {
+                for (Lock lock : locks) {
+                    if (!lock.tryLock((timeInNanos + startTime) - System.nanoTime(),
+                            TimeUnit.NANOSECONDS)) {
+                        for (Lock aquiredLock : aquiredLocks) {
+                            aquiredLock.unlock();
+                        }
+                        return false;
+                    }
+                    aquiredLocks.add(lock);
+                }
+            } catch (InterruptedException e) {
+                for (Lock lock : aquiredLocks) {
+                    lock.unlock();
+                }
+                throw e;
+            }
+            return true;
+        }
+
+        @Override
+        public void unlock() {
+            for (Lock lock : locks) {
+                lock.unlock();
+            }
+        }
+
+        @Override
+        public Condition newCondition() {
+            throw new UnsupportedOperationException("Conditions not supported.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionWatchableGraph.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionWatchableGraph.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionWatchableGraph.java
new file mode 100644
index 0000000..3892811
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UnionWatchableGraph.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.clerezza.rdf.utils;
+
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.WatchableGraph;
+import org.apache.commons.rdf.event.FilterTriple;
+import org.apache.commons.rdf.event.GraphListener;
+
+/**
+ *
+ * @author developer
+ */
+public class UnionWatchableGraph extends UnionGraph implements WatchableGraph {
+    
+    public UnionWatchableGraph(WatchableGraph... baseTripleCollections) {
+        super(baseTripleCollections);
+    }
+        @Override
+    public void addGraphListener(GraphListener listener, FilterTriple filter) {
+        for (Graph graph : baseTripleCollections) {
+            ((WatchableGraph)graph).addGraphListener(listener, filter);
+        }
+    }
+
+    @Override
+    public void addGraphListener(GraphListener listener, FilterTriple filter, long delay) {
+        for (Graph graph : baseTripleCollections) {
+            ((WatchableGraph)graph).addGraphListener(listener, filter, delay);
+        }
+    }
+
+    @Override
+    public void removeGraphListener(GraphListener listener) {
+        for (Graph graph : baseTripleCollections) {
+            ((WatchableGraph)graph).removeGraphListener(listener);
+        }
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UriMutatingGraph.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UriMutatingGraph.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UriMutatingGraph.java
new file mode 100644
index 0000000..4b0a4dc
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/UriMutatingGraph.java
@@ -0,0 +1,223 @@
+/*
+ * 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.clerezza.rdf.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.AbstractGraph;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.commons.rdf.impl.utils.simple.SimpleImmutableGraph;
+
+/**
+ * This wrapps a Triplecollection changing a prefix for the Iris contained
+ * in subject or object position.
+ *
+ * Currently it only supports read opearations.
+ *
+ * @author reto
+ */
+public class UriMutatingGraph implements Graph {
+
+    private final Graph base;
+    private final String sourcePrefix;
+    private final String targetPrefix;
+    private final int sourcePrefixLength;
+    private final int targetPrefixLength;
+
+    public UriMutatingGraph(Graph base, String sourcePrefix,
+            String targetPrefix) {
+        this.base = base;
+        this.sourcePrefix = sourcePrefix;
+        sourcePrefixLength= sourcePrefix.length();
+        this.targetPrefix = targetPrefix;
+        targetPrefixLength= targetPrefix.length();
+    }
+
+    private <R extends RdfTerm> R toTargetRdfTerm(final R sourceRdfTerm) {
+        if (sourceRdfTerm instanceof Iri) {
+            final Iri sourceIri = (Iri) sourceRdfTerm;
+            if (sourceIri.getUnicodeString().startsWith(sourcePrefix)) {
+                final String uriRest = sourceIri.getUnicodeString()
+                        .substring(sourcePrefixLength);
+                return (R) new Iri(targetPrefix+uriRest);
+            }
+        }
+        return sourceRdfTerm;            
+    }
+
+    private Triple toTargetTriple(Triple triple) {
+        if (triple == null) {
+            return null;
+        }
+        return new TripleImpl(toTargetRdfTerm(triple.getSubject()),
+                triple.getPredicate(), toTargetRdfTerm(triple.getObject()));
+    }
+
+    private <R extends RdfTerm> R toSourceRdfTerm(final R targetRdfTerm) {
+        if (targetRdfTerm instanceof Iri) {
+            final Iri sourceIri = (Iri) targetRdfTerm;
+            if (sourceIri.getUnicodeString().startsWith(targetPrefix)) {
+                final String uriRest = sourceIri.getUnicodeString()
+                        .substring(targetPrefixLength);
+                return (R) new Iri(sourcePrefix+uriRest);
+            }
+        }
+        return targetRdfTerm;
+    }
+
+    private Triple toSourceTriple(Triple triple) {
+        if (triple == null) {
+            return null;
+        }
+        return new TripleImpl(toSourceRdfTerm(triple.getSubject()),
+                triple.getPredicate(), toSourceRdfTerm(triple.getObject()));
+    }
+
+    @Override
+    public Iterator<Triple> filter(BlankNodeOrIri subject, Iri predicate, RdfTerm object) {
+        final Iterator<Triple> baseIter = base.filter(toSourceRdfTerm(subject),
+                predicate, toSourceRdfTerm(object));
+        return new WrappedIteraror(baseIter);
+
+
+    }
+
+
+    @Override
+    public int size() {
+        return base.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return base.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return base.contains(toSourceTriple((Triple)o));
+    }
+
+    @Override
+    public Iterator<Triple> iterator() {
+        return filter(null, null, null);
+    }
+
+    @Override
+    public Object[] toArray() {
+        Object[] result = base.toArray();
+        for (int i = 0; i < result.length; i++) {
+            Triple triple = (Triple) result[i];
+            result[i] = toTargetTriple(triple);
+        }
+        return result;
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        T[] result = base.toArray(a);
+        for (int i = 0; i < result.length; i++) {
+            Triple triple = (Triple) result[i];
+            result[i] = (T) toTargetTriple(triple);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean add(Triple e) {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        for (Object object : c) {
+            if (!contains(object)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends Triple> c) {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public void clear() {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public ImmutableGraph getImmutableGraph() {
+        return new SimpleImmutableGraph(this);
+    }
+
+    @Override
+    public ReadWriteLock getLock() {
+        return base.getLock();
+    }
+
+    class WrappedIteraror implements Iterator<Triple>{
+        private final Iterator<Triple> baseIter;
+
+        private WrappedIteraror(Iterator<Triple> baseIter) {
+            this.baseIter = baseIter;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return baseIter.hasNext();
+        }
+
+        @Override
+        public Triple next() {
+            return toTargetTriple(baseIter.next());
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/graphnodeprovider/GraphNodeProvider.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/graphnodeprovider/GraphNodeProvider.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/graphnodeprovider/GraphNodeProvider.java
new file mode 100644
index 0000000..03c73a5
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/graphnodeprovider/GraphNodeProvider.java
@@ -0,0 +1,51 @@
+package org.apache.clerezza.rdf.utils.graphnodeprovider;
+
+/*
+ * 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.
+ */
+import org.apache.commons.rdf.Iri;
+import org.apache.clerezza.rdf.utils.GraphNode;
+
+/**
+ * A service that returns a GraphNode for a specified named resource, the
+ * returned GraphNode has as BaseGraph the ContentGraph provided by the
+ * ContentGraphProvider and the for remote uris the Graphs they dereference to
+ * and for local URIs with a path-section starting with /user/{username}/ the
+ * local-public-graph of that user.
+ */
+public interface GraphNodeProvider {
+
+    /**
+     * Get a GraphNode for the specified resource, see class comments for
+     * details.
+     */
+    GraphNode get(Iri uriRef);
+
+    /**
+     * Get a GraphNode for the specified resource, The resource is assumed to be
+     * local, i.e. the method behaves like get(Iri) for a Uri with an
+     * authority section contained in the Set retuned by
+     * <code>org.apache.clerezza.platform.config.PlatformConfig#getBaseUris()</code>
+     */
+    GraphNode getLocal(Iri uriRef);
+
+    /**
+     * return true iff getLocal(uriRef).getNodeContext.size > 0
+     */
+    boolean existsLocal(Iri uriRef);
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/74f5fdb3/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/smushing/BaseSmusher.java
----------------------------------------------------------------------
diff --git a/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/smushing/BaseSmusher.java b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/smushing/BaseSmusher.java
new file mode 100644
index 0000000..1841cd1
--- /dev/null
+++ b/rdf/utils/src/main/java/org/apache/clerezza/rdf/utils/smushing/BaseSmusher.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.clerezza.rdf.utils.smushing;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.clerezza.rdf.ontologies.OWL;
+
+/**
+ *
+ * @author Reto
+ */
+public class BaseSmusher {
+
+    /**
+     * Smushes the resources in mGraph that belong to the same set in equivalenceSets,
+     * i.e. it adds all properties to one of the resources in the equivalence set.
+     * 
+     * Optionally owl:sameAs statement are added that point from the IRIs that 
+     * no longer have properties to the one with properties. If addOwlSameAs
+     * is false the IRIs will just disappear from the graph.
+     * 
+     * @param mGraph the graph to smush
+     * @param equivalenceSets sets of equivalent resources
+     * @param addOwlSameAs whether owl:sameAs statements should be added
+     */
+    public void smush(Graph mGraph, Set<Set<BlankNodeOrIri>> equivalenceSets, boolean addOwlSameAs) {
+        Map<BlankNodeOrIri, BlankNodeOrIri> current2ReplacementMap = new HashMap<BlankNodeOrIri, BlankNodeOrIri>();
+        final Graph owlSameAsGraph = new SimpleGraph();
+        for (Set<BlankNodeOrIri> equivalenceSet : equivalenceSets) {
+            final BlankNodeOrIri replacement = getReplacementFor(equivalenceSet, owlSameAsGraph);
+            for (BlankNodeOrIri current : equivalenceSet) {
+                if (!current.equals(replacement)) {
+                    current2ReplacementMap.put(current, replacement);
+                }
+            }
+        }
+        final Set<Triple> newTriples = new HashSet<Triple>();
+        Lock l = mGraph.getLock().writeLock();
+        l.lock();
+        try {
+            for (Iterator<Triple> it = mGraph.iterator(); it.hasNext();) {
+                final Triple triple = it.next();
+                final BlankNodeOrIri subject = triple.getSubject();
+                BlankNodeOrIri subjectReplacement = current2ReplacementMap.get(subject);
+                final RdfTerm object = triple.getObject();
+                @SuppressWarnings(value = "element-type-mismatch")
+                RdfTerm objectReplacement = current2ReplacementMap.get(object);
+                if ((subjectReplacement != null) || (objectReplacement != null)) {
+                    it.remove();
+                    if (subjectReplacement == null) {
+                        subjectReplacement = subject;
+                    }
+                    if (objectReplacement == null) {
+                        objectReplacement = object;
+                    }
+                    newTriples.add(new TripleImpl(subjectReplacement, triple.getPredicate(), objectReplacement));
+                }
+            }
+            for (Triple triple : newTriples) {
+                mGraph.add(triple);
+            }
+            mGraph.addAll(owlSameAsGraph);
+        } finally {
+            l.unlock();
+        }
+    }
+    
+    private BlankNodeOrIri getReplacementFor(Set<BlankNodeOrIri> equivalenceSet, 
+            Graph owlSameAsGraph) {
+        final Set<Iri> uriRefs = new HashSet<Iri>();
+        for (BlankNodeOrIri nonLiteral : equivalenceSet) {
+            if (nonLiteral instanceof Iri) {
+                uriRefs.add((Iri) nonLiteral);
+            }
+        }
+        switch (uriRefs.size()) {
+            case 1:
+                return uriRefs.iterator().next();
+            case 0:
+                return new BlankNode();
+        }
+        final Iri preferedIri = getPreferedIri(uriRefs);
+        final Iterator<Iri> uriRefIter = uriRefs.iterator();
+        while (uriRefIter.hasNext()) {
+            Iri uriRef = uriRefIter.next();
+            if (!uriRef.equals(preferedIri)) {
+                owlSameAsGraph.add(new TripleImpl(uriRef, OWL.sameAs, preferedIri));
+            }
+        }
+        return preferedIri;
+    }
+
+    
+    /**
+     * Returns a prefered IRI for the IRIs in a set. Typically and in the
+     * default implementation the IRI will be one of the set. Note however that 
+     * subclass implementations may also return another IRI to be used.
+     * 
+     * @param uriRefs
+     * @return 
+     */
+    protected Iri getPreferedIri(Set<Iri> uriRefs) {
+        final Iterator<Iri> uriRefIter = uriRefs.iterator();
+        //instead of an arbitrary one we might either decide lexicographically
+        //or look at their frequency in mGraph
+        return uriRefIter.next();
+    }
+    
+}


Mime
View raw message