Back to git
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5d29018
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target/
+.svn
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..66a6d0f
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,8 @@
+Apache Commons RDF
+Copyright 2001-2014 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes software developed at
+https://github.com/commons-rdf/commons-rdf.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5e05c3d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,72 @@
+## Building
+
+Build using Apache Maven with
+
+    mvn install
+
+## Documentation
+
+You can build the documentation with:
+
+    mvn site
+
+## FAQ
+
+Some more advanced questions focused on showing the differences to other proposed APIs.
+
+### Can I add RdfTerms from one implementation to another?
+
+Yes, any compliant implementation of BlankNode, Iri or Literal as well as Triple
+can be added to any implemenation of Graph, as long the Graph supports adding triples. Implementation 
+may not require the nodes to be of a particular implementation of having been 
+created with a specific factory.
+
+### How does it work?
+
+Implementation might need to map instances of BlankNode to their internal 
+implementation. This should be done in a way that when there is no more reference
+to the BlankNode object (i.e. when the object can be garbage collected) the mapping
+to the internal implementation is removed from memory to. This can be achieved 
+by using a java.util.WeakHashMap
+
+### Do I get back the same object that I added?
+
+For instances of Iri or Literals you get back an object that result equal to the
+originally added object, i.e. an object with the same HashCode and of which the
+equals method return true when compared with the originally added object. Ther
+is no guarantee that the same instance will be returned.
+For instances of BlankNode the above in only guaranteed as long as the original 
+object is referenced. When the original object becomes eligible for garbage 
+collection the implementation may start returning a different (an not equal)
+object. In practice this means BlankNode objects cannot safely be serialized 
+(using Java serialization) or passed around via RMI.
+
+### Can an implementation remove redundant information from a Graph?
+
+Yes, as long as this doesn't affect any BlankNode instance that is currently 
+reachable (i.e. the Java object is in memory and is not eligible for garbage
+collection).
+
+For  example given the non-lean graph:
+
+    ex:a ex:p _:x .
+    _:y ex:p _:x .
+
+As long as there is no BlankNode instance referencing _:y the implementation can
+reduce the graph to:
+
+    ex:a ex:p _:x .
+
+removing the redundancy. If however there is a reachable BlankNode instance for 
+_:y the implementation must not remove the redundancy as the code which has
+access to the object can go on adding a triple:
+
+    _:y ex:p2 ex:b .
+
+Thus creating a graph that doesn't contain any internal redundancy, namely:
+
+    ex:a ex:p _:x .
+    _:y ex:p _:x .
+    _:y ex:p2 ex:b .
+
+
diff --git a/alerts.txt b/alerts.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/alerts.txt
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 0000000..7994cd2
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+   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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-parent</artifactId>
+        <version>37</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>commons-rdf</groupId>
+    <artifactId>commons-rdf-api</artifactId>
+    <version>0.1-SNAPSHOT</version>
+    <name>Apache Commons RDF API</name>
+    <description>
+        Apache Commons RDF provides an API modelling the RDF data model as defined by 
+        http://www.w3.org/TR/rdf11-concepts/
+    </description>
+    <url>http://commons.apache.org/sandbox/commons-rdf/</url>
+    <!-- TBD
+    <issueManagement>
+        <system>jira</system>
+        <url>http://issues.apache.org/jira/browse/RDF</url>
+    </issueManagement>
+    -->
+    <inceptionYear>2014</inceptionYear>
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/rdf/trunk</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/rdf/trunk</developerConnection>
+        <url>http://svn.apache.org/viewvc/commons/proper/rdf/trunk</url>
+    </scm>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <distributionManagement>
+      <site>
+        <id>apache.website</id>
+        <name>Apache Commons Site</name>
+        <url>${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid}</url>
+      </site>
+    </distributionManagement>
+
+    <properties>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+        <commons.javadoc.java.link>http://docs.oracle.com/javase/7/docs/api/</commons.javadoc.java.link>
+        <commons.componentid>rdf</commons.componentid>
+        <commons.release.version>${project.version}</commons.release.version>
+        <commons.encoding>UTF-8</commons.encoding>
+<!--        <commons.rc.version>RC1</commons.rc.version>
+        <commons.release.desc>(Requires Java ${maven.compiler.target} or later)</commons.release.desc>
+        <commons.release.2.version>1.4.1</commons.release.2.version>
+        <commons.release.2.binary.suffix />
+        <commons.release.2.desc>(Requires Java 1.3 or later)</commons.release.2.desc> -->
+        <!-- TBD <commons.jira.id>RDF</commons.jira.id>
+        <commons.jira.pid></commons.jira.pid> -->
+    </properties>
+
+    <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-compiler-plugin</artifactId>
+              <version>${commons.compiler.version}</version>
+              <configuration>
+                <!-- Fix incremental compiler bug, see https://jira.codehaus.org/browse/MCOMPILER-205 etc. -->
+                <excludes>
+                  <exclude>**/package-info.java</exclude>
+                </excludes>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+        <plugins>
+
+            <!-- Exclude examples from binary jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <!-- Exclude examples from source jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>**/*FunctionalTest.java</exclude>
+                        <exclude>**/POP3*Test.java</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/bin.xml</descriptor>
+                        <descriptor>src/main/assembly/src.xml</descriptor>
+                    </descriptors>
+                    <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <configuration>
+                            <target>
+                                <jar destfile="target/commons-net-ftp-${project.version}.jar">
+                                    <metainf dir="${basedir}" includes="NOTICE.txt,LICENSE.txt" />
+                                    <manifest>
+                                        <attribute name="Extension-Name" value="org.apache.commons.net" />
+                                        <attribute name="Specification-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Vendor" value="${project.organization.name}" />
+                                        <attribute name="Implementation-Version" value="${project.version}" />
+                                        <attribute name="Implementation-Vendor-Id" value="org.apache" />
+                                        <attribute name="Implementation-Build" value="${implementation.build}"/>
+                                        <attribute name="X-Compile-Source-JDK" value="${maven.compiler.source}" />
+                                        <attribute name="X-Compile-Target-JDK" value="${maven.compiler.target}" />
+                                    </manifest>
+                                    <fileset dir="target/classes" includes="org/apache/commons/net/ftp/**,org/apache/commons/net/*,org/apache/commons/net/io/*,org/apache/commons/net/util/*" />
+                                </jar>
+                                <!--
+                                    Create the binary examples jar, which will be added to the binary zip/tgz,
+                                    but not deployed independently to Maven
+                                -->
+                                <jar destfile="target/commons-net-examples-${project.version}.jar">
+                                    <metainf dir="${basedir}" includes="NOTICE.txt,LICENSE.txt" />
+                                    <manifest>
+                                        <attribute name="Extension-Name" value="org.apache.commons.net" />
+                                        <attribute name="Specification-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Vendor" value="${project.organization.name}" />
+                                        <attribute name="Implementation-Version" value="${project.version}" />
+                                        <attribute name="Implementation-Vendor-Id" value="org.apache" />
+                                        <attribute name="Implementation-Build" value="${implementation.build}"/>
+                                        <attribute name="X-Compile-Source-JDK" value="${maven.compiler.source}" />
+                                        <attribute name="X-Compile-Target-JDK" value="${maven.compiler.target}" />
+                                        <!-- Helper application -->
+                                        <attribute name="Main-Class" value="examples/Main" />
+                                        <!-- Allow java -jar examples.jar to work -->
+                                        <attribute name="Class-Path" value="commons-net-${project.version}.jar" />
+                                    </manifest>
+                                    <fileset dir="target/classes" includes="examples/**" />
+                                </jar>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--  Attaches the commons-net-ftp and examples JARs to the Maven lifecycle
+                  to ensure they will be signed and deployed as normal -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>attach-artifacts</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>target/commons-net-ftp-${project.version}.jar</file>
+                                    <type>jar</type>
+                                    <classifier>ftp</classifier>
+                                </artifact>
+                                <artifact>
+                                    <file>target/commons-net-examples-${project.version}.jar</file>
+                                    <type>jar</type>
+                                    <classifier>examples</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Exclude examples from Javadoc jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>examples.*</excludePackageNames>
+                </configuration>
+            </plugin>
+
+            <!-- Copy the examples sources -->
+            <plugin>
+              <artifactId>maven-resources-plugin</artifactId>
+              <executions>
+                <execution>
+                  <id>copy-resources</id>
+                  <phase>pre-site</phase>
+                  <goals>
+                    <goal>copy-resources</goal>
+                  </goals>
+                  <configuration>
+                    <outputDirectory>${basedir}/target/site/examples</outputDirectory>
+                    <resources>
+                      <resource>
+                        <directory>src/main/java/examples</directory>
+                        <excludes>
+                          <exclude>**/Main.java</exclude>
+                        </excludes>
+                        <filtering>false</filtering>
+                      </resource>
+                    </resources>
+                  </configuration>
+                </execution>
+              </executions>
+            </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-scm-publish-plugin</artifactId>
+            <configuration>
+              <ignorePathsToDelete>
+                <ignorePathToDelete>javadocs</ignorePathToDelete>
+              </ignorePathsToDelete>
+            </configuration>
+          </plugin>
+
+        </plugins>
+
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-changes-plugin</artifactId>
+                <version>${commons.changes.version}</version>
+                <configuration>
+                    <issueLinkTemplatePerSystem>
+                        <default>%URL%/%ISSUE%</default>
+                    </issueLinkTemplatePerSystem>
+                    <template>release-notes.vm</template>
+                    <templateDirectory>src/changes</templateDirectory>
+                    <!--  Add sample JIRA report - 'mvn changes:jira-report' or 'mvn site' -->
+                    <onlyCurrentVersion>false</onlyCurrentVersion>
+                    <columnNames>Fix Version,Key,Component,Summary,Type,Resolution,Status</columnNames>
+                    <!-- Sort cols have to be reversed in JIRA 4 -->
+                    <sortColumnNames>Key DESC,Type,Fix Version DESC</sortColumnNames>
+                    <resolutionIds>Fixed</resolutionIds>
+                    <statusIds>Resolved,Closed</statusIds>
+                    <!-- Don't include sub-task -->
+                    <typeIds>Bug,New Feature,Task,Improvement,Wish,Test</typeIds>
+                    <fixVersionIds>${commons.release.version}</fixVersionIds>
+                    <!-- The default is 100 -->
+                    <maxEntries>100</maxEntries>
+                </configuration>
+                <reportSets>
+                    <reportSet>
+                        <reports>
+                            <report>changes-report</report>
+                            <report>jira-report</report>
+                        </reports>
+                    </reportSet>
+                </reportSets>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>findbugs-maven-plugin</artifactId>
+                <version>2.5.5</version>
+                <configuration>
+                    <excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>clirr-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                      <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>examples.*</excludePackageNames>
+                </configuration>
+                <reportSets>
+                  <reportSet>
+                    <reports>
+                      <report>javadoc</report>
+                    </reports>
+                  </reportSet>
+                </reportSets>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.11</version>
+                <configuration>
+                    <configLocation>${basedir}/checkstyle.xml</configLocation>
+                    <suppressionsLocation>${basedir}/checkstyle-suppressions.xml</suppressionsLocation>
+                    <enableRulesSummary>false</enableRulesSummary>
+                </configuration>
+            </plugin>
+
+            <plugin>
+              <groupId>org.apache.rat</groupId>
+              <artifactId>apache-rat-plugin</artifactId>
+              <!-- Parent pom does not (yet) exclude these -->
+              <configuration>
+                <excludes>
+                  <exclude>.checkstyle</exclude>
+                  <exclude>.fbprefs</exclude>
+                </excludes>
+              </configuration>
+            </plugin>
+
+        </plugins>
+    </reporting>
+
+    <profiles>
+      <profile>
+        <!-- Temporary hack to suppress Javadoc 8 errors -->
+        <id>javadoc_8</id>
+        <activation>
+          <jdk>1.8</jdk>
+        </activation>
+        <properties>
+          <!-- Disable Xdoclint, until JavaDoc issues are fixed -->
+          <additionalparam>-Xdoclint:none</additionalparam>
+        </properties>
+      </profile>
+    </profiles>
+
+</project>
diff --git a/api/src/main/assembly/bin.xml b/api/src/main/assembly/bin.xml
new file mode 100644
index 0000000..3c114dd
--- /dev/null
+++ b/api/src/main/assembly/bin.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<assembly
+  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>bin</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>README*</include>
+                <include>LICENSE*</include>
+                <include>NOTICE*</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>commons-net-${project.version}.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/site/apidocs</directory>
+            <outputDirectory>apidocs</outputDirectory>
+            <includes>
+                <include>**/*</include>
+            </includes>
+        </fileSet>
+        <!-- Include sources jar for IDEs -->
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>commons-net-${project.version}-sources.jar</include>
+            </includes>
+        </fileSet>
+        <!-- Include examples as binary jar -->
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>commons-net-examples-${project.version}.jar</include>
+            </includes>
+        </fileSet>
+        <!-- Include example sources for developers -->
+        <fileSet>
+            <directory>src/main/java/examples</directory>
+            <outputDirectory>examples</outputDirectory>
+            <includes>
+                <include>**/*</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/api/src/main/assembly/src.xml b/api/src/main/assembly/src.xml
new file mode 100644
index 0000000..a5f8da1
--- /dev/null
+++ b/api/src/main/assembly/src.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<assembly
+  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+  <id>src</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <baseDirectory>${artifactId}-${version}-src</baseDirectory>
+  <fileSets>
+    <fileSet>
+      <includes>
+        <include>README*</include>
+        <include>LICENSE*</include>
+        <include>NOTICE*</include>
+        <include>RELEASE-NOTES.txt</include>
+        <include>pom.xml</include>
+        <include>findbugs-exclude-filter.xml</include>
+        <include>checkstyle*.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>src</directory>
+    </fileSet>
+  </fileSets>
+</assembly>
+
diff --git a/api/src/main/java/org/apache/commons/rdf/BlankNode.java b/api/src/main/java/org/apache/commons/rdf/BlankNode.java
new file mode 100644
index 0000000..2fcf23b
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/BlankNode.java
@@ -0,0 +1,41 @@
+/*
+ * 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.commons.rdf;
+
+/**
+ * A Blank Node represents a resource, 
+ * but does not indicate a URI for the resource. Blank nodes act like 
+ * existentially qualified variables in first order logic. 
+ *
+ * An <a href= "http://www.w3.org/TR/rdf11-concepts/#dfn-blank-node" >RDF-1.1
+ * Blank Node</a>, as defined by <a href=
+ * "http://www.w3.org/TR/rdf11-concepts/#section-blank-nodes" >RDF-1.1 Concepts
+ * and Abstract Syntax</a>, a W3C Recommendation published on 25 February 2014.<br>
+ *
+ * Note that: Blank nodes are disjoint from IRIs and literals. Otherwise,
+ * the set of possible blank nodes is arbitrary. RDF makes no reference to any
+ * internal structure of blank nodes.
+ *
+ *
+ * @see <a href= "http://www.w3.org/TR/rdf11-concepts/#dfn-blank-node">RDF-1.1
+ * Blank Node</a>
+ */
+public class BlankNode implements BlankNodeOrIri {
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/BlankNodeOrIri.java b/api/src/main/java/org/apache/commons/rdf/BlankNodeOrIri.java
new file mode 100644
index 0000000..0a292d8
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/BlankNodeOrIri.java
@@ -0,0 +1,30 @@
+/*
+ * 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.commons.rdf;
+
+/**
+ * Represents a <code>Resource</code> that is not a <code>Literal</code>. 
+ * This is a marker interface implemented by <code>UriRef</code> 
+ * and <code>BNode</code>.
+ *
+ * @author reto
+ */
+public interface BlankNodeOrIri extends RdfTerm {
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/Graph.java b/api/src/main/java/org/apache/commons/rdf/Graph.java
new file mode 100644
index 0000000..5a188ff
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/Graph.java
@@ -0,0 +1,88 @@
+/*
+ * 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.commons.rdf;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.commons.rdf.event.FilterTriple;
+import org.apache.commons.rdf.event.GraphListener;
+
+
+/**
+ * A set of triples (as it doesn't allow duplicates), it does however
+ * not extend {@link java.util.Set} as it doesn't inherit its
+ * specification for <code>hashCode()</code> and <code>equals</code>.
+ * It is possible to add <code>GraphListener</code> to listen for modifications
+ * in the triples.
+ *
+ * @author reto
+ */
+public interface Graph extends Collection<Triple> {
+    
+    /**
+     * Filters triples given a pattern. 
+     * filter(null, null, null) returns the same as iterator()
+     * 
+     * @param subject
+     * @param predicate
+     * @param object
+     * @return <code>Iterator</code>
+     */
+    public Iterator<Triple> filter(BlankNodeOrIri subject, Iri predicate, 
+            RdfTerm object);
+
+    /**
+     * Returns true if <code>other</code> describes the same graph and will 
+     * always describe the same graph as this instance, false otherwise. 
+     * It returns true if this == other or if it
+     * is otherwise guaranteed that changes to one of the instances are
+     * immediately reflected in the other or if both graphs are immutable.
+     *
+     * @param other
+     * @return true if other == this
+     */
+    @Override
+    public boolean equals(Object other);
+
+    /**
+     * Returns an ImutableGraph describing the graph at the current point in 
+     * time. if <code>this</code> is an instance of ImmutableGraph this can 
+     * safely return <code>this</code>.
+     *
+     * @return the current time slice of the possibly mutable graph represented by the instance.
+     */
+    public ImmutableGraph getImmutableGraph();
+    
+    /**
+     * The lock provided by this methods allows to create read- and write-locks
+     * that span multiple method calls. Having a read locks prevents other
+     * threads from writing to this Graph, having a write-lock prevents other
+     * threads from reading and writing. Implementations would typically
+     * return a <code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
+     * Immutable instances (such as instances of <code>ImmutableGraph</code>)
+     * or instances used in transaction where concurrent acces of the same 
+     * instance is not an issue may return a no-op ReadWriteLock (i.e. one
+     * which returned ReadLock and WriteLock instances of which the methods do 
+     * not do anything)
+     *
+     * @return the lock of this Graph
+     */
+    ReadWriteLock getLock();
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/ImmutableGraph.java b/api/src/main/java/org/apache/commons/rdf/ImmutableGraph.java
new file mode 100644
index 0000000..a3b0211
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/ImmutableGraph.java
@@ -0,0 +1,55 @@
+ /*
+ * 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.commons.rdf;
+
+/**
+ * A graph, modeled as a set of triples.
+ * This interface does not extend java.util.Set because of the different 
+ * identity constraints, i.e. two <code>Graph</code>s may be equal (isomorphic) 
+ * even if the set of triples are not.
+ * 
+ * Implementations MUST be immutable and throw respective exceptions, when 
+ * add/remove-methods are called.
+ * 
+ * @see org.apache.clerezza.rdf.core.impl.AbstractGraph
+ * @author reto
+ *
+ */
+public interface ImmutableGraph extends Graph {
+
+    /** 
+     * Returns true if two graphs are isomorphic
+     * 
+     * @return true if two graphs are isomorphic
+     */
+    @Override
+    public boolean equals(Object obj);
+
+    /** 
+     * Return the sum of the blank-nodes independent hashes of the triples. 
+     * More precisely the hash of the triple is calculated as follows:
+     * (hash(subject) >> 1) ^  hash(hashCode) ^ (hash(hashCode) << 1)
+     * Where the hash-fucntion return the hashCode of the argument 
+     * for grounded arguments and 0 otherwise. 
+     * 
+     * @return hash code
+     */
+    @Override
+    public int hashCode();
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/commons/rdf/Iri.java b/api/src/main/java/org/apache/commons/rdf/Iri.java
new file mode 100644
index 0000000..e1ef0f7
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/Iri.java
@@ -0,0 +1,83 @@
+/*
+ * 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.commons.rdf;
+
+import java.io.Serializable;
+
+/**
+ * Represents an RDF URI Reference
+ * 
+ * RDF URI References are defined in section 6.4 RDF URI References of
+ * http://www.w3.org/TR/2004/REC-rdf-concepts-20040210/#section-Graph-URIref
+ * 
+ * Note that an RDF URI Reference is not the same as defined by RFC3986, 
+ * RDF URI References support most unicode characters 
+ * 
+ * @author reto
+ */
+public class Iri implements BlankNodeOrIri, Serializable {
+
+    private String unicodeString;
+
+    public Iri(String unicodeString) {
+        this.unicodeString = unicodeString;
+    }
+
+    /** 
+     * @return the unicode string that produces the URI
+     */
+    public String getUnicodeString() {
+        return unicodeString;
+    }
+
+    /**
+     * Returns true iff <code>obj</code> == <code>UriRef</code>
+     * 
+     * @param obj
+     * @return true if obj is an instanceof UriRef with 
+     * the same unicode-string, false otherwise
+     */
+    @Override
+    public boolean equals(Object obj) {
+
+        if (!(obj instanceof Iri)) {
+            return false;
+        }
+
+        return unicodeString.equals(((Iri) obj).getUnicodeString());
+    }
+
+    /**
+     * @return 5 + the hashcode of the string
+     */
+    @Override
+    public int hashCode() {
+        int hash = 5 + unicodeString.hashCode();
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buffer = new StringBuilder();
+        buffer.append('<');
+        buffer.append(unicodeString);
+        buffer.append('>');
+        return buffer.toString();
+    }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/commons/rdf/Language.java b/api/src/main/java/org/apache/commons/rdf/Language.java
new file mode 100644
index 0000000..03f328c
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/Language.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.commons.rdf;
+
+/**
+ * Represents a language as expressed by the RDF 4646 language tag
+ *
+ * @author reto
+ */
+public class Language {
+
+    private String id;
+
+    /**
+     * Constructs the language tag defined by RDF 4646, normalized to lowercase.
+     *
+     * @param the id as defined by RDF 4646, normalized to lowercase.
+     */
+    public Language(String id) {
+        if ((id == null) || (id.equals(""))) {
+            throw new IllegalArgumentException("A language id may not be null or empty");
+        }
+        this.id = id;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (other instanceof Language) {
+            return id.equals(((Language) other).id);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return id;
+    }
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/Literal.java b/api/src/main/java/org/apache/commons/rdf/Literal.java
new file mode 100644
index 0000000..cf5e1ee
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/Literal.java
@@ -0,0 +1,93 @@
+/*
+ * 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.commons.rdf;
+
+
+/**
+ * Represents a literal value that can be a node in an RDF Graph. 
+ * Literals are used to identify values such as numbers and dates by 
+ * means of a lexical representation. There are two types of literals 
+ * represented by the subinterfaces {@link PlainLiteral} 
+ * and {@link TypedLiteral} 
+ *
+ * @author reto
+ */
+public interface Literal extends RdfTerm {
+    
+    /**
+     * The lexical form of this literal, represented by a <a
+     * href="http://www.unicode.org/versions/latest/">Unicode string</a>.
+     *
+     * @return The lexical form of this literal.
+     * @see <a
+     * href="http://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form">RDF-1.1
+     * Literal lexical form</a>
+     */
+    String getLexicalForm();
+
+    /**
+     * The IRI identifying the datatype that determines how the lexical form
+     * maps to a literal value.
+     *
+     * @return The datatype IRI for this literal.
+     * @see <a
+     * href="http://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri">RDF-1.1
+     * Literal datatype IRI</a>
+     */
+    Iri getDataType();
+    
+    /**
+     * If and only if the datatype IRI is <a
+     * href="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
+     * >http://www.w3.org/1999/02/22-rdf-syntax-ns#langString</a>, the language
+     * tag for this Literal is a language tag as defined by <a
+     * href="http://tools.ietf.org/html/bcp47">BCP47</a>.<br>
+     * If the datatype IRI is not <a
+     * href="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
+     * >http://www.w3.org/1999/02/22-rdf-syntax-ns#langString</a>, this method
+     * must null.
+     *
+     * @return The language tag of the literal or null if no language tag is defined
+     * @see <a
+     * href="http://www.w3.org/TR/rdf11-concepts/#dfn-language-tag">RDF-1.1
+     * Literal language tag</a>
+     */
+    public Language getLanguage();
+    
+    /** 
+     * Returns true if <code>obj</code> is an instance of 
+     * <code>literal</code> that is term-equal with this, false otherwise
+     * 
+     * Two literals are term-equal (the same RDF literal) if and only if the 
+     * two lexical forms, the two datatype IRIs, and the two language tags (if 
+     * any) compare equal, character by character.
+     * 
+     * @return true if obj equals this, false otherwise.
+     */
+    public boolean equals(Object obj);
+    
+    /**
+     * Returns the hash code of the lexical form plus the hash code of the 
+     * datatype plus if the literal has a language the hash code of the 
+     * language. 
+     * 
+     * @return hash code
+     */
+    public int hashCode();
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/RdfTerm.java b/api/src/main/java/org/apache/commons/rdf/RdfTerm.java
new file mode 100644
index 0000000..8f0fb40
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/RdfTerm.java
@@ -0,0 +1,32 @@
+/*
+ * 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.commons.rdf;
+
+/**
+ * An <a href= "http://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term" >RDF-1.1
+ * Term</a>, as defined by <a href= "http://www.w3.org/TR/rdf11-concepts/"
+ * >RDF-1.1 Concepts and Abstract Syntax</a>, a W3C Recommendation published on
+ * 25 February 2014.<br>
+ *
+ * @see <a href= "http://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term" >RDF-1.1
+ * Term</a>
+ */
+public interface RdfTerm {
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/Triple.java b/api/src/main/java/org/apache/commons/rdf/Triple.java
new file mode 100644
index 0000000..2a1569e
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/Triple.java
@@ -0,0 +1,57 @@
+/*
+ * 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.commons.rdf;
+
+/**
+ * A structure containing a subject, a predicate, and an object. 
+ * Also known as a statement.
+ *
+ * @author reto
+ */
+public interface Triple {
+
+    BlankNodeOrIri getSubject();
+
+    Iri getPredicate();
+
+    RdfTerm getObject();
+
+    /**
+     * 
+     * @param obj
+     * @return true iff subject, predicate, and object of both triples are equal
+     */
+    @Override
+    boolean equals(Object obj);
+
+    /**
+     * The hash code is computed as follow
+     * (subject.hashCode() >> 1) ^  predicate.hashCode() ^ object.hashCode() << 1)
+     * 
+     * Note that the hash returned is computed including the hash of BNodes, so 
+     * it is not blank-node blind as in Graph.
+     * 
+     * This would have to change if triple should extend Graph
+     * 
+     * @return hash code
+     */
+    @Override
+    int hashCode();
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/WatchableGraph.java b/api/src/main/java/org/apache/commons/rdf/WatchableGraph.java
new file mode 100644
index 0000000..6367333
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/WatchableGraph.java
@@ -0,0 +1,94 @@
+/*
+ * 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.commons.rdf;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.commons.rdf.event.FilterTriple;
+import org.apache.commons.rdf.event.GraphListener;
+
+
+/**
+ * An extension to the Graph interface that allows to add throws events
+ * on modifications.
+ *
+ * @author reto
+ */
+public interface WatchableGraph extends Graph {
+   
+
+    /**
+     * Adds the specified <code>GraphListener</code> to the graph. This listener
+     * will be notified, when the graph is modified and the <code>Triple</code>
+     * that was part of the modifiaction matched the specified
+     * <code>FilterTriple</code>. The notification will be passed to the
+     * listener after the specified delay time (in milli-seconds) has passed.
+     * If more matching events occur during the delay period, then they are
+     * passed all together at the end of the delay period. If the the listener
+     * unregisters or the platform is stopped within the period then the already
+     * occurred events may not be delivered.
+     *
+     * All implementations support this method, immutable implementations will
+     * typically provide an empty implementation, they shall not throw an
+     * exception.
+     *
+     * Implementation of which the triples change over time without add- and
+     * remove-methods being called (e.g. implementation dynamically generating
+     * their triples on invocation of the filer-method) may choose not to, or
+     * only partially propagate their changes to the listener. They should
+     * describe the behavior in the documentation of the class.
+     *
+     * Implementations should keep weak references the listeners, so that the
+     * listener can be garbage collected if its no longer referenced by another
+     * object.
+     *
+     * If delay is 0 notification will happen synchroneously.
+     *
+     * @param listener The listener that will be notified
+     * @param filter The triple filter with which triples are tested,
+     *        that were part of the modification.
+     * @param delay The time period afer which the listener will be notified in milliseconds.
+     */
+    public void addGraphListener(GraphListener listener, FilterTriple filter,
+            long delay);
+
+    /**
+     * Adds the specified <code>GraphListener</code> to the graph. This listener
+     * will be notified, when the graph is modified and the <code>Triple</code>
+     * that was part of the modifiaction matched the specified
+     * <code>FilterTriple</code>. The notification will be passed without delay.
+     *
+     * Same as <code>addGraphListener(listener, filter, 0).
+     *
+     * @param listener The listener that will be notified
+     * @param filter The triple filter with which triples are tested,
+     *        that were part of the modification.
+     */
+    public void addGraphListener(GraphListener listener, FilterTriple filter);
+
+    /**
+     * Removes the specified <code>GraphListener</code> from the graph. This
+     * listener will no longer be notified, when the graph is modified.
+     *
+     * @param listener The listener to be removed.
+     */
+    public void removeGraphListener(GraphListener listener);
+  
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/event/AddEvent.java b/api/src/main/java/org/apache/commons/rdf/event/AddEvent.java
new file mode 100644
index 0000000..1d4a835
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/event/AddEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.commons.rdf.event;
+
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Graph;
+
+/**
+ * This class represent a addition event that occured on a
+ * <code>TripleCollection</code>.
+ *
+ * @author rbn
+ */
+public class AddEvent extends GraphEvent {
+
+
+    public AddEvent(Graph graph,  Triple triple) {
+        super(graph, triple);
+    }
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/event/FilterTriple.java b/api/src/main/java/org/apache/commons/rdf/event/FilterTriple.java
new file mode 100644
index 0000000..3480c13
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/event/FilterTriple.java
@@ -0,0 +1,86 @@
+/*
+ * 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.commons.rdf.event;
+
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Iri;
+
+/**
+ * The <code>FilterTriple</code> class provides a match()-method that tests
+ * if a <code>Triple</code> match a certain triple pattern.
+ *
+ * @author mir
+ */
+public class FilterTriple {
+
+    private BlankNodeOrIri subject;
+    private Iri predicate;
+    private RdfTerm object;
+    
+    /**
+     * Creates a new <code>FilterTriple</code>. The specified subject,
+     * predicate and object are used to test a given <code>Triple</code>. Any
+     * of these values can be null, which acts as wildcard in the test.
+     *
+     * @param subject  the subject.
+     * @param predicate  the predicate.
+     * @param object  the object.
+     */
+    public FilterTriple (BlankNodeOrIri subject, Iri predicate, RdfTerm object) {
+        this.subject = subject;
+        this.predicate = predicate;
+        this.object = object;
+    }
+
+    /**
+     * Returns true if the subject, predicate and object of the specified
+     * <code>Triple</code> match the subject, predicate and object of this
+     * <code>FilterTriple</code>. Null values in the <code>FilterTriple</code>
+     * act as wildcards.
+     * @param triple
+     * @return
+     */
+    public boolean match(Triple triple) {
+        boolean subjectMatch, predicateMatch, objectMatch;
+        if (this.subject == null) {
+            subjectMatch = true;            
+        } else {
+            subjectMatch = this.subject.equals(triple.getSubject());
+        }
+        if (this.predicate == null) {
+            predicateMatch = true;
+        } else {
+            predicateMatch = this.predicate.equals(triple.getPredicate());
+        }
+        if (this.object == null) {
+            objectMatch = true;
+        } else {
+            objectMatch = this.object.equals(triple.getObject());
+        }
+        return subjectMatch && predicateMatch && objectMatch;
+    }
+
+    @Override
+    public String toString() {
+        return "FilterTriples: "+subject+" "+predicate+" "+object;
+    }
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/event/GraphEvent.java b/api/src/main/java/org/apache/commons/rdf/event/GraphEvent.java
new file mode 100644
index 0000000..d055088
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/event/GraphEvent.java
@@ -0,0 +1,59 @@
+/*
+ * 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.commons.rdf.event;
+
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Graph;
+
+/**
+ * This class represent a modification event that occured on a
+ * <code>TripleCollection</code>. A <code>GraphEvent</code> object keeps
+ * information about this event. These information are: The <code>Triple</code>
+ * that was part of the modification, the type of modification (addition or
+ * removal) and the <code>TripleCollection</code> that was modified.
+ *
+ * @author mir
+ */
+public class GraphEvent {
+
+    private Graph graph;
+    private Triple triple;
+
+    protected GraphEvent(Graph graph, Triple triple) {
+        this.graph = graph;
+        this.triple = triple;
+    }
+
+    /**
+     * Returns the <code>TripleCollection</code> that was modified in the event.
+     * @return the graph
+     */
+    public Graph getGraph() {
+        return graph;
+    }
+
+
+    /**
+     * Return the <code>Triple</code> that was part of the modification.
+     * @return the triple
+     */
+    public Triple getTriple() {
+        return triple;
+    }
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/event/GraphListener.java b/api/src/main/java/org/apache/commons/rdf/event/GraphListener.java
new file mode 100644
index 0000000..8d0b257
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/event/GraphListener.java
@@ -0,0 +1,43 @@
+/*
+ * 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.commons.rdf.event;
+
+import java.util.List;
+
+/**
+ * A class that is interested in graph events implements this interface and
+ * is then added as listener to a <code>ListenableTripleCollection</code> or
+ * one of its subclasses. When the <code>ListenableTripleCollection</code> is
+ * modified, then the <code>GraphListener</code> is notified.
+ *
+ * @author mir
+ */
+public interface GraphListener {
+
+    /**
+     * This method is called when a <code>ListenableTripleCollection</code> was
+     * modified, to which this <code>GraphListener</code> was added. A
+     * <code>List</code> containing <code>GraphEvent</code>s are passed as
+     * argument. The list contains all events in which a triple was part of
+     * the modification that matched the <code>FilterTriple</code> which was passed
+     * as argument when the listener was added.
+     * @param events
+     */
+    public void graphChanged(List<GraphEvent> events);
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/event/RemoveEvent.java b/api/src/main/java/org/apache/commons/rdf/event/RemoveEvent.java
new file mode 100644
index 0000000..60150d6
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/event/RemoveEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.commons.rdf.event;
+
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Graph;
+
+/**
+ * This class represent a removal event that occured on a
+ * <code>TripleCollection</code>.
+ *
+ * @author rbn
+ */
+public class RemoveEvent extends GraphEvent {
+
+
+    public RemoveEvent(Graph graph,  Triple triple) {
+        super(graph, triple);
+    }
+
+}
diff --git a/api/src/main/java/org/apache/commons/rdf/package-info.java b/api/src/main/java/org/apache/commons/rdf/package-info.java
new file mode 100644
index 0000000..da34f2d
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Common RDF API
+ */
+package org.apache.commons.rdf;
\ No newline at end of file
diff --git a/api/src/site/custom/project-info-report.properties b/api/src/site/custom/project-info-report.properties
new file mode 100644
index 0000000..ec62c64
--- /dev/null
+++ b/api/src/site/custom/project-info-report.properties
@@ -0,0 +1,24 @@
+#
+#  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.
+#
+
+# Replace SCM report description in index page
+report.scm.description=This document lists ways to access the online source repository.
+
+# Replace SCM report text for viewvc section
+report.scm.webaccess.title=Browser (HTTP) Access
+report.scm.webaccess.url=The following is a link to a browsable version of the source repository. \
+Please use the "Anonymous Access" or "Developer Access" URL if you want to check out the source using your SCM client.
\ No newline at end of file
diff --git a/api/src/site/resources/download_net.cgi b/api/src/site/resources/download_net.cgi
new file mode 100644
index 0000000..495cde1
--- /dev/null
+++ b/api/src/site/resources/download_net.cgi
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Just call the standard mirrors.cgi script. It will use download.html
+# as the input template.
+exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $*
\ No newline at end of file
diff --git a/api/src/site/site.xml b/api/src/site/site.xml
new file mode 100644
index 0000000..6a45085
--- /dev/null
+++ b/api/src/site/site.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+   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.
+-->
+<project name="Apache Commons Net">
+
+  <bannerRight>
+    <name>Apache Commons Net</name>
+    <src>/images/net-logo-white.png</src>
+    <href>/index.html</href>
+    <alt>Commons Net&amp;trade; logo</alt>
+  </bannerRight>
+
+  <body>
+    <menu name="Documentation">
+      <item name="Overview"                    href="index.html"/>     
+    </menu>
+    <menu name="Development">
+      <item name="Coding Specifications"       href="code-standards.html"/>
+      <item name="SVN repository"              href="source-repository.html"/>
+    </menu>
+
+  </body>
+
+</project>
diff --git a/api/src/site/xdoc/code-standards.xml b/api/src/site/xdoc/code-standards.xml
new file mode 100644
index 0000000..6cc29a3
--- /dev/null
+++ b/api/src/site/xdoc/code-standards.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+
+<document>
+
+ <properties>
+  <title>Coding Standards</title>
+  <author email="jon@latchkey.com">Jon S. Stevens</author>
+  <author email="jvanzyl@apache.org">Jason van Zyl</author>
+ </properties>
+
+<body>
+
+<section name="Coding Standards">
+
+<p>
+This document describes a list of coding conventions that are required
+for code submissions to the project. By default, the coding conventions
+for most Open Source Projects should follow the existing coding conventions
+in the code that you are working on. For example, if the bracket is on
+the same line as the if statement, then you should write all your code
+to have that convention.
+</p>
+
+<p>
+<strong>If you commit code that does not follow these conventions, you
+are responsible for also fixing your own code.</strong>
+</p>
+
+<p>
+Below is a list of coding conventions that are specific to Apache Commons Net
+everything else not specificially mentioned here should follow the official
+<a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">Sun
+Java Coding Conventions</a>.
+</p>
+
+<p>
+1. Brackets should begin and end on a new line and should exist even
+for one line statements. Examples:
+</p>
+
+<source test=""><![CDATA[
+if ( foo )
+{
+    // code here
+}
+
+try
+{
+    // code here
+}
+catch (Exception bar)
+{
+    // code here
+}
+finally
+{
+    // code here
+}
+
+while ( true )
+{
+    // code here
+}
+]]></source>
+
+<p>
+2. Though it's considered okay to include spaces inside parens, the
+preference is to not include them. Both of the following are okay:
+</p>
+
+<source test=""><![CDATA[
+if (foo)
+
+or
+
+if ( foo )
+]]></source>
+
+<p>
+3. 4 space indent. <strong>NO tabs</strong>. Period. We understand
+that many developers like to use tabs, but the fact of the matter is
+that in a distributed development environment where diffs are sent to
+the mailing lists by both developers and the version control system
+(which sends commit log messages), the use tabs makes it impossible to
+preserve legibility.
+</p>
+
+<p>
+In Emacs-speak, this translates to the following command:
+</p>
+
+<source><![CDATA[
+(setq-default tab-width 4 indent-tabs-mode nil)
+]]></source>
+
+<p>
+4. Native linefeeds (svn:eol-style native) for all .java source code and text files.
+Platform specific files should have the platform specific linefeeds.
+</p>
+
+<p>
+5. JavaDoc <strong>MUST</strong> exist on all public and protected methods.
+JavaDoc on private and default access methods and members is preferred and
+encouraged.  If your code modifications use an existing class/method/variable
+which lacks JavaDoc, it is required that you add it.  This will improve the
+project as a whole.
+</p>
+
+<p>
+6. The Apache License header <strong>MUST</strong> be placed at the top
+of each and every file.
+</p>
+
+<p>
+9. Import statements must be fully qualified for clarity.
+</p>
+
+<source><![CDATA[
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import org.apache.foo.Bar;
+import org.apache.bar.Foo;
+]]></source>
+
+<p>
+And not
+</p>
+
+<source><![CDATA[
+import java.util.*;
+import org.apache.foo.*;
+import org.apache.bar.*;
+]]></source>
+
+<hr noshade="true" size="1"/>
+
+<p>
+X/Emacs users might appreciate this in their .emacs file.
+</p>
+
+<source><![CDATA[
+(defun apache-jakarta-mode ()
+  "The Java mode specialization for Apache Jakarta projects."
+  (if (not (assoc "apache-jakarta" c-style-alist))
+      ;; Define the Apache Jakarta cc-mode style.
+      (c-add-style "apache-jakarta" '("java" (indent-tabs-mode . nil))))
+
+  (c-set-style "apache-jakarta")
+  (c-set-offset 'substatement-open 0 nil)
+  (setq mode-name "Apache Jakarta")
+
+  ;; Turn on syntax highlighting when X is running.
+  (if (boundp 'window-system)
+      (progn (setq font-lock-support-mode 'lazy-lock-mode)
+             (font-lock-mode t))))
+
+;; Activate Jakarta mode.
+(if (fboundp 'jde-mode)
+    (add-hook 'jde-mode-hook 'apache-jakarta-mode)
+  (add-hook 'java-mode-hook 'apache-jakarta-mode))
+]]></source>
+
+<p>
+Thanks for your cooperation.
+</p>
+
+</section>
+
+</body>
+</document>
diff --git a/api/src/site/xdoc/index.xml b/api/src/site/xdoc/index.xml
new file mode 100644
index 0000000..7a7a1ec
--- /dev/null
+++ b/api/src/site/xdoc/index.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+   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.
+-->
+<document>
+
+    <properties>
+        <title>Overview</title>
+        <author email="dev@commons.apache.org">Apache Commons Documentation Team</author>
+    </properties>
+
+    <body>
+
+        <section name="Apache Commons RDF">
+            <p>
+                Apache Commons RDF provides an API modelling the RDF data model as defined by 
+                http://www.w3.org/TR/rdf11-concepts/
+            </p>
+        </section>
+        <section name="Features">
+            <p>
+                This Library shall
+                <ul>
+                    <li>Allow to access, modify nad monitor RDF data</li>
+                    <li>Support all concepts defined by the RDF Abstract Syntax</li>
+                    <li>Provide an easy to use API</li>
+                    <li>Support both triple stores as well as the wrapping other sources</li>
+                    <li>Allow to seamlessly use instances coming from different sources</li>
+                    <li>Integrate well with existing Java APIs</li>
+                </ul>
+            </p>
+        </section>
+
+</document>
+
diff --git a/doap_rdf.rdf b/doap_rdf.rdf
new file mode 100644
index 0000000..a7a5e17
--- /dev/null
+++ b/doap_rdf.rdf
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:asfext="http://projects.apache.org/ns/asfext#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:doap="http://usefulinc.com/ns/doap#" xml:lang="en">
+  <Project rdf:about="http://commons.apache.org/rdf/">
+    <name>Apache Commons RDF</name>
+    <homepage rdf:resource="http://commons.apache.org/rdf/"/>
+    <programming-language>Java</programming-language>
+    <category rdf:resource="http://projects.apache.org/category/library"/>
+    <license rdf:resource="http://usefulinc.com/doap/licenses/asl20"/>
+    <bug-database rdf:resource="https://issues.apache.org/jira/browse/RDF"/>
+    <download-page rdf:resource="http://commons.apache.org/rdf/download_net.cgi"/>
+    <asfext:pmc rdf:resource="http://commons.apache.org/"/>
+    <shortdesc xml:lang="en">Apache Commons Rdf</shortdesc>
+    <description xml:lang="en"/>
+    <repository>
+      <SVNRepository>
+        <browse rdf:resource="http://svn.apache.org/repos/asf/commons/proper/rdf/trunk"/>
+        <location rdf:resource="http://svn.apache.org/repos/asf/commons/proper/rdf"/>
+      </SVNRepository>
+    </repository>
+    <release>
+    </release>
+    <mailing-list rdf:resource="http://commons.apache.org/mail-lists.html"/>
+  </Project>
+</rdf:RDF>
diff --git a/impl.sparql/pom.xml b/impl.sparql/pom.xml
new file mode 100644
index 0000000..8fe7681
--- /dev/null
+++ b/impl.sparql/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-parent</artifactId>
+        <version>37</version>
+        <relativePath />
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>commons-rdf</groupId>
+    <artifactId>commons-rdf-impl-sparql</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+    <name>Apache Commons RDF SPARQL backed implementation.</name>
+    <description>An implementation of the rdf commons API backed by a sparql 
+        endpoint. STATUS: Incomplete, currecnt code only supports reading 
+        graphs and does not yet support BlankNodes.</description>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <commons.encoding>UTF-8</commons.encoding>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-rdf</groupId>
+            <artifactId>commons-rdf-api</artifactId>
+            <version>0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-rdf</groupId>
+            <artifactId>commons-rdf-impl-utils</artifactId>
+            <version>0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jena</groupId>
+            <artifactId>jena-fuseki</artifactId>
+            <version>1.1.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java
new file mode 100644
index 0000000..c74aa06
--- /dev/null
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java
@@ -0,0 +1,74 @@
+/*
+ * 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.commons.rdf.impl.sparql;
+
+import java.util.Collection;
+import java.util.Objects;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
+
+/**
+ *
+ * @author developer
+ */
+class SparqlBNode extends BlankNode {
+    
+    private final static Iri internalBNodeId = new Iri("urn:x-internalid:fdmpoihdfw");
+    
+    final ImmutableGraph context;
+    private final int isoDistinguisher;
+
+    SparqlBNode(BlankNode node, Collection<Triple> context, int isoDistinguisher) {
+        this.isoDistinguisher = isoDistinguisher;
+        final SimpleGraph contextBuider = new SimpleGraph();
+        for (Triple triple : context) {
+            BlankNodeOrIri subject = triple.getSubject();
+            RdfTerm object = triple.getObject();
+            contextBuider.add(new TripleImpl(subject.equals(node) ? internalBNodeId : subject, 
+                    triple.getPredicate(), 
+                    object.equals(node) ? internalBNodeId : object));
+        }
+        this.context = contextBuider.getImmutableGraph();
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7+isoDistinguisher;
+        hash = 61 * hash + Objects.hashCode(this.context);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final SparqlBNode other = (SparqlBNode) obj;
+        if (isoDistinguisher != other.isoDistinguisher) {
+            return false;
+        }
+        return Objects.equals(this.context, other.context);
+    }
+}
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java
new file mode 100644
index 0000000..ca3f619
--- /dev/null
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java
@@ -0,0 +1,222 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.apache.commons.rdf.impl.sparql;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import javax.xml.parsers.*;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.AbstractLiteral;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+/**
+ *
+ * @author developer
+ */
+public class SparqlClient {
+
+    final String endpoint;
+
+    public SparqlClient(final String endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    List<Map<String, RdfTerm>> queryResultSet(final String query) throws IOException {
+        CloseableHttpClient httpclient = HttpClients.createDefault();
+        HttpPost httpPost = new HttpPost(endpoint);
+        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+        nvps.add(new BasicNameValuePair("query", query));
+        httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+        CloseableHttpResponse response2 = httpclient.execute(httpPost);
+
+        try {
+            HttpEntity entity2 = response2.getEntity();
+            InputStream in = entity2.getContent();
+            SAXParserFactory spf = SAXParserFactory.newInstance();
+            spf.setNamespaceAware(true);
+            SAXParser saxParser = spf.newSAXParser();
+            XMLReader xmlReader = saxParser.getXMLReader();
+            final SparqlsResultsHandler sparqlsResultsHandler = new SparqlsResultsHandler();
+            xmlReader.setContentHandler(sparqlsResultsHandler);
+            xmlReader.parse(new InputSource(in));
+            /*
+             for (int ch = in.read(); ch != -1; ch = in.read()) {
+             System.out.print((char)ch);
+             }
+             */
+            // do something useful with the response body
+            // and ensure it is fully consumed
+            EntityUtils.consume(entity2);
+            return sparqlsResultsHandler.getResults();
+        } catch (ParserConfigurationException ex) {
+            throw new RuntimeException(ex);
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex);
+        } finally {
+            response2.close();
+        }
+
+    }
+
+    final public static class SparqlsResultsHandler extends DefaultHandler {
+
+        private String currentBindingName;
+        private Map<String, RdfTerm> currentResult = null;
+        private final List<Map<String, RdfTerm>> results = new ArrayList<>();
+        private boolean readingValue;
+        private String lang; //the xml:lang attribute of a literal
+        private String value;
+        private Map<String, BlankNode> bNodeMap = new HashMap<>();
+        private static final Iri XSD_STRING = new Iri("http://www.w3.org/2001/XMLSchema#string");
+
+        private RdfTerm getBNode(String value) {
+            if (!bNodeMap.containsKey(value)) {
+                bNodeMap.put(value, new BlankNode());
+            }
+            return bNodeMap.get(value);
+        }
+
+        private List<Map<String, RdfTerm>> getResults() {
+            return results;
+        }
+
+        enum BindingType {
+
+            uri, bnode, literal;
+        }
+
+        @Override
+        public void startDocument() throws SAXException {
+
+        }
+
+        @Override
+        public void startElement(String namespaceURI,
+                String localName,
+                String qName,
+                Attributes atts)
+                throws SAXException {
+            if ("http://www.w3.org/2005/sparql-results#".equals(namespaceURI)) {
+                if ("result".equals(localName)) {
+                    if (currentResult != null) {
+                        throw new SAXException("unexpected tag <result>");
+                    }
+                    currentResult = new HashMap<>();
+                } else if ("binding".equals(localName)) {
+                    if (currentResult == null) {
+                        throw new SAXException("unexpected tag <binding>");
+                    }
+                    currentBindingName = atts.getValue("name");
+                } else if ("uri".equals(localName) || "bnode".equals(localName) || "literal".equals(localName)) {
+                    if (readingValue) {
+                        throw new SAXException("unexpected tag <" + localName + ">");
+                    }
+                    lang = atts.getValue("http://www.w3.org/XML/1998/namespace", "lang");
+                    readingValue = true;
+                }
+            }
+
+            //System.out.println(namespaceURI);
+            //System.out.println(qName);
+        }
+
+        @Override
+        public void characters(char[] chars, int start, int length) throws SAXException {
+            if (readingValue) {
+                value = new String(chars, start, length);
+                //System.err.println(value + start + ", " + length);
+            }
+        }
+
+        @Override
+        public void endElement(String namespaceURI,
+                String localName,
+                String qName)
+                throws SAXException {
+            if ("http://www.w3.org/2005/sparql-results#".equals(namespaceURI)) {
+                if ("result".equals(localName)) {
+                    results.add(currentResult);
+                    currentResult = null;
+                } else if ("binding".equals(localName)) {
+                    if (currentBindingName == null) {
+                        throw new SAXException("unexpected tag </binding>");
+                    }
+                    currentBindingName = null;
+                } else {
+                    try {
+                        BindingType b = BindingType.valueOf(localName);
+                        RdfTerm rdfTerm = null;
+                        final Language language = lang == null? null : new Language(lang);;
+                        switch (b) {
+                            case uri:
+                                rdfTerm = new Iri(value);
+                                break;
+                            case bnode:
+                                rdfTerm = getBNode(value);
+                                break;
+                            case literal:
+                                final String lf = value;
+                                rdfTerm = new AbstractLiteral() {
+
+                                    @Override
+                                    public String getLexicalForm() {
+                                        return lf;
+                                    }
+
+                                    @Override
+                                    public Iri getDataType() {
+                                        //TODO implement
+                                        return XSD_STRING;
+                                    }
+
+                                    @Override
+                                    public Language getLanguage() {
+                                        return language;
+                                    }
+                                };
+                                break;
+                        }
+                        currentResult.put(currentBindingName, rdfTerm);
+                        readingValue = false;
+                    } catch (IllegalArgumentException e) {
+                            //not uri|bnode|literal
+                    }
+                }
+            }
+        }
+
+        public void endDocument() throws SAXException {
+            //System.out.println("results: " + results.size());
+        }
+
+    }
+
+}
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
new file mode 100644
index 0000000..64b6133
--- /dev/null
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
@@ -0,0 +1,439 @@
+/*
+ * 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.commons.rdf.impl.sparql;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Literal;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.AbstractGraph;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+
+/**
+ *
+ * @author reto
+ */
+public class SparqlGraph extends AbstractGraph {
+
+    private static final int MAX_ISOMORPHIC_BNODES = 1000;
+    private static final Logger log = Logger.getLogger(SparqlGraph.class.getName());
+
+    final SparqlClient sparqlClient;
+
+    /**
+     * Constructs a Graph representing the default graph at the specified
+     * endpoint
+     */
+    public SparqlGraph(final String endpoint) {
+        sparqlClient = new SparqlClient(endpoint);
+    }
+
+    @Override
+    protected Iterator<Triple> performFilter(final BlankNodeOrIri filterSubject,
+            final Iri filterPredicate, final RdfTerm filterObject) {
+        try {
+            final StringBuilder queryBuilder = new StringBuilder();
+            queryBuilder.append("SELECT ?s ?p ?o WHERE { ");
+            if (filterSubject == null) {
+                queryBuilder.append("?s");
+            } else {
+                queryBuilder.append(asSparqlTerm(filterSubject));
+            }
+            queryBuilder.append(' ');
+            if (filterPredicate == null) {
+                queryBuilder.append("?p");
+            } else {
+                queryBuilder.append(asSparqlTerm(filterPredicate));
+            }
+            queryBuilder.append(' ');
+            if (filterObject == null) {
+                queryBuilder.append("?o");
+            } else {
+                queryBuilder.append(asSparqlTerm(filterObject));
+            }
+            queryBuilder.append(" }");
+            final List<Map<String, RdfTerm>> sparqlResults = sparqlClient.queryResultSet(queryBuilder.toString());
+            //first to triples without bnode-conversion
+            //rawTripkles contains the triples with the BNodes from the result set
+            final Collection<Triple> rawTriples = new ArrayList<>();
+            for (Map<String, RdfTerm> result : sparqlResults) {
+                rawTriples.add(new TripleImpl(filterSubject != null ? filterSubject : (BlankNodeOrIri) result.get("s"),
+                        filterPredicate != null ? filterPredicate : (Iri) result.get("p"),
+                        filterObject != null ? filterObject : result.get("o")));
+
+            }
+            //then bnode conversion
+            final Iterator<Triple> rawTriplesIter = rawTriples.iterator();
+            //this is basically just wokring around the lack of (named) nested functions
+            return (new Callable<Iterator<Triple>>() {
+
+                final Map<BlankNode, SparqlBNode> nodeMap = new HashMap<>();
+
+                private RdfTerm useSparqlNode(RdfTerm node) throws IOException {
+                    if (node instanceof BlankNodeOrIri) {
+                        return useSparqlNode((BlankNodeOrIri) node);
+                    }
+                    return node;
+                }
+
+                private BlankNodeOrIri useSparqlNode(BlankNodeOrIri node) throws IOException {
+                    if (node instanceof BlankNode) {
+                        if (!nodeMap.containsKey(node)) {
+                            createBlankNodesForcontext((BlankNode) node);
+                        }
+                        if (!nodeMap.containsKey(node)) {
+                            throw new RuntimeException("no Bnode created");
+                        }
+                        return nodeMap.get(node);
+                    } else {
+                        return node;
+                    }
+                }
+
+                private void createBlankNodesForcontext(final BlankNode node) throws IOException {
+                    final Collection<Triple> context = getContext(node);
+                    final Set<BlankNode> rawNodes = new HashSet<>();
+                    for (Triple triple : context) {
+                        {
+                            final BlankNodeOrIri subject = triple.getSubject();
+                            if (subject instanceof BlankNode) {
+                                rawNodes.add((BlankNode) subject);
+                            }
+                        }
+                        {
+                            final RdfTerm object = triple.getObject();
+                            if (object instanceof BlankNode) {
+                                rawNodes.add((BlankNode) object);
+                            }
+                        }
+                    }
+                    final Set<SparqlBNode> createdSparqlNodes = new HashSet<>();
+                    //final Map<BlankNode, SparqlBNode> preliminaryNodes = new HashMap<>();
+                    for (BlankNode rawNode : rawNodes) {
+                        for (int i = 0; i < MAX_ISOMORPHIC_BNODES; i++) {
+                            SparqlBNode sparqlBNode = new SparqlBNode(rawNode, context, i);
+                            if (!createdSparqlNodes.contains(sparqlBNode)) {
+                                nodeMap.put(rawNode, sparqlBNode);
+                                createdSparqlNodes.add(sparqlBNode);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                private Collection<Triple> getContext(final BlankNode node) throws IOException {
+                    //we need to get the cntext of the BNode
+                    //if the filter was for (null, null, null) we have the whole
+                    //bnode context in the reuslt set, otherwise we need to get 
+                    //more triples from the endpoint,
+                    //let's first handle the easy case
+                    if ((filterSubject == null) && (filterPredicate == null)
+                            && (filterObject == null)) {
+                        return getContextInRaw(node);
+                    } else {
+                        final Collection<Triple> startContext = getContextInRaw(node);
+                        final Set<Collection<Triple>> expandedContexts = expandContext(startContext);
+                        //expand bnode context
+                        //note that there might be different contexts for 
+                        //a bnode as present in the current result set
+                        //in this case we just haveto make sure we don't 
+                        //pick the same context for different bnodes in the resultset
+
+                        //TODO make sure we don't take one that has already been used
+                        return expandedContexts.iterator().next();
+                    }
+
+                }
+
+                private Collection<Triple> getContextInRaw(BlankNode node) {
+                    final Collection<Triple> context = new ArrayList<>();
+                    for (Triple rawTriple : rawTriples) {
+                        BlankNodeOrIri rawSubject = rawTriple.getSubject();
+                        RdfTerm rawObject = rawTriple.getObject();
+                        if (rawSubject.equals(node) || rawObject.equals(node)) {
+                            context.add(rawTriple);
+                        }
+                    }
+                    return context;
+                }
+
+                @Override
+                public Iterator<Triple> call() throws Exception {
+                    return new Iterator<Triple>() {
+
+                        @Override
+                        public boolean hasNext() {
+                            return rawTriplesIter.hasNext();
+                        }
+
+                        @Override
+                        public Triple next() {
+                            try {
+                                Triple rawTriple = rawTriplesIter.next();
+                                return new TripleImpl(useSparqlNode(rawTriple.getSubject()),
+                                        rawTriple.getPredicate(),
+                                        useSparqlNode(rawTriple.getObject()));
+                            } catch (IOException ex) {
+                                throw new RuntimeException(ex);
+                            }
+                        }
+                    };
+                }
+
+                /**
+                 * returns all MSGs that are supergraphs of startContext
+                 *
+                 * @param startContext
+                 * @return
+                 */
+                private Set<Collection<Triple>> expandContext(Collection<Triple> startContext) throws IOException {
+                    final Collection<String> triplePatterns = new ArrayList<>();
+                    int varCounter = 0;
+                    final Map<BlankNode, String> bNodeVarNameMap = new HashMap<>();
+                    for (Triple t : startContext) {
+                        final StringBuilder builder = new StringBuilder();
+                        {
+                            final BlankNodeOrIri s = t.getSubject();
+                            String varName;
+                            if (s instanceof BlankNode) {
+                                if (bNodeVarNameMap.containsKey(s)) {
+                                    varName = bNodeVarNameMap.get(s);
+                                } else {
+                                    varName = "v" + (varCounter++);
+                                    bNodeVarNameMap.put((BlankNode) s, varName);
+                                    
+                                }
+                                builder.append('?');
+                                builder.append(varName);
+                            } else {
+                                builder.append(asSparqlTerm(s));
+                            }
+                        }
+                        builder.append(' ');
+                        builder.append(asSparqlTerm(t.getPredicate()));
+                        builder.append(' ');
+                        {
+                            final RdfTerm o = t.getObject();
+                            String varName;
+                            if (o instanceof BlankNode) {
+                                if (bNodeVarNameMap.containsKey(o)) {
+                                    varName = bNodeVarNameMap.get(o);
+                                } else {
+                                    varName = "v" + (varCounter++);
+                                    bNodeVarNameMap.put((BlankNode) o, varName);
+                                }
+                                builder.append('?');
+                                builder.append(varName);
+                            } else {
+                                builder.append(asSparqlTerm(o));
+                            }
+                        }
+                        builder.append('.');
+                        triplePatterns.add(builder.toString());
+
+                    }
+                    final StringBuilder queryBuilder = new StringBuilder();
+                    queryBuilder.append("SELECT * WHERE {\n ");
+                    for (String triplePattern : triplePatterns) {
+                        queryBuilder.append(triplePattern);
+                        queryBuilder.append('\n');
+                    }
+                    Set<BlankNode> bNodesInContext = bNodeVarNameMap.keySet();
+                    for (BlankNode bNode : bNodesInContext) {
+                        final String bNodeVarLabel = bNodeVarNameMap.get(bNode);
+                        //looking for outgoing properties of the bnode
+                        queryBuilder.append("OPTIONAL { ");
+                        queryBuilder.append('?');
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(' ');
+                        queryBuilder.append("?po");
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(" ?o");
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(" } .\n");
+                        //looking for incoming properties of the bnode
+                        queryBuilder.append("OPTIONAL { ");
+                        queryBuilder.append("?s");
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(' ');
+                        queryBuilder.append("?pi");
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(" ?");
+                        queryBuilder.append(bNodeVarLabel);
+                        queryBuilder.append(" } .\n");
+                    }
+                    queryBuilder.append(" }");
+                    final List<Map<String, RdfTerm>> expansionQueryResults = sparqlClient.queryResultSet(queryBuilder.toString());
+                    Set<Collection<Triple>> expandedContexts = new HashSet<>();
+                    //the query results may or may be from disjoint supergraphs
+                    //we expand them all as if they are different which may lead
+                    //us to the same MSG multiple times
+                    RESULTS:
+                    for (Map<String, RdfTerm> expansionQueryResult : expansionQueryResults) {
+                        Collection<Triple> expandedContext = new HashSet<>();
+                        Map<BlankNode, BlankNode> newBNodesToOldBNodes = new HashMap<>();
+                        for (BlankNode oldBNode : bNodesInContext) {
+                            final String bNodeVarLabel = bNodeVarNameMap.get(oldBNode);
+                            final RdfTerm newNode = expansionQueryResult.get(bNodeVarLabel);
+                            if (!(newNode instanceof BlankNode)) {
+                                //this subgraph is't a match
+                                continue RESULTS;
+                            }
+                            newBNodesToOldBNodes.put((BlankNode) newNode, oldBNode);
+                        }
+                        expandedContext.addAll(startContext);
+                        boolean newBNodeIntroduced = false;
+                        boolean newTripleAdded = false;
+                        for (BlankNode oldBNode : bNodesInContext) {
+                            final String bNodeVarLabel = bNodeVarNameMap.get(oldBNode);
+                            {
+                                final Iri newPredicate = (Iri) expansionQueryResult.get("po" + bNodeVarLabel);
+                                if (newPredicate != null) {
+                                    RdfTerm newObject = expansionQueryResult.get("o" + bNodeVarLabel);
+                                    if (newObject instanceof BlankNode) {
+                                        if (newBNodesToOldBNodes.containsKey(newObject)) {
+                                            //point back to BNode in startContext
+                                            newObject = newBNodesToOldBNodes.get(newObject);
+                                        } else {
+                                            newBNodeIntroduced = true;
+                                        }
+                                    }
+                                    if (expandedContext.add(new TripleImpl(oldBNode, newPredicate, newObject))) {
+                                        newTripleAdded = true;
+                                    }
+                                }
+                            }
+                            {
+                                final Iri newPredicate = (Iri) expansionQueryResult.get("pi" + bNodeVarLabel);
+                                if (newPredicate != null) {
+                                    RdfTerm newSubject = expansionQueryResult.get("s" + bNodeVarLabel);
+                                    if (newSubject instanceof BlankNode) {
+                                        if (newBNodesToOldBNodes.containsKey(newSubject)) {
+                                            //point back to BNode in startContext
+                                            newSubject = newBNodesToOldBNodes.get(newSubject);
+                                        } else {
+                                            newBNodeIntroduced = true;
+                                        }
+                                    }
+                                    if (expandedContext.add(new TripleImpl((BlankNodeOrIri) newSubject, newPredicate, oldBNode))) {
+                                        newTripleAdded = true;
+                                    }
+                                }
+                            }
+                        }
+                        if (newBNodeIntroduced) {
+                            //we could be more efficient than this ans just expand the newly introduced bnodes
+                            expandedContexts.addAll(expandContext(expandedContext));
+                        } else {
+                            if (newTripleAdded) {
+                                //look for more results
+                                expandedContexts.addAll(expandContext(expandedContext));
+                                //expandedContexts.add(expandedContext);
+                            }
+                        }
+
+                    }
+                    if (expandedContexts.isEmpty()) {
+                        expandedContexts.add(startContext);
+                    }
+                    return expandedContexts;
+                }
+
+            }).call();
+        } catch (AlienBNodeException e) {
+            return new Iterator<Triple>() {
+
+                @Override
+                public boolean hasNext() {
+                    return false;
+                }
+
+                @Override
+                public Triple next() {
+                    throw new NoSuchElementException();
+                }
+            };
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Override
+    protected int performSize() {
+        try {
+            return sparqlClient.queryResultSet("SELECT * WHERE { ?s ?p ?o}").size();
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private String asSparqlTerm(Iri iri) {
+        return "<" + iri.getUnicodeString() + ">";
+    }
+
+    private String asSparqlTerm(Literal literal) {
+        //TODO langauge and datatype
+        return "\"" + literal.getLexicalForm() + "\"";
+    }
+
+    private String asSparqlTerm(BlankNode bnode) {
+        if (!(bnode instanceof SparqlBNode)) {
+            throw new AlienBNodeException();
+        }
+        //this requires adding additional clauses to the graph pattern
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    private String asSparqlTerm(BlankNodeOrIri term) {
+        if (term instanceof Iri) {
+            return asSparqlTerm((Iri) term);
+        } else {
+            return asSparqlTerm((BlankNode) term);
+        }
+    }
+
+    private String asSparqlTerm(RdfTerm term) {
+        if (term instanceof BlankNodeOrIri) {
+            return asSparqlTerm((BlankNodeOrIri) term);
+        } else {
+            return asSparqlTerm((Literal) term);
+        }
+    }
+
+    private static class AlienBNodeException extends RuntimeException {
+
+        public AlienBNodeException() {
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java
new file mode 100644
index 0000000..5208d34
--- /dev/null
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java
@@ -0,0 +1,101 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.apache.commons.rdf.impl.sparql;
+
+import com.hp.hpl.jena.query.DatasetAccessor;
+import com.hp.hpl.jena.query.DatasetAccessorFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import org.apache.jena.fuseki.EmbeddedFusekiServer;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ *
+ * @author reto
+ */
+public class BNodeCircleTest {
+
+    final static int serverPort = findFreePort();
+    static EmbeddedFusekiServer server;
+
+    @BeforeClass
+    public static void prepare() throws IOException {
+        final String serviceURI = "http://localhost:" + serverPort + "/ds/data";
+        final DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceURI);
+        final InputStream in = BNodeCircleTest.class.getResourceAsStream("bnode-circle.ttl");
+        final Model m = ModelFactory.createDefaultModel();
+        String base = "http://example.org/";
+        m.read(in, base, "TURTLE");
+        server = EmbeddedFusekiServer.memTDB(serverPort, "/ds");//dataSet.getAbsolutePath());
+        server.start();
+        System.out.println("Started fuseki on port " + serverPort);
+        accessor.putModel(m);
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        server.stop();
+    }
+
+    @Test
+    public void graphSize() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        Assert.assertEquals("Graph not of the exepected size", 2, graph.size());
+    }
+
+    
+    
+    @Test
+    public void nullFilter() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        
+        final Iri foafKnows = new Iri("http://xmlns.com/foaf/0.1/knows");
+
+        final Iterator<Triple> iter = graph.filter(null, null, null);
+        Assert.assertTrue(iter.hasNext());
+        final Triple triple1 = iter.next();
+        final BlankNodeOrIri subject = triple1.getSubject();
+        final RdfTerm object = triple1.getObject();
+        Assert.assertTrue(subject instanceof BlankNode);
+        Assert.assertTrue(object instanceof BlankNode);
+        Assert.assertNotEquals(subject, object);
+        Assert.assertTrue(iter.hasNext());
+    }
+    
+
+    
+
+    public static int findFreePort() {
+        int port = 0;
+        try (ServerSocket server = new ServerSocket(0);) {
+            port = server.getLocalPort();
+        } catch (Exception e) {
+            throw new RuntimeException("unable to find a free port");
+        }
+        return port;
+    }
+
+}
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java
new file mode 100644
index 0000000..a376fcd
--- /dev/null
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java
@@ -0,0 +1,137 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.apache.commons.rdf.impl.sparql;
+
+import com.hp.hpl.jena.query.DatasetAccessor;
+import com.hp.hpl.jena.query.DatasetAccessorFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import org.apache.jena.fuseki.EmbeddedFusekiServer;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ *
+ * @author reto
+ */
+public class BNodeTest {
+
+    final static int serverPort = findFreePort();
+    static EmbeddedFusekiServer server;
+
+    @BeforeClass
+    public static void prepare() throws IOException {
+        final String serviceURI = "http://localhost:" + serverPort + "/ds/data";
+        final DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceURI);
+        final InputStream in = BNodeTest.class.getResourceAsStream("simple-bnode.ttl");
+        final Model m = ModelFactory.createDefaultModel();
+        String base = "http://example.org/";
+        m.read(in, base, "TURTLE");
+        server = EmbeddedFusekiServer.memTDB(serverPort, "/ds");//dataSet.getAbsolutePath());
+        server.start();
+        System.out.println("Started fuseki on port " + serverPort);
+        accessor.putModel(m);
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        server.stop();
+    }
+
+    @Test
+    public void graphSize() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        Assert.assertEquals("Graph not of the exepected size", 3, graph.size());
+    }
+
+    /* Filtering with a Bode that cannot be in graph
+    */
+    @Test
+    public void filterAlienBNode() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        
+        final BlankNode blankNode = new BlankNode();
+        final Iterator<Triple> iter = graph.filter(blankNode, null, null);
+        Assert.assertFalse(iter.hasNext());
+    }
+    
+    @Test
+    public void bNodeIdentity() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        
+        final Iri foafPerson = new Iri("http://xmlns.com/foaf/0.1/Person");
+        final Iri foafName = new Iri("http://xmlns.com/foaf/0.1/name");
+        final Iri foafKnows = new Iri("http://xmlns.com/foaf/0.1/knows");
+        final Iri rdfType = new Iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
+
+        final Iterator<Triple> iter = graph.filter(null, foafName, null);
+        Assert.assertTrue(iter.hasNext());
+        final BlankNodeOrIri namedThing = iter.next().getSubject();
+        Assert.assertTrue(namedThing instanceof BlankNode);
+        
+        final Iterator<Triple> iter2 = graph.filter(null, rdfType, foafPerson);
+        Assert.assertTrue(iter2.hasNext());
+        final BlankNodeOrIri person = iter2.next().getSubject();
+        Assert.assertTrue(person instanceof BlankNode);
+        Assert.assertEquals(namedThing, person);
+        
+        final Iterator<Triple> iter3 = graph.filter(null, foafKnows, null);
+        Assert.assertTrue(iter3.hasNext());
+        final RdfTerm knownThing = iter3.next().getObject();
+        Assert.assertTrue(knownThing instanceof BlankNode);
+        Assert.assertEquals(knownThing, person);
+        Assert.assertEquals(namedThing, knownThing);
+    }
+    
+    @Ignore
+    @Test
+    public void filter1() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        
+        final Iri foafPerson = new Iri("http://xmlns.com/foaf/0.1/Person");
+        final Iri foafName = new Iri("http://xmlns.com/foaf/0.1/name");
+        final Iri rdfType = new Iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
+
+        final Iterator<Triple> iter = graph.filter(null, foafName, null);
+        Assert.assertTrue(iter.hasNext());
+        final BlankNodeOrIri person = iter.next().getSubject();
+        Assert.assertTrue(person instanceof BlankNode);
+        
+        final Iterator<Triple> iter2 = graph.filter(person, rdfType, null);
+        Assert.assertTrue(iter2.hasNext());
+    }
+    
+
+    public static int findFreePort() {
+        int port = 0;
+        try (ServerSocket server = new ServerSocket(0);) {
+            port = server.getLocalPort();
+        } catch (Exception e) {
+            throw new RuntimeException("unable to find a free port");
+        }
+        return port;
+    }
+
+}
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java
new file mode 100644
index 0000000..e75bc2c
--- /dev/null
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java
@@ -0,0 +1,104 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.apache.commons.rdf.impl.sparql;
+
+import com.hp.hpl.jena.query.DatasetAccessor;
+import com.hp.hpl.jena.query.DatasetAccessorFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import org.apache.jena.fuseki.EmbeddedFusekiServer;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ * @author reto
+ */
+public class SparqlGraphTest {
+
+    final static int serverPort = findFreePort();
+    static EmbeddedFusekiServer server;
+
+    @BeforeClass
+    public static void prepare() throws IOException {
+        final String serviceURI = "http://localhost:" + serverPort + "/ds/data";
+        final DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceURI);
+        final InputStream in = SparqlGraphTest.class.getResourceAsStream("grounded.ttl");
+        final Model m = ModelFactory.createDefaultModel();
+        String base = "http://example.org/";
+        m.read(in, base, "TURTLE");
+        server = EmbeddedFusekiServer.memTDB(serverPort, "/ds");//dataSet.getAbsolutePath());
+        server.start();
+        System.out.println("Started fuseki on port " + serverPort);
+        accessor.putModel(m);
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        server.stop();
+    }
+
+    @Test
+    public void graphSize() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        Assert.assertEquals("Graph not of the exepected size", 8, graph.size());
+    }
+
+    @Test
+    public void filter1() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        final Iri spiderman = new Iri("http://example.org/#spiderman");
+        final Iri greenGoblin = new Iri("http://example.org/#green-goblin");
+        final Iri enemyOf = new Iri("http://www.perceive.net/schemas/relationship/enemyOf");
+        final Iri foafName = new Iri("http://xmlns.com/foaf/0.1/name");
+        {
+            final Iterator<Triple> iter = graph.filter(spiderman, null, greenGoblin);
+            Assert.assertTrue(iter.hasNext());
+            Assert.assertEquals(enemyOf, iter.next().getPredicate());
+            Assert.assertFalse(iter.hasNext());
+        }
+        {
+            final Iterator<Triple> iter = graph.filter(spiderman, foafName, null);
+            Set<Literal> names = new HashSet<>();
+            for (int i = 0; i < 2; i++) {
+                Assert.assertTrue(iter.hasNext());
+                RdfTerm name = iter.next().getObject();
+                Assert.assertTrue(name instanceof Literal);
+                names.add((Literal)name);
+            }
+            Assert.assertFalse(iter.hasNext());
+            Assert.assertTrue(names.contains(new PlainLiteralImpl("Spiderman")));
+            Assert.assertTrue(names.contains(new PlainLiteralImpl("Человек-паук", new Language("ru"))));
+        }
+    }
+
+    public static int findFreePort() {
+        int port = 0;
+        try (ServerSocket server = new ServerSocket(0);) {
+            port = server.getLocalPort();
+        } catch (Exception e) {
+            throw new RuntimeException("unable to find a free port");
+        }
+        return port;
+    }
+
+}
diff --git a/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/bnode-circle.ttl b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/bnode-circle.ttl
new file mode 100644
index 0000000..f03ab4d
--- /dev/null
+++ b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/bnode-circle.ttl
@@ -0,0 +1,7 @@
+@base <http://example.org/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+_:a foaf:knows _:b .
+_:b foaf:knows _:a .
\ No newline at end of file
diff --git a/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/grounded.ttl b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/grounded.ttl
new file mode 100644
index 0000000..ccc39c4
--- /dev/null
+++ b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/grounded.ttl
@@ -0,0 +1,16 @@
+@base <http://example.org/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix rel: <http://www.perceive.net/schemas/relationship/> .
+
+<#green-goblin>
+    rel:enemyOf <#spiderman> ;
+    a foaf:Person ;    # in the context of the Marvel universe
+    foaf:name "Green Goblin" ;
+    foaf:age 128 .
+
+<#spiderman>
+    rel:enemyOf <#green-goblin> ;
+    a foaf:Person ;
+    foaf:name "Spiderman", "Человек-паук"@ru .
\ No newline at end of file
diff --git a/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/simple-bnode.ttl b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/simple-bnode.ttl
new file mode 100644
index 0000000..6bcf67f
--- /dev/null
+++ b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/simple-bnode.ttl
@@ -0,0 +1,7 @@
+@base <http://example.org/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://example.org/#me> foaf:knows [ a foaf:Person;
+  foaf:name "Alice Barker"].
\ No newline at end of file
diff --git a/impl.utils/pom.xml b/impl.utils/pom.xml
new file mode 100644
index 0000000..9a17a90
--- /dev/null
+++ b/impl.utils/pom.xml
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+   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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-parent</artifactId>
+        <version>37</version>
+        <relativePath />
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>commons-rdf</groupId>
+    <artifactId>commons-rdf-impl-utils</artifactId>
+    <version>0.1-SNAPSHOT</version>
+    <name>Apache Commons RDF Implementation Utils</name>
+    <description>
+        Apache Commons RDF provides an API modelling the RDF data model as defined by 
+        http://www.w3.org/TR/rdf11-concepts/
+    </description>
+    <url>http://commons.apache.org/sandbox/commons-rdf/</url>
+    <!-- TBD
+    <issueManagement>
+        <system>jira</system>
+        <url>http://issues.apache.org/jira/browse/RDF</url>
+    </issueManagement>
+    -->
+    <inceptionYear>2014</inceptionYear>
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/rdf/trunk</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/rdf/trunk</developerConnection>
+        <url>http://svn.apache.org/viewvc/commons/proper/rdf/trunk</url>
+    </scm>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>commons-rdf</groupId>
+            <artifactId>commons-rdf-api</artifactId>
+            <version>0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.7</version>
+            <type>jar</type>
+        </dependency>
+    </dependencies>
+
+    <distributionManagement>
+      <site>
+        <id>apache.website</id>
+        <name>Apache Commons Site</name>
+        <url>${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid}</url>
+      </site>
+    </distributionManagement>
+
+    <properties>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+        <commons.javadoc.java.link>http://docs.oracle.com/javase/7/docs/api/</commons.javadoc.java.link>
+        <commons.componentid>rdf</commons.componentid>
+        <commons.release.version>${project.version}</commons.release.version>
+<!--        <commons.rc.version>RC1</commons.rc.version>
+        <commons.release.desc>(Requires Java ${maven.compiler.target} or later)</commons.release.desc>
+        <commons.release.2.version>1.4.1</commons.release.2.version>
+        <commons.release.2.binary.suffix />
+        <commons.release.2.desc>(Requires Java 1.3 or later)</commons.release.2.desc> -->
+        <!-- TBD <commons.jira.id>RDF</commons.jira.id>
+        <commons.jira.pid></commons.jira.pid> -->
+    </properties>
+
+    <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-compiler-plugin</artifactId>
+              <version>${commons.compiler.version}</version>
+              <configuration>
+                <!-- Fix incremental compiler bug, see https://jira.codehaus.org/browse/MCOMPILER-205 etc. -->
+                <excludes>
+                  <exclude>**/package-info.java</exclude>
+                </excludes>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+        <plugins>
+
+            <!-- Exclude examples from binary jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <!-- Exclude examples from source jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>**/*FunctionalTest.java</exclude>
+                        <exclude>**/POP3*Test.java</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/bin.xml</descriptor>
+                        <descriptor>src/main/assembly/src.xml</descriptor>
+                    </descriptors>
+                    <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <configuration>
+                            <target>
+                                <jar destfile="target/commons-net-ftp-${project.version}.jar">
+                                    <metainf dir="${basedir}" includes="NOTICE.txt,LICENSE.txt" />
+                                    <manifest>
+                                        <attribute name="Extension-Name" value="org.apache.commons.net" />
+                                        <attribute name="Specification-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Vendor" value="${project.organization.name}" />
+                                        <attribute name="Implementation-Version" value="${project.version}" />
+                                        <attribute name="Implementation-Vendor-Id" value="org.apache" />
+                                        <attribute name="Implementation-Build" value="${implementation.build}"/>
+                                        <attribute name="X-Compile-Source-JDK" value="${maven.compiler.source}" />
+                                        <attribute name="X-Compile-Target-JDK" value="${maven.compiler.target}" />
+                                    </manifest>
+                                    <fileset dir="target/classes" includes="org/apache/commons/net/ftp/**,org/apache/commons/net/*,org/apache/commons/net/io/*,org/apache/commons/net/util/*" />
+                                </jar>
+                                <!--
+                                    Create the binary examples jar, which will be added to the binary zip/tgz,
+                                    but not deployed independently to Maven
+                                -->
+                                <jar destfile="target/commons-net-examples-${project.version}.jar">
+                                    <metainf dir="${basedir}" includes="NOTICE.txt,LICENSE.txt" />
+                                    <manifest>
+                                        <attribute name="Extension-Name" value="org.apache.commons.net" />
+                                        <attribute name="Specification-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Title" value="${project.name}" />
+                                        <attribute name="Implementation-Vendor" value="${project.organization.name}" />
+                                        <attribute name="Implementation-Version" value="${project.version}" />
+                                        <attribute name="Implementation-Vendor-Id" value="org.apache" />
+                                        <attribute name="Implementation-Build" value="${implementation.build}"/>
+                                        <attribute name="X-Compile-Source-JDK" value="${maven.compiler.source}" />
+                                        <attribute name="X-Compile-Target-JDK" value="${maven.compiler.target}" />
+                                        <!-- Helper application -->
+                                        <attribute name="Main-Class" value="examples/Main" />
+                                        <!-- Allow java -jar examples.jar to work -->
+                                        <attribute name="Class-Path" value="commons-net-${project.version}.jar" />
+                                    </manifest>
+                                    <fileset dir="target/classes" includes="examples/**" />
+                                </jar>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--  Attaches the commons-net-ftp and examples JARs to the Maven lifecycle
+                  to ensure they will be signed and deployed as normal -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>attach-artifacts</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>target/commons-net-ftp-${project.version}.jar</file>
+                                    <type>jar</type>
+                                    <classifier>ftp</classifier>
+                                </artifact>
+                                <artifact>
+                                    <file>target/commons-net-examples-${project.version}.jar</file>
+                                    <type>jar</type>
+                                    <classifier>examples</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Exclude examples from Javadoc jar -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>examples.*</excludePackageNames>
+                </configuration>
+            </plugin>
+
+            <!-- Copy the examples sources -->
+            <plugin>
+              <artifactId>maven-resources-plugin</artifactId>
+              <executions>
+                <execution>
+                  <id>copy-resources</id>
+                  <phase>pre-site</phase>
+                  <goals>
+                    <goal>copy-resources</goal>
+                  </goals>
+                  <configuration>
+                    <outputDirectory>${basedir}/target/site/examples</outputDirectory>
+                    <resources>
+                      <resource>
+                        <directory>src/main/java/examples</directory>
+                        <excludes>
+                          <exclude>**/Main.java</exclude>
+                        </excludes>
+                        <filtering>false</filtering>
+                      </resource>
+                    </resources>
+                  </configuration>
+                </execution>
+              </executions>
+            </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-scm-publish-plugin</artifactId>
+            <configuration>
+              <ignorePathsToDelete>
+                <ignorePathToDelete>javadocs</ignorePathToDelete>
+              </ignorePathsToDelete>
+            </configuration>
+          </plugin>
+
+        </plugins>
+
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-changes-plugin</artifactId>
+                <version>${commons.changes.version}</version>
+                <configuration>
+                    <issueLinkTemplatePerSystem>
+                        <default>%URL%/%ISSUE%</default>
+                    </issueLinkTemplatePerSystem>
+                    <template>release-notes.vm</template>
+                    <templateDirectory>src/changes</templateDirectory>
+                    <!--  Add sample JIRA report - 'mvn changes:jira-report' or 'mvn site' -->
+                    <onlyCurrentVersion>false</onlyCurrentVersion>
+                    <columnNames>Fix Version,Key,Component,Summary,Type,Resolution,Status</columnNames>
+                    <!-- Sort cols have to be reversed in JIRA 4 -->
+                    <sortColumnNames>Key DESC,Type,Fix Version DESC</sortColumnNames>
+                    <resolutionIds>Fixed</resolutionIds>
+                    <statusIds>Resolved,Closed</statusIds>
+                    <!-- Don't include sub-task -->
+                    <typeIds>Bug,New Feature,Task,Improvement,Wish,Test</typeIds>
+                    <fixVersionIds>${commons.release.version}</fixVersionIds>
+                    <!-- The default is 100 -->
+                    <maxEntries>100</maxEntries>
+                </configuration>
+                <reportSets>
+                    <reportSet>
+                        <reports>
+                            <report>changes-report</report>
+                            <report>jira-report</report>
+                        </reports>
+                    </reportSet>
+                </reportSets>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>findbugs-maven-plugin</artifactId>
+                <version>2.5.5</version>
+                <configuration>
+                    <excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>clirr-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                      <exclude>examples/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>examples.*</excludePackageNames>
+                </configuration>
+                <reportSets>
+                  <reportSet>
+                    <reports>
+                      <report>javadoc</report>
+                    </reports>
+                  </reportSet>
+                </reportSets>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.11</version>
+                <configuration>
+                    <configLocation>${basedir}/checkstyle.xml</configLocation>
+                    <suppressionsLocation>${basedir}/checkstyle-suppressions.xml</suppressionsLocation>
+                    <enableRulesSummary>false</enableRulesSummary>
+                </configuration>
+            </plugin>
+
+            <plugin>
+              <groupId>org.apache.rat</groupId>
+              <artifactId>apache-rat-plugin</artifactId>
+              <!-- Parent pom does not (yet) exclude these -->
+              <configuration>
+                <excludes>
+                  <exclude>.checkstyle</exclude>
+                  <exclude>.fbprefs</exclude>
+                </excludes>
+              </configuration>
+            </plugin>
+
+        </plugins>
+    </reporting>
+
+    <profiles>
+      <profile>
+        <!-- Temporary hack to suppress Javadoc 8 errors -->
+        <id>javadoc_8</id>
+        <activation>
+          <jdk>1.8</jdk>
+        </activation>
+        <properties>
+          <!-- Disable Xdoclint, until JavaDoc issues are fixed -->
+          <additionalparam>-Xdoclint:none</additionalparam>
+        </properties>
+      </profile>
+    </profiles>
+
+</project>
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractGraph.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractGraph.java
new file mode 100644
index 0000000..2c99679
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractGraph.java
@@ -0,0 +1,316 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.AbstractCollection;
+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.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+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.WatchableGraph;
+import org.apache.commons.rdf.event.AddEvent;
+import org.apache.commons.rdf.event.FilterTriple;
+import org.apache.commons.rdf.event.GraphEvent;
+import org.apache.commons.rdf.event.GraphListener;
+import org.apache.commons.rdf.event.RemoveEvent;
+import org.apache.commons.rdf.impl.utils.debug.ReentrantReadWriteLockTracker;
+import org.apache.commons.rdf.impl.utils.simple.SimpleImmutableGraph;
+
+/**
+ * An abstract implementation of <code>Graph</code> implementing
+ * <code>iterator</code> and <code>contains</code> calling <code>filter</code>.
+ *
+ * @author reto
+ */
+public abstract class AbstractGraph extends AbstractCollection<Triple>
+        implements Graph {
+
+    
+    private static final String DEBUG_MODE = "rdfLocksDebugging";
+    private final ReadWriteLock lock;
+
+    private final Lock readLock;
+    private final Lock writeLock;
+
+    /**
+     * Constructs a LocalbleMGraph for an Graph.
+     *
+     * @param providedMGraph a non-lockable graph
+     */
+    public AbstractGraph() {
+        {
+            String debugMode = System.getProperty(DEBUG_MODE);
+            if (debugMode != null && debugMode.toLowerCase().equals("true")) {
+                lock = new ReentrantReadWriteLockTracker();
+            } else {
+                lock = new ReentrantReadWriteLock();
+            }
+        }
+        readLock = lock.readLock();
+        writeLock = lock.writeLock();
+    }
+    
+    public AbstractGraph(final ReadWriteLock lock) {
+        this.lock = lock;
+        readLock = lock.readLock();
+        writeLock = lock.writeLock();
+    }
+
+    @Override
+    public ReadWriteLock getLock() {
+        return lock;
+    }
+
+    @Override
+    public ImmutableGraph getImmutableGraph() {
+        readLock.lock();
+        try {
+            return performGetImmutableGraph();
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    public ImmutableGraph performGetImmutableGraph() {
+        return new SimpleImmutableGraph(this);
+    }
+
+    @Override
+    public Iterator<Triple> filter(BlankNodeOrIri subject, Iri predicate, RdfTerm object) {
+        readLock.lock();
+        try {
+            return new LockingIterator(performFilter(subject, predicate, object), lock);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public int size() {
+        readLock.lock();
+        try {
+            return performSize();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean isEmpty() {
+        readLock.lock();
+        try {
+            return performIsEmpty();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    @SuppressWarnings("element-type-mismatch")
+    public boolean contains(Object o) {
+        readLock.lock();
+        try {
+            return performContains(o);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public Iterator<Triple> iterator() {
+        readLock.lock();
+        try {
+            return new LockingIterator(performIterator(), lock);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public Object[] toArray() {
+        readLock.lock();
+        try {
+            return performToArray();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        readLock.lock();
+        try {
+            return performToArray(a);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        readLock.lock();
+        try {
+            return performContainsAll(c);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean add(Triple e) {
+        writeLock.lock();
+        try {
+            return performAdd(e);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        writeLock.lock();
+        try {
+            return performRemove(o);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends Triple> c) {
+        writeLock.lock();
+        try {
+            return performAddAll(c);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        writeLock.lock();
+        try {
+            return performRemoveAll(c);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        writeLock.lock();
+        try {
+            return performRetainAll(c);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void clear() {
+        writeLock.lock();
+        try {
+            performClear();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    
+    @Override
+    public boolean equals(Object obj) {
+        /*if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != getClass()) {
+            return false;
+        }*/
+        return this == obj;
+    }
+
+
+    protected abstract Iterator<Triple> performFilter(BlankNodeOrIri subject, Iri predicate, RdfTerm object);
+
+    protected abstract int performSize();
+
+    protected boolean performIsEmpty() {
+        return super.isEmpty();
+    }
+
+    protected Object[] performToArray() {
+        return super.toArray();
+    }
+
+    protected boolean performRemove(Object o) {
+        return super.remove(o);
+    }
+
+    protected boolean performAddAll(Collection<? extends Triple> c) {
+        return super.addAll(c);
+    }
+
+    protected boolean performRemoveAll(Collection<?> c) {
+        return super.removeAll(c);
+    }
+
+    protected boolean performRetainAll(Collection<?> c) {
+        return super.retainAll(c);
+    }
+
+    protected void performClear() {
+        super.clear();
+    }
+
+    protected boolean performContains(Object o) {
+        return super.contains(o);
+    }
+
+    protected Iterator<Triple> performIterator() {
+        return performFilter(null, null, null);
+    }
+
+    protected boolean performContainsAll(Collection<?> c) {
+        return super.containsAll(c);
+    }
+
+    protected <T> T[] performToArray(T[] a) {
+        return super.toArray(a);
+    }
+
+    protected boolean performAdd(Triple e) {
+        return super.add(e);
+    }
+
+ 
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractImmutableGraph.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractImmutableGraph.java
new file mode 100644
index 0000000..912a5ff
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.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;
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractLiteral.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/AbstractLiteral.java
new file mode 100644
index 0000000..e1fac11
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils;
+
+import org.apache.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;
+        }
+    }
+    
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/DelayedNotificator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/DelayedNotificator.java
new file mode 100644
index 0000000..8fc8e92
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/DelayedNotificator.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.commons.rdf.impl.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+
+import org.apache.commons.rdf.event.GraphEvent;
+import org.apache.commons.rdf.event.GraphListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author reto
+ */
+class DelayedNotificator {
+
+    private static final Logger log = LoggerFactory.getLogger(DelayedNotificator.class);
+    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.debug("Ignoring garbage collected listener");
+                            } else {
+                                try {
+                                    listener.graphChanged(eventsLocal);
+                                } catch (Exception e) {
+                                    log.warn("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);
+        }
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/LockingIterator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/LockingIterator.java
new file mode 100644
index 0000000..8f6945e
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils;
+
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.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();
+        }
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/PlainLiteralImpl.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/PlainLiteralImpl.java
new file mode 100644
index 0000000..5dcbaf7
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/PlainLiteralImpl.java
@@ -0,0 +1,104 @@
+/*
+ * 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.commons.rdf.impl.utils;
+
+import java.io.Serializable;
+import org.apache.commons.rdf.Iri;
+
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+
+/**
+ *
+ * @author reto
+ */
+public class PlainLiteralImpl implements Literal, Serializable {
+
+    private String lexicalForm;
+    private Language language = null;
+
+    public PlainLiteralImpl(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException("The literal string cannot be null");
+        }
+        this.lexicalForm = value;
+    }
+
+    public PlainLiteralImpl(String value, Language language) {
+        if (value == null) {
+            throw new IllegalArgumentException("The literal string cannot be null");
+        }
+        this.lexicalForm = value;
+        this.language = language;
+    }
+
+    @Override
+    public String getLexicalForm() {
+        return lexicalForm;
+    }
+
+    @Override
+    public boolean equals(Object otherObj) {
+        if (!(otherObj instanceof Literal)) {
+            return false;
+        }
+        Literal other = (Literal) otherObj;
+        if (!lexicalForm.equals(other.getLexicalForm())) {
+            return false;
+        }
+        if (language != null) {
+            return language.equals(other.getLanguage());
+        }
+        if (other.getLanguage() != null) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = lexicalForm.hashCode() + XSD_STRING_HASH;
+        if (language != null) {
+            hash += language.hashCode();
+        }
+        return hash;
+    }
+
+    @Override
+    public Language getLanguage() {
+        return language;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer result = new StringBuffer();
+        result.append('\"').append(lexicalForm).append('\"');
+        if (language != null) {
+            result.append("@").append(language.toString());
+        }
+        return result.toString();
+    }
+
+    @Override
+    public Iri getDataType() {
+        return XSD_STRING;
+    }
+    private static final Iri XSD_STRING = new Iri("http://www.w3.org/2001/XMLSchema#string");
+    private static final int XSD_STRING_HASH = XSD_STRING.hashCode();
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/TripleImpl.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/TripleImpl.java
new file mode 100644
index 0000000..ece7d55
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils;
+
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.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 + ".";
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/TypedLiteralImpl.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/TypedLiteralImpl.java
new file mode 100644
index 0000000..45863ff
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils;
+
+import java.io.Serializable;
+
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Language;
+import org.apache.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 = lexicalForm.hashCode()+dataType.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;
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/WatchableGraphWrapper.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/WatchableGraphWrapper.java
new file mode 100644
index 0000000..76b9283
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.WatchableGraph;
+import org.apache.commons.rdf.event.AddEvent;
+import org.apache.commons.rdf.event.FilterTriple;
+import org.apache.commons.rdf.event.GraphEvent;
+import org.apache.commons.rdf.event.GraphListener;
+import org.apache.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;
+        }
+    }
+    
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/ReadLockDebug.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/ReadLockDebug.java
new file mode 100644
index 0000000..f2b93b8
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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;
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/ReentrantReadWriteLockTracker.java
new file mode 100644
index 0000000..65abf32
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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;
+    }
+
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/WriteLockDebug.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/debug/WriteLockDebug.java
new file mode 100644
index 0000000..0231331
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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;
+    }
+
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GraphMatcher.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GraphMatcher.java
new file mode 100644
index 0000000..70f5437
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GraphMatcher.java
@@ -0,0 +1,141 @@
+/*
+ * 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.commons.rdf.impl.utils.graphmatching;
+
+
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.commons.rdf.impl.utils.simple.SimpleMGraph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author reto
+ * 
+ */
+public class GraphMatcher {
+
+
+    private final static Logger log = LoggerFactory.getLogger(GraphMatcher.class);
+
+    /**
+     * 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.isDebugEnabled()) {
+            Set<BlankNode> bn1  = Utils.getBNodes(g1);
+            log.debug("doing trial and error matching for {} bnodes, " +
+                    "in graphs of size: {}.", 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);
+    }
+
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GraphNotIsomorphicException.java
new file mode 100644
index 0000000..42de52e
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils.graphmatching;
+
+/**
+ *
+ * @author reto
+ */
+class GraphNotIsomorphicException extends Exception {
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/GroupMappingIterator.java
new file mode 100644
index 0000000..f79bd2a
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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.");
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/HashMatching.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/HashMatching.java
new file mode 100644
index 0000000..ae419f6
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.commons.rdf.impl.utils.graphmatching;
+
+
+import org.apache.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.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.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.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);
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/MappingIterator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/MappingIterator.java
new file mode 100644
index 0000000..dea95b5
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/MappingIterator.java
@@ -0,0 +1,76 @@
+package org.apache.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.");
+    }
+
+
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/PermutationIterator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/PermutationIterator.java
new file mode 100644
index 0000000..6b6fa07
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/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.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;
+        }
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/Utils.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/Utils.java
new file mode 100644
index 0000000..25a7a4b
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/Utils.java
@@ -0,0 +1,82 @@
+package org.apache.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.commons.rdf.BlankNode;
+import org.apache.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;
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashMap.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashMap.java
new file mode 100644
index 0000000..922ae47
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashMap.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2002-2004 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.
+ */
+
+/*
+ * Note: originally released under the GNU LGPL v2.1, 
+ * but rereleased by the original author under the ASF license (above).
+ */
+
+package org.apache.commons.rdf.impl.utils.graphmatching.collections;
+
+
+
+/**
+ * <p>A hash map that uses primitive ints for the key rather than objects.</p>
+ *
+ * <p>Note that this class is for internal optimization purposes only, and may
+ * not be supported in future releases of Jakarta Commons Lang.  Utilities of
+ * this sort may be included in future releases of Jakarta Commons Collections.</p>
+ *
+ * @author Justin Couch
+ * @author Alex Chaffee (alex@apache.org)
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Revision: 1.2 $
+ * @see java.util.HashMap
+ */
+public class IntHashMap<T> {
+
+
+    private IntSet keySet = new IntHashSet();
+
+    /**
+     * The hash table data.
+     */
+    private transient Entry<T> table[];
+
+    /**
+     * The total number of entries in the hash table.
+     */
+    private transient int count;
+
+    /**
+     * The table is rehashed when its size exceeds this threshold.  (The
+     * value of this field is (int)(capacity * loadFactor).)
+     *
+     * @serial
+     */
+    private int threshold;
+
+    /**
+     * The load factor for the hashtable.
+     *
+     * @serial
+     */
+    private float loadFactor;
+
+    /**
+     * <p>Innerclass that acts as a datastructure to create a new entry in the
+     * table.</p>
+     */
+    private static class Entry<T> {
+        int hash;
+        int key;
+        T value;
+        Entry<T> next;
+
+        /**
+         * <p>Create a new entry with the given values.</p>
+         *
+         * @param hash The code used to hash the object with
+         * @param key The key used to enter this in the table
+         * @param value The value for this key
+         * @param next A reference to the next entry in the table
+         */
+        protected Entry(int hash, int key, T value, Entry<T> next) {
+            this.hash = hash;
+            this.key = key;
+            this.value = value;
+            this.next = next;
+        }
+    }
+
+    /**
+     * <p>Constructs a new, empty hashtable with a default capacity and load
+     * factor, which is <code>20</code> and <code>0.75</code> respectively.</p>
+     */
+    public IntHashMap() {
+        this(20, 0.75f);
+    }
+
+    /**
+     * <p>Constructs a new, empty hashtable with the specified initial capacity
+     * and default load factor, which is <code>0.75</code>.</p>
+     *
+     * @param  initialCapacity the initial capacity of the hashtable.
+     * @throws IllegalArgumentException if the initial capacity is less
+     *   than zero.
+     */
+    public IntHashMap(int initialCapacity) {
+        this(initialCapacity, 0.75f);
+    }
+
+    /**
+     * <p>Constructs a new, empty hashtable with the specified initial
+     * capacity and the specified load factor.</p>
+     *
+     * @param initialCapacity the initial capacity of the hashtable.
+     * @param loadFactor the load factor of the hashtable.
+     * @throws IllegalArgumentException  if the initial capacity is less
+     *             than zero, or if the load factor is nonpositive.
+     */
+    public IntHashMap(int initialCapacity, float loadFactor) {
+        super();
+        if (initialCapacity < 0) {
+            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
+        }
+        if (loadFactor <= 0) {
+            throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+        }
+        if (initialCapacity == 0) {
+            initialCapacity = 1;
+        }
+
+        this.loadFactor = loadFactor;
+        table = new Entry[initialCapacity];
+        threshold = (int) (initialCapacity * loadFactor);
+    }
+
+    /**
+     * <p>Returns the number of keys in this hashtable.</p>
+     *
+     * @return  the number of keys in this hashtable.
+     */
+    public int size() {
+        return count;
+    }
+
+    /**
+     * <p>Tests if this hashtable maps no keys to values.</p>
+     *
+     * @return  <code>true</code> if this hashtable maps no keys to values;
+     *          <code>false</code> otherwise.
+     */
+    public boolean isEmpty() {
+        return count == 0;
+    }
+
+    /**
+     * <p>Tests if some key maps into the specified value in this hashtable.
+     * This operation is more expensive than the <code>containsKey</code>
+     * method.</p>
+     *
+     * <p>Note that this method is identical in functionality to containsValue,
+     * (which is part of the Map interface in the collections framework).</p>
+     *
+     * @param      value   a value to search for.
+     * @return     <code>true</code> if and only if some key maps to the
+     *             <code>value</code> argument in this hashtable as
+     *             determined by the <tt>equals</tt> method;
+     *             <code>false</code> otherwise.
+     * @throws  NullPointerException  if the value is <code>null</code>.
+     * @see        #containsKey(int)
+     * @see        #containsValue(Object)
+     * @see        java.util.Map
+     */
+    public boolean contains(Object value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+
+        Entry tab[] = table;
+        for (int i = tab.length; i-- > 0;) {
+            for (Entry e = tab[i]; e != null; e = e.next) {
+                if (e.value.equals(value)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * <p>Returns <code>true</code> if this HashMap maps one or more keys
+     * to this value.</p>
+     *
+     * <p>Note that this method is identical in functionality to contains
+     * (which predates the Map interface).</p>
+     *
+     * @param value value whose presence in this HashMap is to be tested.
+     * @see    java.util.Map
+     * @since JDK1.2
+     */
+    public boolean containsValue(Object value) {
+        return contains(value);
+    }
+
+    /**
+     * <p>Tests if the specified object is a key in this hashtable.</p>
+     *
+     * @param  key  possible key.
+     * @return <code>true</code> if and only if the specified object is a
+     *    key in this hashtable, as determined by the <tt>equals</tt>
+     *    method; <code>false</code> otherwise.
+     * @see #contains(Object)
+     */
+    public boolean containsKey(int key) {
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * <p>Returns the value to which the specified key is mapped in this map.</p>
+     *
+     * @param   key   a key in the hashtable.
+     * @return  the value to which the key is mapped in this hashtable;
+     *          <code>null</code> if the key is not mapped to any value in
+     *          this hashtable.
+     * @see     #put(int, Object)
+     */
+    public T get(int key) {
+        Entry<T> tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry<T> e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                return e.value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * <p>Increases the capacity of and internally reorganizes this
+     * hashtable, in order to accommodate and access its entries more
+     * efficiently.</p>
+     *
+     * <p>This method is called automatically when the number of keys
+     * in the hashtable exceeds this hashtable's capacity and load
+     * factor.</p>
+     */
+    protected void rehash() {
+        int oldCapacity = table.length;
+        Entry<T> oldMap[] = table;
+
+        int newCapacity = oldCapacity * 2 + 1;
+        Entry<T> newMap[] = new Entry[newCapacity];
+
+        threshold = (int) (newCapacity * loadFactor);
+        table = newMap;
+
+        for (int i = oldCapacity; i-- > 0;) {
+            for (Entry<T> old = oldMap[i]; old != null;) {
+                Entry<T> e = old;
+                old = old.next;
+
+                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
+                e.next = newMap[index];
+                newMap[index] = e;
+            }
+        }
+    }
+
+    /**
+     * <p>Maps the specified <code>key</code> to the specified
+     * <code>value</code> in this hashtable. The key cannot be
+     * <code>null</code>. </p>
+     *
+     * <p>The value can be retrieved by calling the <code>get</code> method
+     * with a key that is equal to the original key.</p>
+     *
+     * @param key     the hashtable key.
+     * @param value   the value.
+     * @return the previous value of the specified key in this hashtable,
+     *         or <code>null</code> if it did not have one.
+     * @throws  NullPointerException  if the key is <code>null</code>.
+     * @see     #get(int)
+     */
+    public Object put(int key, T value) {
+            keySet.add(key);
+        // Makes sure the key is not already in the hashtable.
+        Entry<T> tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry<T> e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                T old = e.value;
+                e.value = value;
+                return old;
+            }
+        }
+
+        if (count >= threshold) {
+            // Rehash the table if the threshold is exceeded
+            rehash();
+
+            tab = table;
+            index = (hash & 0x7FFFFFFF) % tab.length;
+        }
+
+        // Creates the new entry.
+        Entry<T> e = new Entry<T>(hash, key, value, tab[index]);
+        tab[index] = e;
+        count++;
+        return null;
+    }
+
+    /**
+     * <p>Removes the key (and its corresponding value) from this
+     * hashtable.</p>
+     *
+     * <p>This method does nothing if the key is not present in the
+     * hashtable.</p>
+     *
+     * @param   key   the key that needs to be removed.
+     * @return  the value to which the key had been mapped in this hashtable,
+     *          or <code>null</code> if the key did not have a mapping.
+     */
+    /*public Object remove(int key) {
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
+            if (e.hash == hash) {
+                if (prev != null) {
+                    prev.next = e.next;
+                } else {
+                    tab[index] = e.next;
+                }
+                count--;
+                Object oldValue = e.value;
+                e.value = null;
+                return oldValue;
+            }
+        }
+        return null;
+    }*/
+
+    /**
+     * <p>Clears this hashtable so that it contains no keys.</p>
+     */
+    public synchronized void clear() {
+            keySet.clear();
+        Entry tab[] = table;
+        for (int index = tab.length; --index >= 0;) {
+            tab[index] = null;
+        }
+        count = 0;
+    }
+    
+    public IntSet keySet() {
+            return keySet;
+    }
+    
+    
+    
+}
+
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashSet.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashSet.java
new file mode 100644
index 0000000..4dd92b1
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntHashSet.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2004 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.commons.rdf.impl.utils.graphmatching.collections;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * This is currently just a placeholder implementation based onm HashSet<Integer>
+ * an efficient implementation is to store the primitives directly.
+ *
+ * @author reto
+ */
+public class IntHashSet extends HashSet<Integer> implements IntSet {
+
+    @Override
+    public IntIterator intIterator() {
+        final Iterator<Integer> base = iterator();
+        return new IntIterator() {
+
+            @Override
+            public int nextInt() {
+                return base.next();
+            }
+
+            @Override
+            public boolean hasNext() {
+                return base.hasNext();
+            }
+
+            @Override
+            public Integer next() {
+                return base.next();
+            }
+
+            @Override
+            public void remove() {
+                base.remove();
+            }
+        };
+    }
+
+    @Override
+    public void add(int i) {
+        super.add((Integer)i);
+    }
+
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntIterator.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntIterator.java
new file mode 100644
index 0000000..050cf82
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntIterator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2004 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.commons.rdf.impl.utils.graphmatching.collections;
+
+import java.util.Iterator;
+
+
+/**
+ * An iterator allowing to iterate over ints, Iterator<Integer> is extended for
+ * compatibility, however accessing nextInt allows faster implementations.
+ *
+ * @author reto
+ */
+public interface IntIterator extends Iterator<Integer> {
+    public int nextInt();
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntSet.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntSet.java
new file mode 100644
index 0000000..5c3e465
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/graphmatching/collections/IntSet.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2004 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.commons.rdf.impl.utils.graphmatching.collections;
+
+import java.util.Set;
+
+/**
+ * A IntSet allows directly adding primitive ints to a set, Set<Integer> is 
+ * extended, but accessingt he respective methods is less efficient.
+ *
+ * @author reto
+ */
+public interface IntSet extends Set<Integer> {
+    /**
+     *
+     * @return an iterator over the primitive int
+     */
+    public IntIterator intIterator();
+    
+    public void add(int i);
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/package-info.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/package-info.java
new file mode 100644
index 0000000..a1fa1c5
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Common RDF API Implementation utilities.
+ */
+package org.apache.commons.rdf.impl.utils;
\ No newline at end of file
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraph.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraph.java
new file mode 100644
index 0000000..9b60a15
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraph.java
@@ -0,0 +1,218 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import org.apache.commons.rdf.impl.utils.AbstractGraph;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Iri;
+
+/**
+ * For now this is a minimalistic implementation, without any indexes or other
+ * optimizations.
+ *
+ * @author reto
+ */
+public class SimpleGraph extends AbstractGraph {
+
+    final Set<Triple> triples;
+
+    private boolean checkConcurrency = false;
+
+    class SimpleIterator implements Iterator<Triple> {
+
+        private Iterator<Triple> listIter;
+        private boolean isValid = true;
+
+        public SimpleIterator(Iterator<Triple> listIter) {
+            this.listIter = listIter;
+        }
+        private Triple currentNext;
+
+        @Override
+        public boolean hasNext() {
+            checkValidity();
+            return listIter.hasNext();
+        }
+
+        @Override
+        public Triple next() {
+            checkValidity();
+            currentNext = listIter.next();
+            return currentNext;
+        }        
+
+        @Override
+        public void remove() {
+            checkValidity();
+            listIter.remove();
+            triples.remove(currentNext);            
+            invalidateIterators(this);            
+        }
+
+        private void checkValidity() throws ConcurrentModificationException {
+            if (checkConcurrency && !isValid) {
+                throw new ConcurrentModificationException();
+            }
+        }
+
+        private void invalidate() {
+            isValid = false;
+        }
+    }    
+    
+    private final Set<SoftReference<SimpleIterator>> iterators =
+            Collections.synchronizedSet(new HashSet<SoftReference<SimpleIterator>>());
+    
+    /**
+     * Creates an empty SimpleGraph
+     */
+    public SimpleGraph() {
+        triples = Collections.synchronizedSet(new HashSet<Triple>());
+    }
+
+    /**
+     * Creates a SimpleGraph using the passed iterator, the iterator 
+     * is consumed before the constructor returns
+     * 
+     * @param iterator
+     */
+    public SimpleGraph(Iterator<Triple> iterator) {
+        triples = new HashSet<Triple>();
+        while (iterator.hasNext()) {
+            Triple triple = iterator.next();
+            triples.add(triple);
+        }
+    }
+
+    /**
+     * Creates a SimpleGraph for the specified set of triples, 
+     * subsequent modification of baseSet do affect the created instance.
+     * 
+     * @param baseSet
+     */
+    public SimpleGraph(Set<Triple> baseSet) {
+        this.triples = baseSet;
+    }
+
+    /**
+     * Creates a SimpleGraph for the specified collection of triples,
+     * subsequent modification of baseSet do not affect the created instance.
+     *
+     * @param baseSet
+     */
+    public SimpleGraph(Collection<Triple> baseCollection) {
+        this.triples = new HashSet<Triple>(baseCollection);
+    }
+
+    @Override
+    public int performSize() {
+        return triples.size();
+    }
+
+    @Override
+    public Iterator<Triple> performFilter(final BlankNodeOrIri subject, final Iri predicate, final RdfTerm object) {
+        final List<Triple> tripleList = new ArrayList<Triple>();
+        synchronized (triples) {
+            Iterator<Triple> baseIter = triples.iterator();
+            while (baseIter.hasNext()) {
+                Triple triple = baseIter.next();
+                if ((subject != null)
+                        && (!triple.getSubject().equals(subject))) {
+                    continue;
+                }
+                if ((predicate != null)
+                        && (!triple.getPredicate().equals(predicate))) {
+                    continue;
+                }
+                if ((object != null)
+                        && (!triple.getObject().equals(object))) {
+                    continue;
+                }
+                tripleList.add(triple);
+            }
+
+            final Iterator<Triple> listIter = tripleList.iterator();
+            SimpleIterator resultIter = new SimpleIterator(listIter);
+            if (checkConcurrency) {
+                iterators.add(new SoftReference<SimpleIterator>(resultIter));
+            }
+            return resultIter;
+        }
+    }
+
+
+    @Override
+    public boolean performAdd(Triple e) {
+        boolean modified = triples.add(e);
+        if (modified) {
+            invalidateIterators(null);
+        }
+        return modified;
+    }
+    
+    private void invalidateIterators(SimpleIterator caller) {
+        if (!checkConcurrency) {
+            return;
+        }
+        Set<SoftReference> oldReferences = new HashSet<SoftReference>();
+        synchronized(iterators) {
+            for (SoftReference<SimpleGraph.SimpleIterator> softReference : iterators) {
+                SimpleIterator simpleIterator = softReference.get();
+                if (simpleIterator == null) {
+                    oldReferences.add(softReference);
+                    continue;
+                }
+                if (simpleIterator != caller) {
+                    simpleIterator.invalidate();
+                }
+            }
+        }
+        iterators.removeAll(oldReferences);
+    }
+
+    /**
+     * Specifies whether or not to throw <code>ConcurrentModificationException</code>s,
+     * if this simple triple collection is modified concurrently. Concurrency
+     * check is set to false by default.
+     *
+     * @param bool Specifies whether or not to check concurrent modifications.
+     */
+    public void setCheckConcurrency(boolean bool) {
+        checkConcurrency = bool;
+    }
+    
+    
+    @Override
+    public ImmutableGraph getImmutableGraph() {
+        return new SimpleImmutableGraph(this);
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleImmutableGraph.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleImmutableGraph.java
new file mode 100644
index 0000000..bc50a09
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleImmutableGraph.java
@@ -0,0 +1,79 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import org.apache.commons.rdf.impl.utils.AbstractImmutableGraph;
+import java.util.Iterator;
+
+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;
+
+/**
+ *
+ * @author reto
+ */
+public class SimpleImmutableGraph extends AbstractImmutableGraph {
+
+    private Graph graph;
+    
+    /**
+     * Creates a ImmutableGraph with the triples in Graph
+     * 
+     * @param Graph the collection of triples this ImmutableGraph shall consist of
+     */
+    public SimpleImmutableGraph(Graph Graph) {
+        this.graph = new SimpleGraph(Graph.iterator());
+    }
+
+    /**
+     * Creates a ImmutableGraph with the triples in Graph.
+     *
+     * This construction allows to specify if the Graph might change
+     * in future. If GraphWillNeverChange is set to true it will
+     * assume that the collection never changes, in this case the collection
+     * isn't copied making things more efficient.
+     *
+     * @param Graph the collection of triples this ImmutableGraph shall consist of
+     * @param GraphWillNeverChange true if the caller promises Graph will never change
+     */
+    public SimpleImmutableGraph(Graph Graph, boolean GraphWillNeverChange) {
+        if (!GraphWillNeverChange) {
+            this.graph = new SimpleGraph(Graph.iterator());
+        } else {
+            this.graph = Graph;
+        }
+    }
+    
+    public SimpleImmutableGraph(Iterator<Triple> tripleIter) {
+        this.graph = new SimpleGraph(tripleIter);
+    }
+
+    @Override
+    public int performSize() {
+        return graph.size();
+    }
+
+    @Override
+    public Iterator<Triple> performFilter(BlankNodeOrIri subject, Iri predicate, RdfTerm object) {
+        return graph.filter(subject, predicate, object);
+    }
+}
diff --git a/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleMGraph.java b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleMGraph.java
new file mode 100644
index 0000000..8d0a5ce
--- /dev/null
+++ b/impl.utils/src/main/java/org/apache/commons/rdf/impl/utils/simple/SimpleMGraph.java
@@ -0,0 +1,57 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.rdf.ImmutableGraph;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Triple;
+
+/**
+ *
+ * @deprecated Use SimpleGraph
+ * @author reto
+ */
+@Deprecated
+public class SimpleMGraph extends SimpleGraph implements Graph {
+
+    /**
+     * Creates an empty SimpleMGraph
+     */
+    public SimpleMGraph() {
+    }
+
+    public SimpleMGraph(Set<Triple> baseSet) {
+        super(baseSet);
+    }
+
+    public SimpleMGraph(Collection<Triple> baseCollection) {
+        super(baseCollection);
+    }
+
+    public SimpleMGraph(Iterator<Triple> iterator) {
+        super(iterator);
+    }
+
+}
+
+    
\ No newline at end of file
diff --git a/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/PlainLiteralImplTest.java b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/PlainLiteralImplTest.java
new file mode 100644
index 0000000..2782f45
--- /dev/null
+++ b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/PlainLiteralImplTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
+import org.junit.Test;
+
+import org.apache.commons.rdf.Language;
+import org.apache.commons.rdf.Literal;
+import org.junit.Assert;
+/**
+ *
+ * @author reto
+ *
+ */
+
+public class PlainLiteralImplTest {
+
+    
+    @Test public void plainLiteralEquality() {
+        String stringValue = "some text";
+        Literal literal1 = new PlainLiteralImpl(stringValue);
+        Literal literal2 = new PlainLiteralImpl(stringValue);        
+        Assert.assertEquals(literal1, literal2);
+        Assert.assertEquals(literal1.hashCode(), literal2.hashCode());
+        Literal literal3 = new PlainLiteralImpl("something else");
+        Assert.assertFalse(literal1.equals(literal3));
+    }
+    
+    @Test public void languageLiteralEquality() {
+        String stringValue = "some text";
+        Language lang = new Language("en-ca");
+        Literal literal1 = new PlainLiteralImpl(stringValue, lang);
+        Literal literal2 = new PlainLiteralImpl(stringValue, lang);        
+        Assert.assertEquals(literal1, literal2);
+        Assert.assertEquals(literal1.hashCode(), literal2.hashCode());
+        Language lang2 = new Language("de");
+        Literal literal3 = new PlainLiteralImpl(stringValue, lang2);
+        Assert.assertFalse(literal1.equals(literal3));
+        Literal literal4 = new PlainLiteralImpl(stringValue, null);
+        Assert.assertFalse(literal3.equals(literal4));
+        Assert.assertFalse(literal4.equals(literal3));
+    }
+
+    /**
+     * hashCode of the lexical form plus the hashCode of the locale
+     */
+    @Test public void checkHashCode() {
+        String stringValue = "some text";
+        Language language = new Language("en");
+        Literal literal = new PlainLiteralImpl(stringValue, language);
+        Assert.assertEquals(literal.getDataType().hashCode() + stringValue.hashCode() + language.hashCode(), literal.hashCode());
+    }
+
+}
diff --git a/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraphTest.java b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraphTest.java
new file mode 100644
index 0000000..a1e8d54
--- /dev/null
+++ b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/SimpleGraphTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.commons.rdf.Triple;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
+
+/**
+ *
+ * @author mir
+ */
+public class SimpleGraphTest {
+
+    private Iri uriRef1 = new Iri("http://example.org/foo");
+    private Iri uriRef2 = new Iri("http://example.org/bar");
+    private Iri uriRef3 = new Iri("http://example.org/test");
+    private Triple triple1 = new TripleImpl(uriRef1, uriRef2, uriRef3);
+    private Triple triple2 = new TripleImpl(uriRef2, uriRef2, uriRef1);
+    private Triple triple3 = new TripleImpl(uriRef3, uriRef1, uriRef3);
+    private Triple triple4 = new TripleImpl(uriRef1, uriRef3, uriRef2);
+    private Triple triple5 = new TripleImpl(uriRef2, uriRef3, uriRef2);
+        
+    @Test
+    public void iteratorRemove() {
+        SimpleGraph stc = new SimpleGraph();
+        stc.add(triple1);
+        stc.add(triple2);
+        stc.add(triple3);
+        stc.add(triple4);
+        stc.add(triple5);
+        Iterator<Triple> iter = stc.iterator();
+        while (iter.hasNext()) {
+            Triple triple = iter.next();
+            iter.remove();
+        }
+        Assert.assertEquals(0, stc.size());
+    }
+
+    @Test
+    public void removeAll() {
+        SimpleGraph stc = new SimpleGraph();
+        stc.add(triple1);
+        stc.add(triple2);
+        stc.add(triple3);
+        stc.add(triple4);
+        stc.add(triple5);
+        SimpleGraph stc2 = new SimpleGraph();
+        stc2.add(triple1);
+        stc2.add(triple3);
+        stc2.add(triple5);
+        stc.removeAll(stc2);
+        Assert.assertEquals(2, stc.size());
+    }
+    
+    @Test
+    public void filterIteratorRemove() {
+        SimpleGraph stc = new SimpleGraph();
+        stc.add(triple1);
+        stc.add(triple2);
+        stc.add(triple3);
+        stc.add(triple4);
+        stc.add(triple5);        
+        Iterator<Triple> iter = stc.filter(uriRef1, null, null);
+        while (iter.hasNext()) {
+            Triple triple = iter.next();
+            iter.remove();
+        }
+        Assert.assertEquals(3, stc.size());
+    }
+
+    @Test(expected=ConcurrentModificationException.class)
+    public void remove() {
+        SimpleGraph stc = new SimpleGraph();
+        stc.setCheckConcurrency(true);
+        stc.add(triple1);
+        stc.add(triple2);
+        stc.add(triple3);
+        stc.add(triple4);
+        stc.add(triple5);
+        Iterator<Triple> iter = stc.filter(uriRef1, null, null);
+        while (iter.hasNext()) {
+            Triple triple = iter.next();
+            stc.remove(triple);
+        }
+        Assert.assertEquals(3, stc.size());
+    }
+}
diff --git a/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TripleImplTest.java b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TripleImplTest.java
new file mode 100644
index 0000000..dd2f967
--- /dev/null
+++ b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TripleImplTest.java
@@ -0,0 +1,57 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.apache.commons.rdf.impl.utils.simple;
+/*
+ *
+ * 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.junit.Test;
+import junit.framework.Assert;
+
+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.PlainLiteralImpl;
+import org.apache.commons.rdf.impl.utils.TripleImpl;
+/**
+ *
+ * @author reto
+ *
+ */
+
+public class TripleImplTest {
+    
+    
+    @Test public void tripleEquality() {
+        BlankNodeOrIri subject = new Iri("http://example.org/");
+        Iri predicate = new Iri("http://example.org/property");
+        RdfTerm object = new PlainLiteralImpl("property value");
+        Triple triple1 = new TripleImpl(subject, predicate, object);
+        Triple triple2 = new TripleImpl(subject, predicate, object);
+        Assert.assertEquals(triple1.hashCode(), triple2.hashCode());
+        Assert.assertEquals(triple1, triple2);    
+    }
+
+}
diff --git a/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TypedLiteralImplTest.java b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TypedLiteralImplTest.java
new file mode 100644
index 0000000..515cf93
--- /dev/null
+++ b/impl.utils/src/test/java/org/apache/commons/rdf/impl/utils/simple/TypedLiteralImplTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.commons.rdf.impl.utils.simple;
+
+import org.apache.commons.rdf.impl.utils.TypedLiteralImpl;
+import org.junit.Test;
+import junit.framework.Assert;
+
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.Literal;
+/**
+ *
+ * @author reto/**
+ *
+ * @author reto/**
+ *
+ * @author reto/**
+ *
+ * @author reto
+ *
+ */
+
+public class TypedLiteralImplTest {
+    
+    
+    @Test public void typedLiteralEquality() {
+        String stringValue = "some text";
+        Iri uriRef = new Iri("http://example.org/datatypes/magic");
+        Literal literal1 = new TypedLiteralImpl(stringValue, uriRef);
+        Literal literal2 = new TypedLiteralImpl(stringValue, uriRef);        
+        Assert.assertEquals(literal1, literal2);
+        Assert.assertEquals(literal1.hashCode(), literal2.hashCode());
+        Literal literal3 = new TypedLiteralImpl("something else", uriRef);
+        Assert.assertFalse(literal1.equals(literal3));
+        Iri uriRef2 = new Iri("http://example.org/datatypes/other");
+        Literal literal4 = new TypedLiteralImpl(stringValue, uriRef2);
+        Assert.assertFalse(literal1.equals(literal4));
+    }
+
+
+    /**
+     * The hascode is equals to the hascode of the lexical form plus the hashcode of the dataTyp
+     */
+    @Test public void checkHashCode() {
+        String stringValue = "some text";
+        Iri uriRef = new Iri("http://example.org/datatypes/magic");
+        Literal literal =  new TypedLiteralImpl(stringValue, uriRef);
+        Assert.assertEquals(stringValue.hashCode() + uriRef.hashCode(), literal.hashCode());
+    }
+
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0455274
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+   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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-parent</artifactId>
+        <version>36</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>commons-rdf</groupId>
+    <artifactId>commons-rdf</artifactId>
+    <packaging>pom</packaging>
+    <version>0.1-SNAPSHOT</version>
+    <name>Apache Commons RDF Reactor</name>
+    <description>
+        Apache Commons RDF provides an API modelling the RDF data model as defined by 
+        http://www.w3.org/TR/rdf11-concepts/
+    </description>
+    <url>http://commons.apache.org/sandbox/commons-rdf/</url>
+    <!-- TBD
+    <issueManagement>
+        <system>jira</system>
+        <url>http://issues.apache.org/jira/browse/RDF</url>
+    </issueManagement>
+    -->
+    <inceptionYear>2014</inceptionYear>
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/rdf/trunk</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/rdf/trunk</developerConnection>
+        <url>http://svn.apache.org/viewvc/commons/proper/rdf/trunk</url>
+    </scm>
+
+
+    <distributionManagement>
+        <site>
+            <id>apache.website</id>
+            <name>Apache Commons Site</name>
+            <url>${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid}</url>
+        </site>
+    </distributionManagement>
+
+    <modules>
+        <module>api</module>
+        <module>impl.utils</module>
+        <module>impl.sparql</module>
+    </modules>
+
+</project>
diff --git a/report.xml b/report.xml
new file mode 100644
index 0000000..d64d43c
--- /dev/null
+++ b/report.xml
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<dfxml xmloutputversion='1.0'>
+  <metadata 
+  xmlns='http://afflib.org/tcpflow/' 
+  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
+  xmlns:dc='http://purl.org/dc/elements/1.1/'>
+    <dc:type>Feature Extraction</dc:type>
+  </metadata>
+  <creator version='1.0'>
+    <program>TCPFLOW</program>
+    <version>1.4.4</version>
+    <build_environment>
+      <compiler>4.8.2 (4.8.2 20140110 (prerelease) [ibm/gcc-4_8-branch merged from gcc-4_8-branch, revision 205847])</compiler>
+      <CPPFLAGS>-pthread -I/usr/local/include -D_FORTIFY_SOURCE=2 -DUTC_OFFSET=+0000 </CPPFLAGS>
+      <CFLAGS>-g   -pthread -g -O3 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -MD -D_FORTIFY_SOURCE=2 -Wpointer-arith -Wmissing-declarations -Wmissing-prototypes -Wshadow -Wwrite-strings -Wcast-align -Waggregate-return -Wbad-function-cast -Wcast-qual -Wundef -Wredundant-decls -Wdisabled-optimization -Wfloat-equal -Wmultichar -Wc++-compat -Wmissing-noreturn -Wall -Wstrict-prototypes</CFLAGS>
+      <CXXFLAGS>-g -pthread -g -O3 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -std=c++11 -Wall -MD -D_FORTIFY_SOURCE=2 -Wpointer-arith -Wshadow -Wwrite-strings -Wcast-align -Wredundant-decls -Wdisabled-optimization -Wfloat-equal -Wmultichar -Wmissing-noreturn -Woverloaded-virtual -Wsign-promo -funit-at-a-time -Wstrict-null-sentinel -Weffc++ </CXXFLAGS>
+      <LDFLAGS>-L/usr/local/lib -Wl,-Bsymbolic-functions -Wl,-z,relro</LDFLAGS>
+      <LIBS>-lpcap -lcairo -lfontconfig -lfreetype -lpixman-1 -lexpat  -lssl -lcrypto -lz -lssl -lcrypto </LIBS>
+      <compilation_date>2014-01-13T17:14:40</compilation_date>
+      <library name="boost" version="105400"/>
+    </build_environment>
+    <execution_environment>
+      <os_sysname>Linux</os_sysname>
+      <os_release>3.13.0-45-generic</os_release>
+      <os_version>#74-Ubuntu SMP Tue Jan 13 19:36:28 UTC 2015</os_version>
+      <host>f3addd37b525</host>
+      <arch>x86_64</arch>
+      <command_line>tcpflow -i lo -c port 3333</command_line>
+      <uid>0</uid>
+      <start_time>2015-02-15T17:15:22Z</start_time>
+    </execution_environment>
+  </creator>
+  <configuration>
+  </configuration>
+  <tdelta>0</tdelta>