Skip to content

Commit

Permalink
inlined pipes
Browse files Browse the repository at this point in the history
  • Loading branch information
jexp committed Oct 23, 2013
1 parent 3ad1ba3 commit 58886bd
Show file tree
Hide file tree
Showing 15 changed files with 607 additions and 130 deletions.
70 changes: 0 additions & 70 deletions pom.xml
Expand Up @@ -11,8 +11,6 @@
<spatial.test.osm.version>20100819</spatial.test.osm.version>
<spatial.test.shp.version>20100819</spatial.test.shp.version>
<bundle.namespace>org.neo4j.gis</bundle.namespace>
<blueprints.version>1.2</blueprints.version>
<gremlin.version>1.5</gremlin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<github.global.server>github</github.global.server>
</properties>
Expand Down Expand Up @@ -317,74 +315,6 @@
<version>1.1</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.tinkerpop.gremlin</groupId>
<artifactId>gremlin-groovy</artifactId>
<version>${gremlin.version}</version>
<type>jar</type>
<scope>provided</scope>
<exclusions>
<!-- Sail support not needed -->
<exclusion>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-sail-graph</artifactId>
</exclusion>
<!-- Maven support in groovy not needed -->
<exclusion>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
</exclusion>
<!-- "readline" not needed - we only expose gremlin through webadmin -->
<exclusion>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.tinkerpop.gremlin</groupId>
<artifactId>gremlin-java</artifactId>
<version>${gremlin.version}</version>
<type>jar</type>
<scope>provided</scope>
<exclusions>
<!-- Sail support not needed -->
<exclusion>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-sail-graph</artifactId>
</exclusion>
<!-- Maven support in groovy not needed -->
<exclusion>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
</exclusion>
<!-- "readline" not needed - we only expose gremlin through webadmin -->
<exclusion>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-neo4j-graph</artifactId>
<version>${blueprints.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-management</artifactId>
</exclusion>
<exclusion>
<artifactId>neo4j-ha</artifactId>
<groupId>org.neo4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
Expand Down
Expand Up @@ -21,8 +21,8 @@

import java.util.NoSuchElementException;

import com.tinkerpop.pipes.AbstractPipe;
import com.vividsolutions.jts.geom.Geometry;
import org.neo4j.gis.spatial.pipes.impl.AbstractPipe;

/**
* Abstract pipe for GeoPipelines.
Expand Down
58 changes: 35 additions & 23 deletions src/main/java/org/neo4j/gis/spatial/pipes/GeoPipeline.java
Expand Up @@ -62,6 +62,7 @@
import org.neo4j.gis.spatial.pipes.filtering.FilterTouch;
import org.neo4j.gis.spatial.pipes.filtering.FilterValid;
import org.neo4j.gis.spatial.pipes.filtering.FilterWithin;
import org.neo4j.gis.spatial.pipes.impl.*;
import org.neo4j.gis.spatial.pipes.processing.ApplyAffineTransformation;
import org.neo4j.gis.spatial.pipes.processing.Area;
import org.neo4j.gis.spatial.pipes.processing.Boundary;
Expand Down Expand Up @@ -103,44 +104,47 @@
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.tinkerpop.gremlin.groovy.GremlinGroovyPipeline;
import com.tinkerpop.pipes.filter.FilterPipe;
import com.tinkerpop.pipes.util.StartPipe;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.util.AffineTransformation;


public class GeoPipeline extends GremlinGroovyPipeline<GeoPipeFlow, GeoPipeFlow> {
public class GeoPipeline extends Pipeline<GeoPipeFlow,GeoPipeFlow> {

protected Layer layer;

protected GeoPipeline(Layer layer) {
this.layer = layer;
this.layer = layer;
}

protected static StartPipe<GeoPipeFlow> createStartPipe(List<SpatialDatabaseRecord> records) {
protected static IdentityPipe<GeoPipeFlow> createStartPipe(List<SpatialDatabaseRecord> records) {
return createStartPipe(records.iterator());
}

protected static StartPipe<GeoPipeFlow> createStartPipe(final Iterator<SpatialDatabaseRecord> records) {
return new StartPipe<GeoPipeFlow>(new Iterator<GeoPipeFlow>() {
@Override
public boolean hasNext() {
return records.hasNext();
}
protected static IdentityPipe<GeoPipeFlow> createStartPipe(final Iterator<SpatialDatabaseRecord> records) {
Iterator<GeoPipeFlow> startIterator = new Iterator<GeoPipeFlow>() {
@Override
public boolean hasNext() {
return records.hasNext();
}

@Override
public GeoPipeFlow next() {
return new GeoPipeFlow(records.next());
}
@Override
public GeoPipeFlow next() {
return new GeoPipeFlow(records.next());
}

@Override
public void remove() {
records.remove();
}
});
@Override
public void remove() {
records.remove();
}
};
final Object start = startIterator;
return new IdentityPipe<GeoPipeFlow>() {
{
super.setStarts((Iterator) start);
}
};
}

/**
Expand Down Expand Up @@ -194,7 +198,6 @@ public static GeoPipeline start(Layer layer, SearchFilter searchFilter) {
* Start a new pipeline that will iterate through all items contained in a Layer
*
* @param layer
* @param searchFilter
* @return geoPipeline
*/
public static GeoPipeline start(Layer layer) {
Expand Down Expand Up @@ -408,7 +411,7 @@ public static GeoPipeline startNearestNeighborSearch(Layer layer, Coordinate poi

return start(layer, new SearchIntersectWindow(layer, extent))
.calculateDistance(layer.getGeometryFactory().createPoint(point))
.propertyFilter("Distance", maxDistance, FilterPipe.Filter.LESS_THAN_EQUAL);
.propertyFilter("Distance", maxDistance, FilterPipe.Filter.LESS_THAN_EQUAL);
}

/**
Expand Down Expand Up @@ -1014,4 +1017,13 @@ public List<Node> toNodeList() {
return result;

}

public <T> GeoPipeline add(final Pipe<?, T> pipe) {
this.addPipe(pipe);
return (GeoPipeline) this;
}

public GeoPipeline range(final int low, final int high) {
return this.add(new RangeFilterPipe<GeoPipeFlow>(low, high));
}
}
Expand Up @@ -21,10 +21,7 @@

import org.neo4j.gis.spatial.pipes.AbstractFilterGeoPipe;
import org.neo4j.gis.spatial.pipes.GeoPipeFlow;

import com.tinkerpop.pipes.filter.FilterPipe;
import com.tinkerpop.pipes.util.PipeHelper;

import org.neo4j.gis.spatial.pipes.impl.FilterPipe;

/**
* Filter by property value.
Expand All @@ -47,6 +44,34 @@ public FilterProperty(String key, Object value, FilterPipe.Filter comparison) {

@Override
protected boolean validate(GeoPipeFlow flow) {
return PipeHelper.compareObjects(comparison, flow.getProperties().get(key), value);
}
final Object leftObject = flow.getProperties().get(key);
switch (comparison) {
case EQUAL:
if (null == leftObject)
return value == null;
return leftObject.equals(value);
case NOT_EQUAL:
if (null == leftObject)
return value != null;
return !leftObject.equals(value);
case GREATER_THAN:
if (null == leftObject || value == null)
return false;
return ((Comparable) leftObject).compareTo(value) == 1;
case LESS_THAN:
if (null == leftObject || value == null)
return false;
return ((Comparable) leftObject).compareTo(value) == -1;
case GREATER_THAN_EQUAL:
if (null == leftObject || value == null)
return false;
return ((Comparable) leftObject).compareTo(value) >= 0;
case LESS_THAN_EQUAL:
if (null == leftObject || value == null)
return false;
return ((Comparable) leftObject).compareTo(value) <= 0;
default:
throw new IllegalArgumentException("Invalid state as no valid filter was provided");
}
}
}
119 changes: 119 additions & 0 deletions src/main/java/org/neo4j/gis/spatial/pipes/impl/AbstractPipe.java
@@ -0,0 +1,119 @@
package org.neo4j.gis.spatial.pipes.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
* An AbstractPipe provides most of the functionality that is repeated in every instance of a Pipe.
* Any subclass of AbstractPipe should simply implement processNextStart(). The standard model is
* <pre>
* protected E processNextStart() throws NoSuchElementException {
* S s = this.starts.next();
* E e = // do something with the S to yield an E
* return e;
* }
* </pre>
* If the current incoming S is not to be emitted and there are no other S objects to process and emit, then throw a NoSuchElementException.
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public abstract class AbstractPipe<S, E> implements Pipe<S, E> {

protected Iterator<S> starts;
private E nextEnd;
protected E currentEnd;
private boolean available = false;

public void setStarts(final Pipe<?, S> starts) {
this.starts = starts;
}

public void setStarts(final Iterator<S> starts) {
if (starts instanceof Pipe)
this.starts = starts;
else
this.starts = new LastElementIterator<S>(starts);
}

public void setStarts(final Iterable<S> starts) {
this.setStarts(starts.iterator());
}

public void reset() {
if (this.starts instanceof Pipe) {
((Pipe) this.starts).reset();
}
this.nextEnd = null;
this.currentEnd = null;
this.available = false;
}

public List getPath() {
final List pathElements = getPathToHere();
final int size = pathElements.size();
// do not repeat filters as they dup the object
if (size == 0 || pathElements.get(size - 1) != this.currentEnd) {
pathElements.add(this.currentEnd);
}
return pathElements;
}

public void remove() {
throw new UnsupportedOperationException();
}

public E next() {
if (this.available) {
this.available = false;
return (this.currentEnd = this.nextEnd);
} else {
return (this.currentEnd = this.processNextStart());
}
}

public boolean hasNext() {
if (this.available)
return true;
else {
try {
this.nextEnd = this.processNextStart();
return (this.available = true);
} catch (final NoSuchElementException e) {
return (this.available = false);
}
}
}

/**
* The iterator method of Iterable is not faithful to the Java semantics of iterator().
* This method simply returns the pipe itself (which is an iterator) and thus, is useful only for foreach iteration.
*
* @return the pipe from the perspective of an iterator
*/
public Iterator<E> iterator() {
return this;
}

public String toString() {
return getClass().getSimpleName();
}

protected abstract E processNextStart() throws NoSuchElementException;

protected List getPathToHere() {
if (this.starts instanceof Pipe) {
return ((Pipe) this.starts).getPath();
} else if (this.starts instanceof LastElementIterator) {
final List list = new ArrayList();
list.add(((LastElementIterator) starts).lastElement());
return list;
} else {
return new ArrayList();
}
}


}

0 comments on commit 58886bd

Please sign in to comment.