You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by re...@apache.org on 2017/12/30 11:58:34 UTC
[2/4] clerezza git commit: Merged in clerezza-rdf-core
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractImmutableGraph.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractImmutableGraph.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractImmutableGraph.java
new file mode 100644
index 0000000..e5644ed
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractImmutableGraph.java
@@ -0,0 +1,112 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.clerezza.commons.rdf.BlankNode;
+import org.apache.clerezza.commons.rdf.ImmutableGraph;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.apache.clerezza.commons.rdf.impl.utils.graphmatching.GraphMatcher;
+
+/**
+ * <code>AbstractGraph</code> is an abstract implementation of <code>ImmutableGraph</code>
+ * implementing the <code>equals</code> and the <code>hashCode</code> methods.
+ *
+ * @author reto
+ *
+ */
+public abstract class AbstractImmutableGraph extends AbstractGraph
+ implements ImmutableGraph {
+
+ public final synchronized int hashCode() {
+ int result = 0;
+ for (Iterator<Triple> iter = iterator(); iter.hasNext();) {
+ result += getBlankNodeBlindHash(iter.next());
+ }
+ return result;
+ }
+
+ /**
+ * @param triple
+ * @return hash without BNode hashes
+ */
+ private int getBlankNodeBlindHash(Triple triple) {
+ int hash = triple.getPredicate().hashCode();
+ RDFTerm subject = triple.getSubject();
+
+ if (!(subject instanceof BlankNode)) {
+ hash ^= subject.hashCode() >> 1;
+ }
+ RDFTerm object = triple.getObject();
+ if (!(object instanceof BlankNode)) {
+ hash ^= object.hashCode() << 1;
+ }
+
+ return hash;
+ }
+
+ @Override
+ public boolean add(Triple e) {
+ throw new UnsupportedOperationException("Graphs are not mutable, use Graph");
+
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Triple> c) {
+ throw new UnsupportedOperationException("Graphs are not mutable, use Graph");
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException("Graphs are not mutable, use Graph");
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException("Graphs are not mutable, use Graph");
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Graphs are not mutable, use Graph");
+ }
+
+
+ @Override
+ public ImmutableGraph getImmutableGraph() {
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ImmutableGraph)) {
+ return false;
+ }
+ if (hashCode() != obj.hashCode()) {
+ return false;
+ }
+ return GraphMatcher.getValidMapping(this, (ImmutableGraph) obj) != null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractLiteral.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractLiteral.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractLiteral.java
new file mode 100644
index 0000000..a236f06
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/AbstractLiteral.java
@@ -0,0 +1,61 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import org.apache.clerezza.commons.rdf.Literal;
+
+/**
+ *
+ * @author developer
+ */
+public abstract class AbstractLiteral implements Literal {
+
+ @Override
+ public int hashCode() {
+ int result = 0;
+ if (getLanguage() != null) {
+ result = getLanguage().hashCode();
+ }
+ result += getLexicalForm().hashCode();
+ result += getDataType().hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Literal) {
+ Literal other = (Literal) obj;
+
+ if (getLanguage() == null) {
+ if (other.getLanguage() != null) {
+ return false;
+ }
+ } else {
+ if (!getLanguage().equals(other.getLanguage())) {
+ return false;
+ }
+ }
+ boolean res = getDataType().equals(other.getDataType()) && getLexicalForm().equals(other.getLexicalForm());
+ return res;
+ } else {
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/DelayedNotificator.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/DelayedNotificator.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/DelayedNotificator.java
new file mode 100644
index 0000000..1cf3321
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/DelayedNotificator.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.commons.rdf.impl.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.clerezza.commons.rdf.event.GraphEvent;
+import org.apache.clerezza.commons.rdf.event.GraphListener;
+
+
+/**
+ *
+ * @author reto
+ */
+class DelayedNotificator {
+
+ private static final Logger log = Logger.getLogger(DelayedNotificator.class.getName());
+ private static Timer timer = new Timer("Event delivery timer",true);
+
+ static class ListenerHolder {
+
+ long delay;
+ List<GraphEvent> events = null;
+ WeakReference<GraphListener> listenerRef;
+
+ public ListenerHolder(GraphListener listener, long delay) {
+ this.listenerRef = new WeakReference<GraphListener>(listener);
+ this.delay = delay;
+ }
+
+ private void registerEvent(GraphEvent event) {
+ synchronized (this) {
+ if (events == null) {
+ events = new ArrayList<GraphEvent>();
+ events.add(event);
+ timer.schedule(new TimerTask() {
+
+ @Override
+ public void run() {
+ List<GraphEvent> eventsLocal;
+ synchronized (ListenerHolder.this) {
+ eventsLocal = events;
+ events = null;
+ }
+ GraphListener listener = listenerRef.get();
+ if (listener == null) {
+ log.fine("Ignoring garbage collected listener");
+ } else {
+ try {
+ listener.graphChanged(eventsLocal);
+ } catch (Exception e) {
+ log.log(Level.WARNING, "Exception delivering ImmutableGraph event", e);
+ }
+ }
+ }
+ }, delay);
+ } else {
+ events.add(event);
+ }
+ }
+ }
+ }
+
+ private final Map<GraphListener, ListenerHolder> map = Collections.synchronizedMap(
+ new WeakHashMap<GraphListener, ListenerHolder>());
+
+ void addDelayedListener(GraphListener listener, long delay) {
+ map.put(listener, new ListenerHolder(listener, delay));
+ }
+
+ /**
+ * removes a Listener, this doesn't prevent the listenerRef from receiving
+ * events alreay scheduled.
+ *
+ * @param listenerRef
+ */
+ void removeDelayedListener(GraphListener listener) {
+ map.remove(listener);
+ }
+
+ /**
+ * if the listenerRef has not been registered as delayed listenerRef te events is
+ * forwarded synchroneously
+ * @param event
+ */
+ void sendEventToListener(GraphListener listener, GraphEvent event) {
+ ListenerHolder holder = map.get(listener);
+ if (holder == null) {
+ listener.graphChanged(Collections.singletonList(event));
+ } else {
+ holder.registerEvent(event);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LiteralImpl.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LiteralImpl.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LiteralImpl.java
new file mode 100644
index 0000000..b2aa4be
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LiteralImpl.java
@@ -0,0 +1,82 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.io.Serializable;
+
+import org.apache.clerezza.commons.rdf.IRI;
+import org.apache.clerezza.commons.rdf.Language;
+
+/**
+ *
+ * @author reto
+ */
+public class LiteralImpl extends AbstractLiteral implements Serializable {
+ private String lexicalForm;
+ private IRI dataType;
+ private int hashCode;
+ private Language language;
+
+ /**
+ * @param lexicalForm
+ * @param dataType
+ * @param Language the language of this literal
+ */
+ public LiteralImpl(String lexicalForm, IRI dataType, Language language) {
+ this.lexicalForm = lexicalForm;
+ this.dataType = dataType;
+ this.language = language;
+ this.hashCode = super.hashCode();
+ }
+
+ public IRI getDataType() {
+ return dataType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.clerezza.rdf.core.LiteralNode#getLexicalForm()
+ */
+ @Override
+ public String getLexicalForm() {
+ return lexicalForm;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ result.append('\"');
+ result.append(getLexicalForm());
+ result.append('\"');
+ result.append("^^");
+ result.append(getDataType());
+ return result.toString();
+ }
+
+ @Override
+ public Language getLanguage() {
+ return language;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LockingIterator.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LockingIterator.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LockingIterator.java
new file mode 100644
index 0000000..79747c2
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/LockingIterator.java
@@ -0,0 +1,73 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.clerezza.commons.rdf.Triple;
+
+/**
+ * Wrapps an iterator<Triple> reading entering a read-lock on every invocation
+ * of hasNext and next
+ * @author reto
+ */
+class LockingIterator implements Iterator<Triple> {
+
+ private Iterator<Triple> base;
+ private Lock readLock;
+ private Lock writeLock;
+
+ public LockingIterator(Iterator<Triple> iterator, ReadWriteLock lock) {
+ base = iterator;
+ readLock = lock.readLock();
+ writeLock = lock.writeLock();
+ }
+
+ @Override
+ public boolean hasNext() {
+ readLock.lock();
+ try {
+ return base.hasNext();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Triple next() {
+ readLock.lock();
+ try {
+ return base.next();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public void remove() {
+ writeLock.lock();
+ try {
+ base.remove();
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/PlainLiteralImpl.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/PlainLiteralImpl.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/PlainLiteralImpl.java
new file mode 100644
index 0000000..49f2633
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/PlainLiteralImpl.java
@@ -0,0 +1,80 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.io.Serializable;
+import org.apache.clerezza.commons.rdf.IRI;
+
+import org.apache.clerezza.commons.rdf.Language;
+import org.apache.clerezza.commons.rdf.Literal;
+
+/**
+ *
+ * @author reto
+ */
+public class PlainLiteralImpl extends AbstractLiteral implements Literal, Serializable {
+
+ private final String lexicalForm;
+ private final Language language;
+
+ public PlainLiteralImpl(String value) {
+ this(value, null);
+ }
+
+ public PlainLiteralImpl(String value, Language language) {
+ if (value == null) {
+ throw new IllegalArgumentException("The literal string cannot be null");
+ }
+ this.lexicalForm = value;
+ this.language = language;
+ if (language == null) {
+ dataType = XSD_STRING;
+ } else {
+ dataType = RDF_LANG_STRING;
+ }
+ }
+
+ @Override
+ public String getLexicalForm() {
+ return lexicalForm;
+ }
+
+ @Override
+ public Language getLanguage() {
+ return language;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder();
+ result.append('\"').append(lexicalForm).append('\"');
+ if (language != null) {
+ result.append("@").append(language.toString());
+ }
+ return result.toString();
+ }
+
+ @Override
+ public IRI getDataType() {
+ return dataType;
+ }
+ private final IRI dataType;
+ private static final IRI XSD_STRING = new IRI("http://www.w3.org/2001/XMLSchema#string");
+ private static final IRI RDF_LANG_STRING = new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString");
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TripleImpl.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TripleImpl.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TripleImpl.java
new file mode 100644
index 0000000..6137c4b
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TripleImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import org.apache.clerezza.commons.rdf.BlankNodeOrIRI;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.apache.clerezza.commons.rdf.IRI;
+
+/**
+ *
+ * @author reto
+ */
+public class TripleImpl implements Triple {
+
+ private final BlankNodeOrIRI subject;
+ private final IRI predicate;
+ private final RDFTerm object;
+
+ /**
+ * Creates a new <code>TripleImpl</code>.
+ *
+ * @param subject the subject.
+ * @param predicate the predicate.
+ * @param object the object.
+ * @throws IllegalArgumentException if an attribute is <code>null</code>.
+ */
+ public TripleImpl(BlankNodeOrIRI subject, IRI predicate, RDFTerm object) {
+ if (subject == null) {
+ throw new IllegalArgumentException("Invalid subject: null");
+ } else if (predicate == null) {
+ throw new IllegalArgumentException("Invalid predicate: null");
+ } else if (object == null) {
+ throw new IllegalArgumentException("Invalid object: null");
+ }
+ this.subject = subject;
+ this.predicate = predicate;
+ this.object = object;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof Triple)) {
+ return false;
+ }
+ final Triple other = (Triple) obj;
+ if (!this.subject.equals(other.getSubject())) {
+ return false;
+ }
+ if (!this.predicate.equals(other.getPredicate())) {
+ return false;
+ }
+ if (!this.object.equals(other.getObject())) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (subject.hashCode() >> 1) ^ predicate.hashCode() ^ (object.hashCode() << 1);
+ }
+
+ @Override
+ public BlankNodeOrIRI getSubject() {
+ return subject;
+ }
+
+ public IRI getPredicate() {
+ return predicate;
+ }
+
+ public RDFTerm getObject() {
+ return object;
+ }
+
+ @Override
+ public String toString() {
+ return subject + " " + predicate + " " + object + ".";
+ }
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TypedLiteralImpl.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TypedLiteralImpl.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TypedLiteralImpl.java
new file mode 100644
index 0000000..67f7c9c
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/TypedLiteralImpl.java
@@ -0,0 +1,80 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.io.Serializable;
+
+import org.apache.clerezza.commons.rdf.IRI;
+import org.apache.clerezza.commons.rdf.Language;
+import org.apache.clerezza.commons.rdf.Literal;
+
+/**
+ *
+ * @author reto
+ */
+public class TypedLiteralImpl extends AbstractLiteral implements Serializable {
+ private String lexicalForm;
+ private IRI dataType;
+ private int hashCode;
+
+ /**
+ * @param lexicalForm
+ * @param dataType
+ */
+ public TypedLiteralImpl(String lexicalForm, IRI dataType) {
+ this.lexicalForm = lexicalForm;
+ this.dataType = dataType;
+ this.hashCode = super.hashCode();
+ }
+
+ public IRI getDataType() {
+ return dataType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.clerezza.rdf.core.LiteralNode#getLexicalForm()
+ */
+ @Override
+ public String getLexicalForm() {
+ return lexicalForm;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ result.append('\"');
+ result.append(getLexicalForm());
+ result.append('\"');
+ result.append("^^");
+ result.append(getDataType());
+ return result.toString();
+ }
+
+ @Override
+ public Language getLanguage() {
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/WatchableGraphWrapper.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/WatchableGraphWrapper.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/WatchableGraphWrapper.java
new file mode 100644
index 0000000..de61fe4
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/WatchableGraphWrapper.java
@@ -0,0 +1,289 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.clerezza.commons.rdf.BlankNodeOrIRI;
+import org.apache.clerezza.commons.rdf.Graph;
+import org.apache.clerezza.commons.rdf.ImmutableGraph;
+import org.apache.clerezza.commons.rdf.IRI;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.apache.clerezza.commons.rdf.WatchableGraph;
+import org.apache.clerezza.commons.rdf.event.AddEvent;
+import org.apache.clerezza.commons.rdf.event.FilterTriple;
+import org.apache.clerezza.commons.rdf.event.GraphEvent;
+import org.apache.clerezza.commons.rdf.event.GraphListener;
+import org.apache.clerezza.commons.rdf.event.RemoveEvent;
+
+/**
+ *
+ * @author developer
+ */
+public class WatchableGraphWrapper implements WatchableGraph {
+
+ final Graph wrapped;
+
+ public WatchableGraphWrapper(Graph wrapped) {
+ this.wrapped = wrapped;
+ }
+
+
+ //all listeners
+ private final Set<ListenerConfiguration> listenerConfigs = Collections.synchronizedSet(
+ new HashSet<ListenerConfiguration>());
+ private DelayedNotificator delayedNotificator = new DelayedNotificator();
+
+ @Override
+ public Iterator<Triple> iterator() {
+ return filter(null, null, null);
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ if (!(o instanceof Triple)) {
+ return false;
+ }
+ Triple t = (Triple) o;
+ return filter(t.getSubject(), t.getPredicate(), t.getObject()).hasNext();
+ }
+
+ @Override
+ public Iterator<Triple> filter(BlankNodeOrIRI subject, IRI predicate,
+ RDFTerm object) {
+ final Iterator<Triple> baseIter = wrapped.filter(subject, predicate, object);
+ return new Iterator<Triple>() {
+
+ Triple currentTriple = null;
+
+ @Override
+ public boolean hasNext() {
+ return baseIter.hasNext();
+ }
+
+ @Override
+ public Triple next() {
+ currentTriple = baseIter.next();
+ return currentTriple;
+ }
+
+ @Override
+ public void remove() {
+ baseIter.remove();
+ dispatchEvent(new RemoveEvent(WatchableGraphWrapper.this, currentTriple));
+ }
+ };
+ }
+
+ @Override
+ public boolean add(Triple triple) {
+ boolean success = performAdd(triple);
+ if (success) {
+ dispatchEvent(new AddEvent(this, triple));
+ }
+ return success;
+ }
+
+ /**
+ * A subclass of <code>AbstractGraph</code> should override
+ * this method instead of <code>add</code> for Graph event support to be
+ * added.
+ *
+ * @param e The triple to be added to the triple collection
+ * @return
+ */
+ protected boolean performAdd(Triple e) {
+ return wrapped.add(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ Triple triple = (Triple) o;
+ boolean success = performRemove(triple);
+ if (success) {
+ dispatchEvent(new RemoveEvent(this, triple));
+ }
+ return success;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ boolean modified = false;
+ for (Iterator<? extends Object> it = c.iterator(); it.hasNext();) {
+ Object object = it.next();
+ if (remove(object)) {
+ modified = true;
+ }
+ }
+ return modified;
+ }
+
+ /**
+ * A subclass of <code>AbstractGraph</code> should override
+ * this method instead of <code>remove</code> for ImmutableGraph event support to be
+ * added.
+ *
+ * @param o The triple to be removed from the triple collection
+ * @return
+ */
+ protected boolean performRemove(Triple triple) {
+ Iterator<Triple> e = filter(null, null, null);
+ while (e.hasNext()) {
+ if (triple.equals(e.next())) {
+ e.remove();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Dispatches a <code>GraphEvent</code> to all registered listeners for which
+ * the specified <code>Triple</code> matches the <code>FilterTriple</code>s
+ * of the listeners.
+ *
+ * @param triple The Triple that was modified
+ * @param type The type of modification
+ */
+ protected void dispatchEvent(GraphEvent event) {
+ synchronized(listenerConfigs) {
+ Iterator<ListenerConfiguration> iter = listenerConfigs.iterator();
+ while (iter.hasNext()) {
+ ListenerConfiguration config = iter.next();
+ GraphListener registeredListener = config.getListener();
+ if (registeredListener == null) {
+ iter.remove();
+ continue;
+ }
+ if (config.getFilter().match(event.getTriple())) {
+ delayedNotificator.sendEventToListener(registeredListener, event);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void addGraphListener(GraphListener listener, FilterTriple filter) {
+ addGraphListener(listener, filter, 0);
+ }
+
+ @Override
+ public void addGraphListener(GraphListener listener, FilterTriple filter,
+ long delay) {
+ listenerConfigs.add(new ListenerConfiguration(listener, filter));
+ if (delay > 0) {
+ delayedNotificator.addDelayedListener(listener, delay);
+ }
+ }
+
+ @Override
+ public void removeGraphListener(GraphListener listener) {
+ synchronized(listenerConfigs) {
+ Iterator<ListenerConfiguration> iter = listenerConfigs.iterator();
+ while (iter.hasNext()) {
+ ListenerConfiguration listenerConfig = iter.next();
+ GraphListener registeredListener = listenerConfig.getListener();
+ if ((registeredListener == null) || (registeredListener.equals(listener))) {
+ iter.remove();
+ }
+ }
+ }
+ delayedNotificator.removeDelayedListener(listener);
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public ReadWriteLock getLock() {
+ return wrapped.getLock();
+ }
+
+ @Override
+ public int size() {
+ return wrapped.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return wrapped.isEmpty();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return wrapped.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return wrapped.toArray(a);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return wrapped.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Triple> c) {
+ return wrapped.addAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ return wrapped.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ wrapped.clear();
+ }
+
+ private static class ListenerConfiguration {
+
+ private WeakReference<GraphListener> listenerRef;
+ private FilterTriple filter;
+
+ private ListenerConfiguration(GraphListener listener, FilterTriple filter) {
+ this.listenerRef = new WeakReference<GraphListener>(listener);
+ this.filter = filter;
+ }
+
+ /**
+ * @return the listener
+ */
+ GraphListener getListener() {
+ GraphListener listener = listenerRef.get();
+ return listener;
+ }
+
+ /**
+ * @return the filter
+ */
+ FilterTriple getFilter() {
+ return filter;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReadLockDebug.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReadLockDebug.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReadLockDebug.java
new file mode 100644
index 0000000..1f47fe9
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReadLockDebug.java
@@ -0,0 +1,85 @@
+/*
+ * 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.commons.rdf.impl.utils.debug;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+
+/**
+ *
+ * @author mir
+ */
+public class ReadLockDebug extends ReadLock {
+
+ ReentrantReadWriteLockTracker lock;
+ StackTraceElement[] stackTrace;
+
+ ReadLock readLock;
+ public ReadLockDebug(ReentrantReadWriteLockTracker lock) {
+ super(lock);
+ this.lock = lock;
+ this.readLock = lock.realReadLock();
+ }
+
+ @Override
+ public void lock() {
+ readLock.lock();
+ lock.addLockedReadLock(this);
+ stackTrace = Thread.currentThread().getStackTrace();
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ readLock.lockInterruptibly();
+ }
+
+ @Override
+ public Condition newCondition() {
+ return readLock.newCondition();
+ }
+
+ @Override
+ public String toString() {
+ return readLock.toString();
+ }
+
+ @Override
+ public boolean tryLock() {
+ return readLock.tryLock();
+ }
+
+ @Override
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return readLock.tryLock(timeout, unit);
+ }
+
+ @Override
+ public void unlock() {
+ readLock.unlock();
+ lock.removeReadLock(this);
+ stackTrace = null;
+ }
+
+ public StackTraceElement[] getStackTrace() {
+ return stackTrace;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java
new file mode 100644
index 0000000..8f382aa
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java
@@ -0,0 +1,133 @@
+/*
+ * 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.commons.rdf.impl.utils.debug;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author mir
+ */
+public class ReentrantReadWriteLockTracker extends ReentrantReadWriteLock {
+
+
+ private Set<ReadLockDebug> lockedReadLocks = Collections.synchronizedSet(new HashSet<ReadLockDebug>());
+ private final WriteLockDebug writeLock = new WriteLockDebug(this);
+ @Override
+ protected Thread getOwner() {
+ return super.getOwner();
+ }
+
+ @Override
+ protected Collection<Thread> getQueuedReaderThreads() {
+ return super.getQueuedReaderThreads();
+ }
+
+ @Override
+ protected Collection<Thread> getQueuedThreads() {
+ return super.getQueuedThreads();
+ }
+
+ @Override
+ protected Collection<Thread> getQueuedWriterThreads() {
+ return super.getQueuedWriterThreads();
+ }
+
+ @Override
+ public int getReadHoldCount() {
+ return super.getReadHoldCount();
+ }
+
+ @Override
+ public int getReadLockCount() {
+ return super.getReadLockCount();
+ }
+
+ @Override
+ public int getWaitQueueLength(Condition condition) {
+ return super.getWaitQueueLength(condition);
+ }
+
+ @Override
+ protected Collection<Thread> getWaitingThreads(Condition condition) {
+ return super.getWaitingThreads(condition);
+ }
+
+ @Override
+ public int getWriteHoldCount() {
+ return super.getWriteHoldCount();
+ }
+
+ @Override
+ public boolean hasWaiters(Condition condition) {
+ return super.hasWaiters(condition);
+ }
+
+ @Override
+ public boolean isWriteLocked() {
+ return super.isWriteLocked();
+ }
+
+ @Override
+ public boolean isWriteLockedByCurrentThread() {
+ return super.isWriteLockedByCurrentThread();
+ }
+
+ @Override
+ public ReadLock readLock() {
+ return new ReadLockDebug(this);
+ }
+
+ ReadLock realReadLock() {
+ return super.readLock();
+ }
+
+ WriteLock realWriteLock() {
+ return super.writeLock();
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+
+ @Override
+ public WriteLockDebug writeLock() {
+ return writeLock;
+ }
+
+ void addLockedReadLock(ReadLockDebug lock) {
+ lockedReadLocks.add(lock);
+ }
+
+ void removeReadLock(ReadLockDebug lock) {
+ lockedReadLocks.remove(lock);
+ }
+
+ public Set<ReadLockDebug> getLockedReadLocks() {
+ return lockedReadLocks;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/WriteLockDebug.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/WriteLockDebug.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/WriteLockDebug.java
new file mode 100644
index 0000000..a4261e3
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/debug/WriteLockDebug.java
@@ -0,0 +1,89 @@
+/*
+ * 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.commons.rdf.impl.utils.debug;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+/**
+ *
+ * @author mir
+ */
+public class WriteLockDebug extends WriteLock {
+
+ private ReentrantReadWriteLockTracker lock;
+ private WriteLock writeLock;
+ private StackTraceElement[] stackTrace;
+
+ public WriteLockDebug(ReentrantReadWriteLockTracker lock) {
+ super(lock);
+ this.lock = lock;
+ this.writeLock = lock.realWriteLock();
+ }
+
+ @Override
+ public int getHoldCount() {
+ return writeLock.getHoldCount();
+ }
+
+ @Override
+ public boolean isHeldByCurrentThread() {
+ return writeLock.isHeldByCurrentThread();
+ }
+
+ @Override
+ public void lock() {
+ writeLock.lock();
+ stackTrace = Thread.currentThread().getStackTrace();
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ writeLock.lockInterruptibly();
+ }
+
+ @Override
+ public Condition newCondition() {
+ return writeLock.newCondition();
+ }
+
+ @Override
+ public boolean tryLock() {
+ return writeLock.tryLock();
+ }
+
+ @Override
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return writeLock.tryLock(timeout, unit);
+ }
+
+ @Override
+ public void unlock() {
+ writeLock.unlock();
+ stackTrace = null;
+ }
+
+ public StackTraceElement[] getStackTrace() {
+ return stackTrace;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphMatcher.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphMatcher.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphMatcher.java
new file mode 100644
index 0000000..ce65d1a
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphMatcher.java
@@ -0,0 +1,140 @@
+/*
+ * 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.commons.rdf.impl.utils.graphmatching;
+
+
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.clerezza.commons.rdf.BlankNode;
+import org.apache.clerezza.commons.rdf.BlankNodeOrIRI;
+import org.apache.clerezza.commons.rdf.Graph;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.apache.clerezza.commons.rdf.impl.utils.TripleImpl;
+import org.apache.clerezza.commons.rdf.impl.utils.simple.SimpleMGraph;
+
+/**
+ * @author reto
+ *
+ */
+public class GraphMatcher {
+
+
+ private final static Logger log = Logger.getLogger(GraphMatcher.class.getName());
+
+ /**
+ * get a mapping from g1 to g2 or null if the graphs are not isomorphic. The
+ * returned map maps each <code>BNode</code>s from g1 to one
+ * of g2. If the graphs are ground graphs the method return an empty map if
+ * the ImmutableGraph are equals and null otherwise.
+ * <p/>
+ * NOTE: This method does not returned mapping from blank nodes to grounded
+ * nodes, a bnode in g1 is not a vraiable that may match any node, but must
+ * match a bnode in g2.
+ * <p/>
+ *
+ * On the algorithm:<br/>
+ * - In a first step it checked if every grounded triple in g1 matches one
+ * in g2<br/>
+ * - [optional] blank node blind matching</br>
+ * - in a map mbng1 bnode of g1 is mapped to a set of of its
+ * properties and inverse properties, this is the predicate and the object
+ * or subject respectively, analoguosly in mbgn2 every bnode of g2<br/>
+ * - based on the incoming and outgoing properties a hash is calculated for
+ * each bnode, in the first step when calculating the hash aconstant value
+ * is taken for the bnodes that might be subject or object in the (inverse properties)
+ * - hash-classes:
+ *
+ * @param g1
+ * @param g2
+ * @return a Set of NodePairs
+ */
+ public static Map<BlankNode, BlankNode> getValidMapping(Graph og1, Graph og2) {
+ Graph g1 = new SimpleMGraph(og1);
+ Graph g2 = new SimpleMGraph(og2);
+ if (!Utils.removeGrounded(g1,g2)) {
+ return null;
+ }
+ final HashMatching hashMatching;
+ try {
+ hashMatching = new HashMatching(g1, g2);
+ } catch (GraphNotIsomorphicException ex) {
+ return null;
+ }
+ Map<BlankNode, BlankNode> matchings = hashMatching.getMatchings();
+ if (g1.size() > 0) {
+ //start trial an error matching
+ //TODO (CLEREZZA-81) at least in the situation where one matching
+ //group is big (approx > 5) we should switch back to hash-based matching
+ //after a first guessed matching, rather than try all permutations
+ Map<BlankNode, BlankNode> remainingMappings = trialAndErrorMatching(g1, g2, hashMatching.getMatchingGroups());
+ if (remainingMappings == null) {
+ return null;
+ } else {
+ matchings.putAll(remainingMappings);
+ }
+ }
+ return matchings;
+ }
+
+ private static Map<BlankNode, BlankNode> trialAndErrorMatching(Graph g1, Graph g2,
+ Map<Set<BlankNode>, Set<BlankNode>> matchingGroups) {
+ if (log.isLoggable(Level.FINE)) {
+ Set<BlankNode> bn1 = Utils.getBNodes(g1);
+ log.log(Level.FINE,"doing trial and error matching for {0}"+" bnodes, "+"in graphs of size: {1}.", new Object[]{bn1.size(), g1.size()});
+ }
+ Iterator<Map<BlankNode, BlankNode>> mappingIter
+ = GroupMappingIterator.create(matchingGroups);
+ while (mappingIter.hasNext()) {
+ Map<BlankNode, BlankNode> map = mappingIter.next();
+ if (checkMapping(g1, g2, map)) {
+ return map;
+ }
+ }
+ return null;
+ }
+
+ private static boolean checkMapping(Graph g1, Graph g2, Map<BlankNode, BlankNode> map) {
+ for (Triple triple : g1) {
+ if (!g2.contains(map(triple, map))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static Triple map(Triple triple, Map<BlankNode, BlankNode> map) {
+ final BlankNodeOrIRI oSubject = triple.getSubject();
+
+ BlankNodeOrIRI subject = oSubject instanceof BlankNode ?
+ map.get((BlankNode)oSubject) : oSubject;
+
+ RDFTerm oObject = triple.getObject();
+ RDFTerm object = oObject instanceof BlankNode ?
+ map.get((BlankNode)oObject) : oObject;
+ return new TripleImpl(subject, triple.getPredicate(), object);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java
new file mode 100644
index 0000000..5b5600f
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java
@@ -0,0 +1,28 @@
+/*
+ * 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.commons.rdf.impl.utils.graphmatching;
+
+/**
+ *
+ * @author reto
+ */
+class GraphNotIsomorphicException extends Exception {
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java
new file mode 100644
index 0000000..4c7a0ae
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2010 reto.
+ *
+ * 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.
+ * under the License.
+ */
+
+package org.apache.clerezza.commons.rdf.impl.utils.graphmatching;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * Iterates over all mappings from each element of every Set<T> to each
+ * elemenent of their corresponding Set<U>.
+ *
+ * @author reto
+ */
+class GroupMappingIterator<T,U> implements Iterator<Map<T, U>> {
+
+ private Iterator<Map<T, U>> firstPartIter;
+ private Map<T, U> currentFirstPart;
+ final private Map<Set<T>, Set<U>> restMap;
+ private Iterator<Map<T, U>> currentRestPartIter;
+
+ static <T,U> Iterator<Map<T, U>> create(Map<Set<T>, Set<U>> matchingGroups) {
+ if (matchingGroups.size() > 1) {
+ return new GroupMappingIterator<T, U>(matchingGroups);
+ } else {
+ if (matchingGroups.size() == 0) {
+ return new ArrayList<Map<T, U>>(0).iterator();
+ }
+ Map.Entry<Set<T>, Set<U>> entry = matchingGroups.entrySet().iterator().next();
+ return new MappingIterator<T,U>(entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ private GroupMappingIterator(Map<Set<T>, Set<U>> matchingGroups) {
+ if (matchingGroups.size() == 0) {
+ throw new IllegalArgumentException("matchingGroups must not be empty");
+ }
+ restMap = new HashMap<Set<T>, Set<U>>();
+ boolean first = true;
+ for (Map.Entry<Set<T>, Set<U>> entry : matchingGroups.entrySet()) {
+ if (first) {
+ firstPartIter = new MappingIterator<T,U>(entry.getKey(),
+ entry.getValue());
+ first = false;
+ } else {
+ restMap.put(entry.getKey(), entry.getValue());
+ }
+ }
+ currentRestPartIter = create(restMap);
+ currentFirstPart = firstPartIter.next();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return firstPartIter.hasNext() || currentRestPartIter.hasNext();
+ }
+
+ @Override
+ public Map<T, U> next() {
+ Map<T, U> restPart;
+ if (currentRestPartIter.hasNext()) {
+ restPart = currentRestPartIter.next();
+ } else {
+ if (firstPartIter.hasNext()) {
+ currentFirstPart = firstPartIter.next();
+ currentRestPartIter = create(restMap);
+ restPart = currentRestPartIter.next();
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ Map<T, U> result = new HashMap<T, U>(restPart);
+ result.putAll(currentFirstPart);
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/HashMatching.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/HashMatching.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/HashMatching.java
new file mode 100644
index 0000000..369cf5c
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/HashMatching.java
@@ -0,0 +1,268 @@
+/*
+ * 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.commons.rdf.impl.utils.graphmatching;
+
+
+import org.apache.clerezza.commons.rdf.impl.utils.graphmatching.collections.IntHashMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.apache.clerezza.commons.rdf.BlankNode;
+import org.apache.clerezza.commons.rdf.Graph;
+import org.apache.clerezza.commons.rdf.BlankNodeOrIRI;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.apache.clerezza.commons.rdf.Graph;
+import org.apache.clerezza.commons.rdf.IRI;
+import org.apache.clerezza.commons.rdf.impl.utils.TripleImpl;
+import org.apache.clerezza.commons.rdf.impl.utils.graphmatching.collections.IntIterator;
+
+/**
+ *
+ * @author reto
+ */
+public class HashMatching {
+
+ private Map<BlankNode, BlankNode> matchings = new HashMap<BlankNode, BlankNode>();
+ private Map<Set<BlankNode>, Set<BlankNode>> matchingGroups;
+
+ /**
+ * tc1 and tc2 will be modified: the triples containing no unmatched bnode
+ * will be removed
+ *
+ * @param tc1
+ * @param tc2
+ * @throws GraphNotIsomorphicException
+ */
+ HashMatching(Graph tc1, Graph tc2) throws GraphNotIsomorphicException {
+ int foundMatchings = 0;
+ int foundMatchingGroups = 0;
+ Map<BlankNode, Integer> bNodeHashMap = new HashMap<BlankNode, Integer>();
+ while (true) {
+ bNodeHashMap = matchByHashes(tc1, tc2, bNodeHashMap);
+ if (bNodeHashMap == null) {
+ throw new GraphNotIsomorphicException();
+ }
+ if (matchings.size() == foundMatchings) {
+ if (!(matchingGroups.size() > foundMatchingGroups)) {
+ break;
+ }
+ }
+ foundMatchings = matchings.size();
+ foundMatchingGroups = matchingGroups.size();
+ }
+ }
+
+ /**
+ *
+ * @return a map containing set of which each bnodes mappes one of the other set
+ */
+ public Map<Set<BlankNode>, Set<BlankNode>> getMatchingGroups() {
+ return matchingGroups;
+ }
+
+ public Map<BlankNode, BlankNode> getMatchings() {
+ return matchings;
+ }
+
+
+ private static IntHashMap<Set<BlankNode>> getHashNodes(Map<BlankNode,
+ Set<Property>> bNodePropMap, Map<BlankNode, Integer> bNodeHashMap) {
+ IntHashMap<Set<BlankNode>> result = new IntHashMap<Set<BlankNode>>();
+ for (Map.Entry<BlankNode, Set<Property>> entry : bNodePropMap.entrySet()) {
+ int hash = computeHash(entry.getValue(), bNodeHashMap);
+ Set<BlankNode> bNodeSet = result.get(hash);
+ if (bNodeSet == null) {
+ bNodeSet = new HashSet<BlankNode>();
+ result.put(hash,bNodeSet);
+ }
+ bNodeSet.add(entry.getKey());
+ }
+ return result;
+ }
+ /*
+ * returns a Map from bnodes to hash that can be used for future
+ * refinements, this could be separate for each ImmutableGraph.
+ *
+ * triples no longer containing an unmatched bnodes ae removed.
+ *
+ * Note that the matched node are not guaranteed to be equals, but only to
+ * be the correct if the graphs are isomorphic.
+ */
+ private Map<BlankNode, Integer> matchByHashes(Graph g1, Graph g2,
+ Map<BlankNode, Integer> bNodeHashMap) {
+ Map<BlankNode, Set<Property>> bNodePropMap1 = getBNodePropMap(g1);
+ Map<BlankNode, Set<Property>> bNodePropMap2 = getBNodePropMap(g2);
+ IntHashMap<Set<BlankNode>> hashNodeMap1 = getHashNodes(bNodePropMap1, bNodeHashMap);
+ IntHashMap<Set<BlankNode>> hashNodeMap2 = getHashNodes(bNodePropMap2, bNodeHashMap);
+ if (!hashNodeMap1.keySet().equals(hashNodeMap2.keySet())) {
+ return null;
+ }
+
+ matchingGroups = new HashMap<Set<BlankNode>, Set<BlankNode>>();
+ IntIterator hashIter = hashNodeMap1.keySet().intIterator();
+ while (hashIter.hasNext()) {
+ int hash = hashIter.next();
+ Set<BlankNode> nodes1 = hashNodeMap1.get(hash);
+ Set<BlankNode> nodes2 = hashNodeMap2.get(hash);
+ if (nodes1.size() != nodes2.size()) {
+ return null;
+ }
+ if (nodes1.size() != 1) {
+ matchingGroups.put(nodes1, nodes2);
+ continue;
+ }
+ final BlankNode bNode1 = nodes1.iterator().next();
+ final BlankNode bNode2 = nodes2.iterator().next();
+ matchings.put(bNode1,bNode2);
+ //in the graphs replace node occurences with grounded node,
+ BlankNodeOrIRI mappedNode = new MappedNode(bNode1, bNode2);
+ replaceNode(g1,bNode1, mappedNode);
+ replaceNode(g2, bNode2, mappedNode);
+ //remove grounded triples
+ if (!Utils.removeGrounded(g1,g2)) {
+ return null;
+ }
+ }
+ Map<BlankNode, Integer> result = new HashMap<BlankNode, Integer>();
+ addInverted(result, hashNodeMap1);
+ addInverted(result, hashNodeMap2);
+ return result;
+ }
+ private static int computeHash(Set<Property> propertySet, Map<BlankNode, Integer> bNodeHashMap) {
+ int result = 0;
+ for (Property property : propertySet) {
+ result += property.hashCode(bNodeHashMap);
+ }
+ return result;
+ }
+ private static Map<BlankNode, Set<Property>> getBNodePropMap(Graph g) {
+ Set<BlankNode> bNodes = Utils.getBNodes(g);
+ Map<BlankNode, Set<Property>> result = new HashMap<BlankNode, Set<Property>>();
+ for (BlankNode bNode : bNodes) {
+ result.put(bNode, getProperties(bNode, g));
+ }
+ return result;
+ }
+ private static Set<Property> getProperties(BlankNode bNode, Graph g) {
+ Set<Property> result = new HashSet<Property>();
+ Iterator<Triple> ti = g.filter(bNode, null, null);
+ while (ti.hasNext()) {
+ Triple triple = ti.next();
+ result.add(new ForwardProperty(triple.getPredicate(), triple.getObject()));
+ }
+ ti = g.filter(null, null, bNode);
+ while (ti.hasNext()) {
+ Triple triple = ti.next();
+ result.add(new BackwardProperty(triple.getSubject(), triple.getPredicate()));
+ }
+ return result;
+ }
+ private static int nodeHash(RDFTerm resource, Map<BlankNode, Integer> bNodeHashMap) {
+ if (resource instanceof BlankNode) {
+ Integer mapValue = bNodeHashMap.get((BlankNode)resource);
+ if (mapValue == null) {
+ return 0;
+ } else {
+ return mapValue;
+ }
+ } else {
+ return resource.hashCode();
+ }
+ }
+ private static void replaceNode(Graph graph, BlankNode bNode, BlankNodeOrIRI replacementNode) {
+ Set<Triple> triplesToRemove = new HashSet<Triple>();
+ for (Triple triple : graph) {
+ Triple replacementTriple = getReplacement(triple, bNode, replacementNode);
+ if (replacementTriple != null) {
+ triplesToRemove.add(triple);
+ graph.add(replacementTriple);
+ }
+ }
+ graph.removeAll(triplesToRemove);
+ }
+ private static Triple getReplacement(Triple triple, BlankNode bNode, BlankNodeOrIRI replacementNode) {
+ if (triple.getSubject().equals(bNode)) {
+ if (triple.getObject().equals(bNode)) {
+ return new TripleImpl(replacementNode, triple.getPredicate(), replacementNode);
+ } else {
+ return new TripleImpl(replacementNode, triple.getPredicate(), triple.getObject());
+ }
+ } else {
+ if (triple.getObject().equals(bNode)) {
+ return new TripleImpl(triple.getSubject(), triple.getPredicate(), replacementNode);
+ } else {
+ return null;
+ }
+ }
+ }
+ private static void addInverted(Map<BlankNode, Integer> result, IntHashMap<Set<BlankNode>> hashNodeMap) {
+ for (int hash : hashNodeMap.keySet()) {
+ Set<BlankNode> bNodes = hashNodeMap.get(hash);
+ for (BlankNode bNode : bNodes) {
+ result.put(bNode, hash);
+ }
+ }
+ }
+
+ private static class BackwardProperty implements Property {
+ private BlankNodeOrIRI subject;
+ private IRI predicate;
+
+ public BackwardProperty(BlankNodeOrIRI subject, IRI predicate) {
+ this.subject = subject;
+ this.predicate = predicate;
+ }
+
+ @Override
+ public int hashCode(Map<BlankNode, Integer> bNodeHashMap) {
+ return 0xFF ^ predicate.hashCode() ^ nodeHash(subject, bNodeHashMap);
+ }
+
+ }
+ private static class ForwardProperty implements Property {
+ private IRI predicate;
+ private RDFTerm object;
+
+ public ForwardProperty(IRI predicate, RDFTerm object) {
+ this.predicate = predicate;
+ this.object = object;
+ }
+
+ @Override
+ public int hashCode(Map<BlankNode, Integer> bNodeHashMap) {
+ return predicate.hashCode() ^ nodeHash(object, bNodeHashMap);
+ }
+ }
+ private static class MappedNode implements BlankNodeOrIRI {
+ private BlankNode bNode1, bNode2;
+
+ public MappedNode(BlankNode bNode1, BlankNode bNode2) {
+ this.bNode1 = bNode1;
+ this.bNode2 = bNode2;
+ }
+
+ }
+ private static interface Property {
+ public int hashCode(Map<BlankNode, Integer> bNodeHashMap);
+ }
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/MappingIterator.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/MappingIterator.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/MappingIterator.java
new file mode 100644
index 0000000..016b590
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/MappingIterator.java
@@ -0,0 +1,76 @@
+package org.apache.clerezza.commons.rdf.impl.utils.graphmatching;
+
+/*
+ * 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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An iterator over all possible mapping beetween the elemnets of two sets of
+ * the same size, each mapping maps each element from set1 to a disctinct one of
+ * set2.
+ *
+ *
+ *
+ * @author reto
+ */
+class MappingIterator<T,U> implements Iterator<Map<T, U>> {
+
+ private List<T> list1;
+ private Iterator<List<U>> permutationList2Iterator;
+
+
+ public MappingIterator(Set<T> set1, Set<U> set2) {
+ if (set1.size() != set2.size()) {
+ throw new IllegalArgumentException();
+ }
+ this.list1 = new ArrayList<T>(set1);
+ permutationList2Iterator = new PermutationIterator<U>(
+ new ArrayList<U>(set2));
+ }
+
+ @Override
+ public boolean hasNext() {
+ return permutationList2Iterator.hasNext();
+ }
+
+ @Override
+ public Map<T, U> next() {
+ List<U> list2 = permutationList2Iterator.next();
+ Map<T, U> result = new HashMap<T, U>(list1.size());
+ for (int i = 0; i < list1.size(); i++) {
+ result.put(list1.get(i), list2.get(i));
+ }
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/PermutationIterator.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/PermutationIterator.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/PermutationIterator.java
new file mode 100644
index 0000000..6f01828
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/PermutationIterator.java
@@ -0,0 +1,107 @@
+/*
+ * 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.commons.rdf.impl.utils.graphmatching;
+
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ *
+ * An Iterator over all permuations of a list.
+ *
+ * @author reto
+ */
+class PermutationIterator<T> implements Iterator<List<T>> {
+
+ private Iterator<List<T>> restIterator;
+ private List<T> list;
+ private List<T> next;
+ int posInList = 0; //the position of the last element of next returned list
+ //with list, this is the one excluded from restIterator
+
+ PermutationIterator(List<T> list) {
+ this.list = Collections.unmodifiableList(list);
+ if (list.size() > 1) {
+ createRestList();
+ }
+ prepareNext();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public List<T> next() {
+ List<T> result = next;
+ if (result == null) {
+ throw new NoSuchElementException();
+ }
+ prepareNext();
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ private void createRestList() {
+ List<T> restList = new ArrayList<T>(list);
+ restList.remove(posInList);
+ restIterator = new PermutationIterator<T>(restList);
+ }
+
+ private void prepareNext() {
+ next = getNext();
+
+ }
+ private List<T> getNext() {
+ if (list.size() == 0) {
+ return null;
+ }
+ if (list.size() == 1) {
+ if (posInList++ == 0) {
+ return new ArrayList<T>(list);
+ } else {
+ return null;
+ }
+ } else {
+ if (!restIterator.hasNext()) {
+ if (posInList < (list.size()-1)) {
+ posInList++;
+ createRestList();
+ } else {
+ return null;
+ }
+ }
+ List<T> result = restIterator.next();
+ result.add(list.get(posInList));
+ return result;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/clerezza/blob/2109cae5/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/Utils.java
----------------------------------------------------------------------
diff --git a/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/Utils.java b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/Utils.java
new file mode 100644
index 0000000..68e178b
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/clerezza/commons/rdf/impl/utils/graphmatching/Utils.java
@@ -0,0 +1,82 @@
+package org.apache.clerezza.commons.rdf.impl.utils.graphmatching;
+/*
+ *
+ * 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 java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.clerezza.commons.rdf.BlankNode;
+import org.apache.clerezza.commons.rdf.Triple;
+
+public class Utils {
+
+ static Set<BlankNode> getBNodes(Collection<Triple> s) {
+ Set<BlankNode> result = new HashSet<BlankNode>();
+ for (Triple triple : s) {
+ if (triple.getSubject() instanceof BlankNode) {
+ result.add((BlankNode) triple.getSubject());
+ }
+ if (triple.getObject() instanceof BlankNode) {
+ result.add((BlankNode) triple.getObject());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * removes the common grounded triples from s1 and s2. returns false if
+ * a grounded triple is not in both sets, true otherwise
+ */
+ static boolean removeGrounded(Collection<Triple> s1, Collection<Triple> s2) {
+ Iterator<Triple> triplesIter = s1.iterator();
+ while (triplesIter.hasNext()) {
+ Triple triple = triplesIter.next();
+ if (!isGrounded(triple)) {
+ continue;
+ }
+ if (!s2.remove(triple)) {
+ return false;
+ }
+ triplesIter.remove();
+ }
+ //for efficiency we might skip this (redefine method)
+ for (Triple triple : s2) {
+ if (isGrounded(triple)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isGrounded(Triple triple) {
+ if (triple.getSubject() instanceof BlankNode) {
+ return false;
+ }
+ if (triple.getObject() instanceof BlankNode) {
+ return false;
+ }
+ return true;
+ }
+
+}