You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2013/02/19 13:57:40 UTC

[7/11] added missing module from the previous code importation

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/FunctionSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/FunctionSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/FunctionSelector.java
new file mode 100644
index 0000000..55619fd
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/FunctionSelector.java
@@ -0,0 +1,151 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.functions.NodeFunction;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class FunctionSelector<Node> implements NodeSelector<Node> {
+
+    private List<NodeSelector<Node>> selectors;
+    private NodeFunction<Collection<Node>,Node> function;
+
+
+    public FunctionSelector(NodeFunction<Collection<Node>,Node> function, List<NodeSelector<Node>> selectors) {
+        this.function  = function;
+        this.selectors = selectors;
+    }
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> nodeRDFBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+        ArrayList<Collection<Node>> args = new ArrayList<Collection<Node>>();
+
+        // for a function, we include in the result path all paths to all arguments, so we create a new map to collect the paths
+        Map<Node, List<Node>> myResultPaths = null;
+        if(resultPaths != null && path != null) {
+            myResultPaths = new HashMap<Node, List<Node>>();
+        }
+
+        for(NodeSelector<Node> selector : selectors) {
+            Collection<Node> param = selector.select(nodeRDFBackend, context, path, myResultPaths);
+            args.add(param);
+        }
+        @SuppressWarnings("unchecked")
+        Collection<Node> result = function.apply(nodeRDFBackend, context, args.toArray(new Collection[selectors.size()]));
+        if(myResultPaths != null && path != null) {
+            // for a function, we include in the result path all paths to all arguments ...
+            List<Node> functionPath = new ArrayList<Node>();
+            for(List<Node> subpath : myResultPaths.values()) {
+                for(Node n : subpath) {
+                    if(!functionPath.contains(n)) {
+                        functionPath.add(n);
+                    }
+                }
+            }
+
+            for(Node n : result) {
+                resultPaths.put(n,functionPath);
+            }
+        }
+        return result;
+    }
+
+
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @return
+     * @param backend
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> backend) {
+        final StringBuilder format = new StringBuilder();
+        format.append(String.format("fn:%s(", function.getPathExpression(backend)));
+        boolean first = true;
+        for (NodeSelector<Node> ns : selectors) {
+            if (!first) {
+                format.append(", ");
+            }
+            format.append(ns.getPathExpression(backend));
+            first = false;
+        }
+        return format.append(")").toString();
+    }
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        throw new UnsupportedOperationException("cannot use functions in unnamed field definitions because the name is ambiguous");
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("unchecked")
+        FunctionSelector<Node> that = (FunctionSelector<Node>) o;
+
+        if (function != null ? !function.equals(that.function) : that.function != null) {
+            return false;
+        }
+        if (selectors != null ? !selectors.equals(that.selectors) : that.selectors != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = selectors != null ? selectors.hashCode() : 0;
+        result = 31 * result + (function != null ? function.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/IntersectionSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/IntersectionSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/IntersectionSelector.java
new file mode 100644
index 0000000..7d30c21
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/IntersectionSelector.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class IntersectionSelector<Node> implements NodeSelector<Node> {
+
+	private NodeSelector<Node> left;
+	private NodeSelector<Node> right;
+
+	public IntersectionSelector(NodeSelector<Node> left, NodeSelector<Node> right) {
+		this.left = left;
+		this.right = right;
+	}
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> nodeRDFBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+		return Sets.intersection(
+				ImmutableSet.copyOf(left.select(nodeRDFBackend,context,path,resultPaths)),
+				ImmutableSet.copyOf(right.select(nodeRDFBackend,context,path,resultPaths))
+		);
+	}
+
+	@Override
+	public String getPathExpression(RDFBackend<Node> backend) {
+		return String.format("(%s & %s)", left.getPathExpression(backend), right.getPathExpression(backend));
+	}
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        throw new UnsupportedOperationException("cannot use intersections in unnamed field definitions because the name is ambiguous");
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("unchecked")
+		IntersectionSelector<Node> that = (IntersectionSelector<Node>) o;
+
+        if (left != null ? !left.equals(that.left) : that.left != null) return false;
+        if (right != null ? !right.equals(that.right) : that.right != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left != null ? left.hashCode() : 0;
+        result = 31 * result + (right != null ? right.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PathSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PathSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PathSelector.java
new file mode 100644
index 0000000..41e2da6
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PathSelector.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Traverse a path by following several edges in the RDF graph. Each step is separated by a "/".
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class PathSelector<Node> implements NodeSelector<Node> {
+
+    private NodeSelector<Node> left;
+    private NodeSelector<Node> right;
+
+    public PathSelector(NodeSelector<Node> left, NodeSelector<Node> right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to and including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> rdfBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+        // a new map for storing the result path for the left selector
+        Map<Node,List<Node>> myResultPaths = null;
+        if(resultPaths != null && path != null) {
+            myResultPaths = new HashMap<Node, List<Node>>();
+        }
+        
+        Collection<Node> nodesLeft = left.select(rdfBackend,context,path,myResultPaths);
+        final Set<Node> result = new HashSet<Node>();
+
+        
+        
+        for(Node n : nodesLeft) {
+            // new path is the path resulting from selecting the context node in the left selector
+            if(myResultPaths != null && myResultPaths.get(n) != null) {
+                result.addAll(right.select(rdfBackend,n,myResultPaths.get(n),resultPaths));
+            } else {
+                result.addAll(right.select(rdfBackend,n,null,null));
+            }
+        }
+        return result;
+    }
+
+
+    @Override
+    public String getPathExpression(RDFBackend<Node> backend) {
+        return String.format("%s / %s", left.getPathExpression(backend), right.getPathExpression(backend));
+    }
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        return left.getName(nodeRDFBackend);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("rawtypes")
+		PathSelector that = (PathSelector) o;
+
+        if (left != null ? !left.equals(that.left) : that.left != null) return false;
+        if (right != null ? !right.equals(that.right) : that.right != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left != null ? left.hashCode() : 0;
+        result = 31 * result + (right != null ? right.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PropertySelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PropertySelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PropertySelector.java
new file mode 100644
index 0000000..7f1aaf9
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/PropertySelector.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A path definition selecting the value of a property. Either a URI enclosed in <> or a namespace prefix and a
+ * local name separated by ":"
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class PropertySelector<Node> implements NodeSelector<Node> {
+
+	private Node property;
+
+
+	public PropertySelector(Node property) {
+		this.property = property;
+	}
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> rdfBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+		if(rdfBackend.isURI(context) || rdfBackend.isBlank(context)) {
+            if(path != null && resultPaths != null) {
+                Collection<Node> results = rdfBackend.listObjects(context,property);
+                for(Node n : results) {
+                    resultPaths.put(n, new ImmutableList.Builder<Node>().addAll(path).add(context).add(n).build());
+                }
+                return results;
+            } else {
+			    return rdfBackend.listObjects(context,property);
+            }
+		} else {
+			return Collections.emptyList();
+		}
+	}
+
+	@Override
+	public String getPathExpression(RDFBackend<Node> backend) {
+		if (property != null) {
+			return String.format("<%s>", backend.stringValue(property));
+		} else {
+			return "*";
+		}
+	}
+
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> backend) {
+        if(property != null) {
+            return backend.stringValue(property);
+        } else {
+            throw new UnsupportedOperationException("cannot use wildcards in unnamed field definitions because the name is undefined");
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("rawtypes")
+		PropertySelector that = (PropertySelector) o;
+
+        if (property != null ? !property.equals(that.property) : that.property != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return property != null ? property.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/RecursivePathSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/RecursivePathSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/RecursivePathSelector.java
new file mode 100644
index 0000000..a054452
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/RecursivePathSelector.java
@@ -0,0 +1,175 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import com.google.common.collect.ImmutableList;
+
+import java.util.*;
+
+public class RecursivePathSelector<Node> implements NodeSelector<Node> {
+
+	private final NodeSelector<Node> delegate;
+	private final int minRecursions, maxRecursions;
+
+	public RecursivePathSelector(NodeSelector<Node> delegate, int min, int max) {
+		this.delegate = delegate;
+		minRecursions = min;
+		maxRecursions = max;
+	}
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> rdfBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+		Set<Node> result = new HashSet<Node>();
+
+		if (minRecursions <= 0) {
+			result.add(context);
+		}
+		subSelect(context, 0, rdfBackend, result,path,resultPaths);
+
+		return result;
+	}
+
+	private void subSelect(Node currentContext, int depth, RDFBackend<Node> rdfBackend, Set<Node> resultSet, List<Node> path, Map<Node, List<Node>> resultPaths) {
+		Collection<Node> nextNodes = delegate.select(rdfBackend, currentContext,path,resultPaths);
+		depth++;
+		for (Node n : nextNodes) {
+			if (!resultSet.contains(n)) {
+				if (depth >= minRecursions){
+					resultSet.add(n);
+				}
+				if (depth < maxRecursions) {
+                    if(path != null && resultPaths != null) {
+					    subSelect(n, depth, rdfBackend, resultSet, new ImmutableList.Builder<Node>().addAll(path).add(currentContext).build(),resultPaths);
+                    } else {
+                        subSelect(n, depth, rdfBackend, resultSet, null,resultPaths);
+                    }
+				}
+			}
+		}
+	}
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+    	if (maxRecursions != Integer.MAX_VALUE) {
+    		if (minRecursions <= 0) {
+    	    	return String.format("(%s){,%d}", delegate.getPathExpression(rdfBackend), maxRecursions);
+    		} else {
+    	    	return String.format("(%s){%d,%d}", delegate.getPathExpression(rdfBackend), minRecursions, maxRecursions);
+    		}
+    	} else {
+    		if (minRecursions <= 0) {
+    	    	return String.format("(%s)*", delegate.getPathExpression(rdfBackend));
+    		} else if (minRecursions == 1) {
+    	    	return String.format("(%s)+", delegate.getPathExpression(rdfBackend));
+    		} else {
+    	    	return String.format("(%s){%d,}", delegate.getPathExpression(rdfBackend), minRecursions);
+    		}
+    	}
+	}
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        return delegate.getName(nodeRDFBackend);
+    }
+
+    /**
+     * <code>(delegate)*</code>
+     * @param delegate the delegate
+     */
+    public static <N> RecursivePathSelector<N> getPathSelectorStared(NodeSelector<N> delegate) {
+    	return new RecursivePathSelector<N>(delegate, 0, Integer.MAX_VALUE);
+    }
+
+    /**
+     * <code>(delegate)+</code>
+     * @param delegate the delegate
+     */
+    public static <N> RecursivePathSelector<N> getPathSelectorPlused(NodeSelector<N> delegate) {
+    	return new RecursivePathSelector<N>(delegate, 1, Integer.MAX_VALUE);
+    }
+    
+    /**
+     * <code>(delegate){m,}</code>
+     * @param delegate the delegate
+     * @param minBound <code>m</code>
+     */
+    public static <N> RecursivePathSelector<N> getPathSelectorMinBound(NodeSelector<N> delegate, int minBound) {
+    	return new RecursivePathSelector<N>(delegate, minBound, Integer.MAX_VALUE);
+    }
+
+    /**
+     * <code>(delegate){,n}</code>
+     * @param delegate the delegate
+     * @param maxBound <code>n</code>
+     */
+    public static <N> RecursivePathSelector<N> getPathSelectorMaxBound(NodeSelector<N> delegate, int maxBound) {
+    	return new RecursivePathSelector<N>(delegate, 0, maxBound);
+    }
+
+    /**
+     * <code>(delegate){m,n}</code>
+     * @param delegate the delegate
+     * @param minBound <code>m</code>
+     * @param maxBound <code>n</code>
+     */
+    public static <N> RecursivePathSelector<N> getPathSelectorMinMaxBound(NodeSelector<N> delegate, int minBound, int maxBound) {
+    	return new RecursivePathSelector<N>(delegate, minBound, maxBound);
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("unchecked")
+		RecursivePathSelector<Node> that = (RecursivePathSelector<Node>) o;
+
+        if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate != null ? delegate.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/ReversePropertySelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/ReversePropertySelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/ReversePropertySelector.java
new file mode 100644
index 0000000..a4e1d0b
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/ReversePropertySelector.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Perform a reverse navigation step over the property wrapped by this selector
+ *
+ * @param <Node>
+ */
+public class ReversePropertySelector<Node> implements NodeSelector<Node> {
+
+	private final Node property;
+
+	public ReversePropertySelector(Node property) {
+		this.property = property;
+	}
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> rdfBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+        if(rdfBackend.isURI(context) || rdfBackend.isBlank(context)) {
+            if(path != null && resultPaths != null) {
+                Collection<Node> results = rdfBackend.listSubjects(context, property);
+                for(Node n :results) {
+                    resultPaths.put(n, new ImmutableList.Builder<Node>().addAll(path).add(context).add(n).build());
+                }
+                return results;
+            } else {
+			    return rdfBackend.listSubjects(property, context);
+            }
+		} else {
+			return Collections.emptyList();
+		}
+	}
+
+	@Override
+	public String getPathExpression(RDFBackend<Node> backend) {
+		if (property != null) {
+			return String.format("^<%s>", backend.stringValue(property));
+		} else {
+			return "^*";
+		}
+	}
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        return nodeRDFBackend.stringValue(property);
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("rawtypes")
+		ReversePropertySelector that = (ReversePropertySelector) o;
+
+        if (property != null ? !property.equals(that.property) : that.property != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return property != null ? property.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/SelfSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/SelfSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/SelfSelector.java
new file mode 100644
index 0000000..cfe3406
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/SelfSelector.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author Jakob Frank <ja...@salzburgresearch.at>
+ * 
+ */
+public class SelfSelector<Node> implements NodeSelector<Node> {
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> nodeRDFBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+        return Collections.singleton(context);
+    }
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return ".";
+    }
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        throw new UnsupportedOperationException("cannot use self selections in unnamed field definitions because the name is ambiguous");
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/StringConstantSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/StringConstantSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/StringConstantSelector.java
new file mode 100644
index 0000000..e46399e
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/StringConstantSelector.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class StringConstantSelector<Node> implements NodeSelector<Node> {
+
+	private String constant;
+
+	public StringConstantSelector(String constant) {
+		this.constant = constant;
+	}
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(RDFBackend<Node> rdfBackend, Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+		return Collections.singleton(rdfBackend.createLiteral(constant));
+	}
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+		return String.format("\"%s\"", constant);
+	}
+
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        return constant;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("rawtypes")
+		StringConstantSelector that = (StringConstantSelector) o;
+
+        if (constant != null ? !constant.equals(that.constant) : that.constant != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return constant != null ? constant.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/TestingSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/TestingSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/TestingSelector.java
new file mode 100644
index 0000000..457033b
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/TestingSelector.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A node selector that wraps a node test around the selection and delegates the selection to another selector.
+ * The result set will be filtered based on the node test.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class TestingSelector<Node> implements NodeSelector<Node> {
+
+    private NodeSelector<Node> delegate;
+    private NodeTest<Node> test;
+
+
+    public TestingSelector(NodeSelector<Node> delegate, NodeTest<Node> test) {
+        this.delegate = delegate;
+        this.test = test;
+    }
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(final RDFBackend<Node> rdfBackend, final Node context, List<Node> path, Map<Node, List<Node>> resultPaths) {
+        Predicate<Node> predicate = new Predicate<Node>() {
+            @Override
+            public boolean apply(Node input) {
+                return test.accept(rdfBackend, context, input);
+            }
+        };
+
+        // TODO: maybe the result paths should also include the test?
+
+        return Collections2.filter(delegate.select(rdfBackend,context,path,resultPaths),predicate);
+    }
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return String.format("%s[%s]", delegate.getPathExpression(rdfBackend), test.getPathExpression(rdfBackend));
+    }
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        return delegate.getName(nodeRDFBackend);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        TestingSelector that = (TestingSelector) o;
+
+        if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) {
+            return false;
+        }
+        if (test != null ? !test.equals(that.test) : that.test != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = delegate != null ? delegate.hashCode() : 0;
+        result = 31 * result + (test != null ? test.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/UnionSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/UnionSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/UnionSelector.java
new file mode 100644
index 0000000..6869ef5
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/UnionSelector.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builds the union of two node selectors. Will eliminate duplicates.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class UnionSelector<Node> implements NodeSelector<Node> {
+
+    private NodeSelector<Node> left;
+    private NodeSelector<Node> right;
+
+    public UnionSelector(NodeSelector<Node> left, NodeSelector<Node> right) {
+        this.left = left;
+        this.right = right;
+    }
+
+
+    /**
+     * Apply the selector to the context node passed as argument and return the collection
+     * of selected nodes in appropriate order.
+     *
+     * @param context     the node where to start the selection
+     * @param path        the path leading to but not including the context node in the current evaluation of LDPath; may be null,
+     *                    in which case path tracking is disabled
+     * @param resultPaths a map where each of the result nodes maps to a path leading to the result node in the LDPath evaluation;
+     *                    if null, path tracking is disabled and the path argument is ignored
+     * @return the collection of selected nodes
+     */
+    @Override
+    public Collection<Node> select(final RDFBackend<Node> rdfBackend, final Node context, final List<Node> path, final Map<Node, List<Node>> resultPaths) {
+        final Set<Node> result = new HashSet<Node>();
+
+        result.addAll(left.select(rdfBackend,context,path,resultPaths));
+        result.addAll(right.select(rdfBackend,context,path,resultPaths));
+        return result;
+    }
+
+    /**
+     * Return the name of the NodeSelector for registration in the selector registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return String.format("(%s | %s)", left.getPathExpression(rdfBackend), right.getPathExpression(rdfBackend));
+    }
+
+    /**
+     * Return a name for this selector to be used as the name for the whole path if not explicitly
+     * specified. In complex selector expressions, this is typically delegated to the first
+     * occurrence of an atomic selector.
+     */
+    @Override
+    public String getName(RDFBackend<Node> nodeRDFBackend) {
+        throw new UnsupportedOperationException("cannot use unions in unnamed field definitions because the name is ambiguous");
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        @SuppressWarnings("rawtypes")
+		UnionSelector that = (UnionSelector) o;
+
+        if (left != null ? !left.equals(that.left) : that.left != null) return false;
+        if (right != null ? !right.equals(that.right) : that.right != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left != null ? left.hashCode() : 0;
+        result = 31 * result + (right != null ? right.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/WildcardSelector.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/WildcardSelector.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/WildcardSelector.java
new file mode 100644
index 0000000..1e62358
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/selectors/WildcardSelector.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.selectors;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+
+/**
+ * A property selector that will match with any property
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class WildcardSelector<Node> extends PropertySelector<Node> implements NodeSelector<Node> {
+
+	public WildcardSelector() {
+		super(null);
+	}
+
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+		return "*";
+	}
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/AndTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/AndTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/AndTest.java
new file mode 100644
index 0000000..e37ebd5
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/AndTest.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+/**
+ * Tests the conjunction of two tests.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class AndTest<Node> extends ComplexTest<Node> {
+
+    private NodeTest<Node> left;
+    private NodeTest<Node> right;
+
+
+    public AndTest(NodeTest<Node> left, NodeTest<Node> right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node args) throws IllegalArgumentException {
+        return left.accept(rdfBackend, context, args) && right.accept(rdfBackend, context, args);
+    }
+
+    /**
+     * Return the name of the NodeFunction for registration in the function registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return String.format("%s & %s", left.getPathExpression(rdfBackend), right.getPathExpression(rdfBackend));
+    }
+
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "(left  & right ) :: (Boolean, Boolean) -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests the conjunction of two tests";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        AndTest andTest = (AndTest) o;
+
+        if (left != null ? !left.equals(andTest.left) : andTest.left != null) {
+            return false;
+        }
+        if (right != null ? !right.equals(andTest.right) : andTest.right != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left != null ? left.hashCode() : 0;
+        result = 31 * result + (right != null ? right.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/ComplexTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/ComplexTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/ComplexTest.java
new file mode 100644
index 0000000..4a2e4f8
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/ComplexTest.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+public abstract class ComplexTest<Node> extends NodeTest<Node> {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/FunctionTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/FunctionTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/FunctionTest.java
new file mode 100644
index 0000000..902d9ea
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/FunctionTest.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.functions.TestFunction;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class FunctionTest<Node> extends NodeTest<Node> {
+
+    private final TestFunction<Node> test;
+    private final List<NodeSelector<Node>> argSelectors;
+
+    public FunctionTest(TestFunction<Node> test, List<NodeSelector<Node>> argSelectors) {
+        this.test = test;
+        this.argSelectors = argSelectors;
+    }
+
+    @Override
+    public boolean accept(RDFBackend<Node> backend, Node context, Node target) throws IllegalArgumentException {
+
+        ArrayList<Collection<Node>> fktArgs = new ArrayList<Collection<Node>>();
+        for (NodeSelector<Node> sel : argSelectors) {
+            fktArgs.add(sel.select(backend, target, null, null));
+        }
+
+        @SuppressWarnings("unchecked")
+        final Boolean isAccepted = test.apply(backend, context, fktArgs.toArray(new Collection[argSelectors.size()]));
+
+        return isAccepted;
+    }
+
+    @Override
+    public String getSignature() {
+        return "(function, argument) :: (TestFunction, List<Nodes>) -> Boolean";
+    }
+
+    @Override
+    public String getDescription() {
+        return "Delegate the test to a TestFunction";
+    }
+
+    @Override
+    public String getPathExpression(RDFBackend<Node> backend) {
+        final StringBuilder sb = new StringBuilder("fn:");
+        sb.append(test.getLocalName());
+        sb.append("(");
+        boolean first = true;
+        for (NodeSelector<Node> ns : argSelectors) {
+            if (!first) {
+                sb.append(", ");
+            }
+            sb.append(ns.getPathExpression(backend));
+            first = false;
+        }
+        return sb.append(")").toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralLanguageTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralLanguageTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralLanguageTest.java
new file mode 100644
index 0000000..6265a56
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralLanguageTest.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+import java.util.Locale;
+
+/**
+ * Tests if the language of the literal node matches the language configured for the test. If the language of the test
+ * is null, only allows literal nodes without language definition.
+ *
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class LiteralLanguageTest<Node> extends NodeTest<Node> {
+
+    private String lang;
+
+
+    public LiteralLanguageTest(String lang) {
+        this.lang = lang;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node node) throws IllegalArgumentException {
+
+        if(rdfBackend.isLiteral(node)) {
+            if(lang != null && !lang.toLowerCase().equals("none")) {
+                return new Locale(lang).equals(rdfBackend.getLiteralLanguage(node));
+            } else {
+                return rdfBackend.getLiteralLanguage(node) == null;
+            }
+        } else {
+            return false;
+        }
+
+    }
+
+    /**
+     * Return the name of the NodeFunction for registration in the function registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return "@" + lang;
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "nodes [@lang] :: (NodeList, Language) -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests the language of the literal nodes passed as argument";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        LiteralLanguageTest that = (LiteralLanguageTest) o;
+
+        if (lang != null ? !lang.equals(that.lang) : that.lang != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return lang != null ? lang.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralTypeTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralTypeTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralTypeTest.java
new file mode 100644
index 0000000..1117634
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/LiteralTypeTest.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+/**
+ * Literal type tests allow to select only literals of a specified type, e.g. to ensure that only decimal values are
+ * retrieved:
+ * <p/>
+ * <code>
+ * ^^TYPE
+ * </code>
+ * <p/>
+ * where TYPE is the XML Schema type to select.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class LiteralTypeTest<Node> extends NodeTest<Node> {
+
+    private String typeUri;
+
+    public LiteralTypeTest(String typeUri) {
+        this.typeUri = typeUri;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node node) throws IllegalArgumentException {
+
+        if(rdfBackend.isLiteral(node)) {
+
+            if(typeUri != null) {
+                return typeUri.equals(rdfBackend.getLiteralType(node).toString());
+            } else {
+                return null == rdfBackend.getLiteralType(node).toString();
+            }
+        } else {
+            return false;
+        }
+
+    }
+
+    /**
+     * Return the name of the NodeFunction for registration in the function registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return "^^" + typeUri;
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "nodes [^^typeUri] :: (NodeList, URI) -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests the types of the nodes passed as argument";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        LiteralTypeTest that = (LiteralTypeTest) o;
+
+        if (typeUri != null ? !typeUri.equals(that.typeUri) : that.typeUri != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return typeUri != null ? typeUri.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/NotTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/NotTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/NotTest.java
new file mode 100644
index 0000000..b0c3637
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/NotTest.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+public class NotTest<Node> extends NodeTest<Node> {
+
+    private final NodeTest<Node> delegate;
+
+    public NotTest(NodeTest<Node> delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public boolean accept(RDFBackend<Node> backend, Node context, Node args) throws IllegalArgumentException {
+        return !delegate.accept(backend, context, args);
+    }
+
+    @Override
+    public String getPathExpression(RDFBackend<Node> backend) {
+        if (delegate instanceof ComplexTest<?>) {
+            return String.format("!(%s)", delegate.getPathExpression(backend));
+        } else {
+            return String.format("!%s", delegate.getPathExpression(backend));
+        }
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "!test :: Boolean -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Negates the test given as argument";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        NotTest notTest = (NotTest) o;
+
+        if (delegate != null ? !delegate.equals(notTest.delegate) : notTest.delegate != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate != null ? delegate.hashCode() : 0;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/OrTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/OrTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/OrTest.java
new file mode 100644
index 0000000..3010b85
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/OrTest.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+/**
+ * Tests the disjunction of two tests.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class OrTest<Node> extends ComplexTest<Node> {
+
+    private NodeTest<Node> left;
+    private NodeTest<Node> right;
+
+    public OrTest(NodeTest<Node> left, NodeTest<Node> right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node args) throws IllegalArgumentException {
+        return left.accept(rdfBackend, context, args) || right.accept(rdfBackend, context, args);
+    }
+
+    /**
+     * Return the name of the NodeFunction for registration in the function registry
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return String.format("%s | %s", left.getPathExpression(rdfBackend), right.getPathExpression(rdfBackend));
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "(left  | right ) :: (Boolean, Boolean) -> Boolean";
+
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests the disjunction of two tests";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) { return true; }
+        if (o == null || getClass() != o.getClass()) { return false; }
+
+        @SuppressWarnings("rawtypes")
+        OrTest orTest = (OrTest) o;
+
+        if (left != null ? !left.equals(orTest.left) : orTest.left != null) { return false; }
+        if (right != null ? !right.equals(orTest.right) : orTest.right != null) { return false; }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = left != null ? left.hashCode() : 0;
+        result = 31 * result + (right != null ? right.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathEqualityTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathEqualityTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathEqualityTest.java
new file mode 100644
index 0000000..f4ed701
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathEqualityTest.java
@@ -0,0 +1,124 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+/**
+ * Checks whether a path selector contains a certain node.  Used for the syntax construct
+ *
+ * <path> is <node>
+ *
+ * e.g.
+ *
+ * rdf:type is skos:Concept
+ *
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class PathEqualityTest<Node> extends NodeTest<Node> {
+
+    private NodeSelector<Node> path;
+    private Node node;
+
+
+    public PathEqualityTest(NodeSelector<Node> path, Node node) {
+        this.node = node;
+        this.path = path;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node candidate) throws IllegalArgumentException {
+        return path.select(rdfBackend, candidate,null,null).contains(node);
+    }
+
+    /**
+     * Return the representation of the NodeFunction or NodeSelector in the RDF Path Language
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        if (rdfBackend.isURI(node)) {
+            return String.format("%s is <%s>", path.getPathExpression(rdfBackend), rdfBackend.stringValue(node));
+        } else {
+            // TODO Can this happen?
+            return String.format("%s is %s", path.getPathExpression(rdfBackend), rdfBackend.stringValue(node));
+        }
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "nodes is nodes :: (NodeList,NodeList) -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests whether the two node lists intersect";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        @SuppressWarnings("rawtypes")
+        PathEqualityTest that = (PathEqualityTest) o;
+
+        if (node != null ? !node.equals(that.node) : that.node != null) {
+            return false;
+        }
+        if (path != null ? !path.equals(that.path) : that.path != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = path != null ? path.hashCode() : 0;
+        result = 31 * result + (node != null ? node.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathTest.java
new file mode 100644
index 0000000..c6e8606
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/PathTest.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.selectors.NodeSelector;
+import at.newmedialab.ldpath.api.tests.NodeTest;
+
+import java.util.Collection;
+
+/**
+ * Tests whether the path given as argument for the constructor yields at least one node when evaluated
+ * from the context node to which the test is applied.
+ * <p/>
+ * Author: Sebastian Schaffert <se...@salzburgresearch.at>
+ */
+public class PathTest<Node> extends NodeTest<Node> {
+
+    private NodeSelector<Node> path;
+
+    public PathTest(NodeSelector<Node> path) {
+        this.path = path;
+    }
+
+    /**
+     * Apply the function to the list of nodes passed as arguments and return the result as type T.
+     * Throws IllegalArgumentException if the function cannot be applied to the nodes passed as argument
+     * or the number of arguments is not correct.
+     *
+     * @param args a nested list of KiWiNodes
+     * @return
+     */
+    @Override
+    public boolean accept(RDFBackend<Node> rdfBackend, Node context, Node candidate) throws IllegalArgumentException {
+
+        if (rdfBackend.isURI(candidate) || rdfBackend.isBlank(candidate)) {
+            Collection<Node> testResult = path.select(rdfBackend, candidate,null,null);
+            return testResult.size() > 0;
+        } else {
+            return false;
+        }
+
+    }
+
+    /**
+     * Return the representation of the NodeFunction or NodeSelector in the RDF Path Language
+     *
+     * @param rdfBackend
+     * @return
+     */
+    @Override
+    public String getPathExpression(RDFBackend<Node> rdfBackend) {
+        return path.getPathExpression(rdfBackend);
+    }
+
+    /**
+     * A string describing the signature of this node function, e.g. "fn:content(uris : Nodes) : Nodes". The
+     * syntax for representing the signature can be chosen by the implementer. This method is for informational
+     * purposes only.
+     *
+     * @return
+     */
+    @Override
+    public String getSignature() {
+        return "nodes :: NodeList -> Boolean";
+    }
+
+    /**
+     * A short human-readable description of what the node function does.
+     *
+     * @return
+     */
+    @Override
+    public String getDescription() {
+        return "Tests whether the node list is non-empty";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) { return true; }
+        if (o == null || getClass() != o.getClass()) { return false; }
+
+        @SuppressWarnings("rawtypes")
+        PathTest pathTest = (PathTest) o;
+
+        if (path != null ? !path.equals(pathTest.path) : pathTest.path != null) { return false; }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return path != null ? path.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/BinaryNumericTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/BinaryNumericTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/BinaryNumericTest.java
new file mode 100644
index 0000000..bb715c6
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/BinaryNumericTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests.functions;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+import at.newmedialab.ldpath.api.functions.TestFunction;
+import at.newmedialab.ldpath.model.transformers.DoubleTransformer;
+
+import java.util.Collection;
+
+public abstract  class BinaryNumericTest<Node> extends TestFunction<Node> {
+
+
+    protected final DoubleTransformer<Node> transformer = new DoubleTransformer<Node>();
+
+    @Override
+    public final Boolean apply(RDFBackend<Node> backend, Node context,
+            Collection<Node>... args) throws IllegalArgumentException {
+
+        if (args.length != 2) { throw new IllegalArgumentException(getLocalName() + " is a binary function and therefor requires exactly two arguments"); }
+
+        Collection<Node> leftArgs = args[0];
+        Collection<Node> rightArgs = args[1];
+
+        for (Node lN : leftArgs) {
+            for (Node rN : rightArgs) {
+                if (!test(backend, lN, rN)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected boolean test(RDFBackend<Node> backend, Node leftNode, Node rightNode) {
+        try {
+            return test(transformer.transform(backend, leftNode), transformer.transform(backend, rightNode));
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
+
+    protected abstract boolean test(Double left, Double right);
+
+    @Override
+    public String getSignature() {
+        return "fn:"+getLocalName()+"(NumericNode a, NumericNode b) :: Boolean";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/EqualTest.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/EqualTest.java b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/EqualTest.java
new file mode 100644
index 0000000..5436b4b
--- /dev/null
+++ b/ldpath/ldpath-core/src/main/java/at/newmedialab/ldpath/model/tests/functions/EqualTest.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 at.newmedialab.ldpath.model.tests.functions;
+
+
+public class EqualTest<Node> extends BinaryNumericTest<Node> {
+
+	@Override
+	protected boolean test(Double left, Double right) {
+		return left.compareTo(right) == 0;
+	}
+
+	@Override
+    public String getDescription() {
+		return "Check whether the two arguments are (numerical) equal";
+	}
+
+	@Override
+	public String getLocalName() {
+		return "eq";
+	}
+
+}