use of com.thinkaurelius.titan.core.attribute.Geoshape in project titan by thinkaurelius.
the class TitanGraphTest method testDataTypes.
/**
* Test the different data types that Titan supports natively and ensure that invalid data types aren't allowed
*/
@Test
public void testDataTypes() throws Exception {
clopen(option(CUSTOM_ATTRIBUTE_CLASS, "attribute10"), SpecialInt.class.getCanonicalName(), option(CUSTOM_SERIALIZER_CLASS, "attribute10"), SpecialIntSerializer.class.getCanonicalName());
PropertyKey num = makeKey("num", SpecialInt.class);
PropertyKey barr = makeKey("barr", byte[].class);
PropertyKey boolval = makeKey("boolval", Boolean.class);
PropertyKey birthday = makeKey("birthday", Instant.class);
PropertyKey geo = makeKey("geo", Geoshape.class);
PropertyKey precise = makeKey("precise", Double.class);
PropertyKey any = mgmt.makePropertyKey("any").cardinality(Cardinality.LIST).dataType(Object.class).make();
try {
//Not a valid data type - primitive
makeKey("pint", int.class);
fail();
} catch (IllegalArgumentException e) {
}
try {
//Not a valid data type - interface
makeKey("number", Number.class);
fail();
} catch (IllegalArgumentException e) {
}
finishSchema();
clopen();
boolval = tx.getPropertyKey("boolval");
num = tx.getPropertyKey("num");
barr = tx.getPropertyKey("barr");
birthday = tx.getPropertyKey("birthday");
geo = tx.getPropertyKey("geo");
precise = tx.getPropertyKey("precise");
any = tx.getPropertyKey("any");
assertEquals(Boolean.class, boolval.dataType());
assertEquals(byte[].class, barr.dataType());
assertEquals(Object.class, any.dataType());
final Instant c = Instant.ofEpochSecond(1429225756);
final Geoshape shape = Geoshape.box(10.0, 10.0, 20.0, 20.0);
TitanVertex v = tx.addVertex();
v.property(n(boolval), true);
v.property(VertexProperty.Cardinality.single, n(birthday), c);
v.property(VertexProperty.Cardinality.single, n(num), new SpecialInt(10));
v.property(VertexProperty.Cardinality.single, n(barr), new byte[] { 1, 2, 3, 4 });
v.property(VertexProperty.Cardinality.single, n(geo), shape);
v.property(VertexProperty.Cardinality.single, n(precise), 10.12345);
v.property(n(any), "Hello");
v.property(n(any), 10l);
int[] testarr = { 5, 6, 7 };
v.property(n(any), testarr);
// ######## VERIFICATION ##########
assertTrue(v.<Boolean>value("boolval"));
assertEquals(10, v.<SpecialInt>value("num").getValue());
assertEquals(c, v.value("birthday"));
assertEquals(4, v.<byte[]>value("barr").length);
assertEquals(shape, v.<Geoshape>value("geo"));
assertEquals(10.12345, v.<Double>value("precise").doubleValue(), 0.000001);
assertCount(3, v.properties("any"));
for (TitanVertexProperty prop : v.query().labels("any").properties()) {
Object value = prop.value();
if (value instanceof String)
assertEquals("Hello", value);
else if (value instanceof Long)
assertEquals(10l, value);
else if (value.getClass().isArray()) {
assertTrue(Arrays.equals(testarr, (int[]) value));
} else
fail();
}
clopen();
v = getV(tx, v);
// ######## VERIFICATION (copied from above) ##########
assertTrue(v.<Boolean>value("boolval"));
assertEquals(10, v.<SpecialInt>value("num").getValue());
assertEquals(c, v.value("birthday"));
assertEquals(4, v.<byte[]>value("barr").length);
assertEquals(shape, v.<Geoshape>value("geo"));
assertEquals(10.12345, v.<Double>value("precise").doubleValue(), 0.000001);
assertCount(3, v.properties("any"));
for (TitanVertexProperty prop : v.query().labels("any").properties()) {
Object value = prop.value();
if (value instanceof String)
assertEquals("Hello", value);
else if (value instanceof Long)
assertEquals(10l, value);
else if (value.getClass().isArray()) {
assertTrue(Arrays.equals(testarr, (int[]) value));
} else
fail();
}
}
use of com.thinkaurelius.titan.core.attribute.Geoshape in project atlas by apache.
the class Solr5Index method buildQueryFilter.
public String buildQueryFilter(Condition<TitanElement> condition, KeyInformation.StoreRetriever informations) {
if (condition instanceof PredicateCondition) {
PredicateCondition<String, TitanElement> atom = (PredicateCondition<String, TitanElement>) condition;
Object value = atom.getValue();
String key = atom.getKey();
TitanPredicate titanPredicate = atom.getPredicate();
if (value instanceof Number) {
String queryValue = escapeValue(value);
Preconditions.checkArgument(titanPredicate instanceof Cmp, "Relation not supported on numeric types: " + titanPredicate);
Cmp numRel = (Cmp) titanPredicate;
switch(numRel) {
case EQUAL:
return (key + ":" + queryValue);
case NOT_EQUAL:
return ("-" + key + ":" + queryValue);
case LESS_THAN:
// use right curly to mean up to but not including value
return (key + ":[* TO " + queryValue + "}");
case LESS_THAN_EQUAL:
return (key + ":[* TO " + queryValue + "]");
case GREATER_THAN:
// use left curly to mean greater than but not including value
return (key + ":{" + queryValue + " TO *]");
case GREATER_THAN_EQUAL:
return (key + ":[" + queryValue + " TO *]");
default:
throw new IllegalArgumentException("Unexpected relation: " + numRel);
}
} else if (value instanceof String) {
Mapping map = getStringMapping(informations.get(key));
assert map == TEXT || map == STRING;
if (map == TEXT && !titanPredicate.toString().startsWith("CONTAINS"))
throw new IllegalArgumentException("Text mapped string values only support CONTAINS queries and not: " + titanPredicate);
if (map == STRING && titanPredicate.toString().startsWith("CONTAINS"))
throw new IllegalArgumentException("String mapped string values do not support CONTAINS queries: " + titanPredicate);
// Special case
if (titanPredicate == Text.CONTAINS) {
// e.g. - if terms tomorrow and world were supplied, and fq=text:(tomorrow world)
// sample data set would return 2 documents: one where text = Tomorrow is the World,
// and the second where text = Hello World. Hence, we are decomposing the query string
// and building an AND query explicitly because we need AND semantics
value = ((String) value).toLowerCase();
List<String> terms = Text.tokenize((String) value);
if (terms.isEmpty()) {
return "";
} else if (terms.size() == 1) {
return (key + ":(" + escapeValue(terms.get(0)) + ")");
} else {
And<TitanElement> andTerms = new And<>();
for (String term : terms) {
andTerms.add(new PredicateCondition<>(key, titanPredicate, term));
}
return buildQueryFilter(andTerms, informations);
}
}
if (titanPredicate == Text.PREFIX || titanPredicate == Text.CONTAINS_PREFIX) {
return (key + ":" + escapeValue(value) + "*");
} else if (titanPredicate == Text.REGEX || titanPredicate == Text.CONTAINS_REGEX) {
return (key + ":/" + value + "/");
} else if (titanPredicate == EQUAL) {
return (key + ":\"" + escapeValue(value) + "\"");
} else if (titanPredicate == NOT_EQUAL) {
return ("-" + key + ":\"" + escapeValue(value) + "\"");
} else {
throw new IllegalArgumentException("Relation is not supported for string value: " + titanPredicate);
}
} else if (value instanceof Geoshape) {
Geoshape geo = (Geoshape) value;
if (geo.getType() == Geoshape.Type.CIRCLE) {
Geoshape.Point center = geo.getPoint();
return ("{!geofilt sfield=" + key + " pt=" + center.getLatitude() + "," + center.getLongitude() + " d=" + geo.getRadius() + // distance in kilometers
"} distErrPct=0");
} else if (geo.getType() == Geoshape.Type.BOX) {
Geoshape.Point southwest = geo.getPoint(0);
Geoshape.Point northeast = geo.getPoint(1);
return (key + ":[" + southwest.getLatitude() + "," + southwest.getLongitude() + " TO " + northeast.getLatitude() + "," + northeast.getLongitude() + "]");
} else if (geo.getType() == Geoshape.Type.POLYGON) {
List<Geoshape.Point> coordinates = getPolygonPoints(geo);
StringBuilder poly = new StringBuilder(key + ":\"IsWithin(POLYGON((");
for (Geoshape.Point coordinate : coordinates) {
poly.append(coordinate.getLongitude()).append(" ").append(coordinate.getLatitude()).append(", ");
}
// close the polygon with the first coordinate
poly.append(coordinates.get(0).getLongitude()).append(" ").append(coordinates.get(0).getLatitude());
poly.append(")))\" distErrPct=0");
return (poly.toString());
}
} else if (value instanceof Date) {
String queryValue = escapeValue(toIsoDate((Date) value));
Preconditions.checkArgument(titanPredicate instanceof Cmp, "Relation not supported on date types: " + titanPredicate);
Cmp numRel = (Cmp) titanPredicate;
switch(numRel) {
case EQUAL:
return (key + ":" + queryValue);
case NOT_EQUAL:
return ("-" + key + ":" + queryValue);
case LESS_THAN:
// use right curly to mean up to but not including value
return (key + ":[* TO " + queryValue + "}");
case LESS_THAN_EQUAL:
return (key + ":[* TO " + queryValue + "]");
case GREATER_THAN:
// use left curly to mean greater than but not including value
return (key + ":{" + queryValue + " TO *]");
case GREATER_THAN_EQUAL:
return (key + ":[" + queryValue + " TO *]");
default:
throw new IllegalArgumentException("Unexpected relation: " + numRel);
}
} else if (value instanceof Boolean) {
Cmp numRel = (Cmp) titanPredicate;
String queryValue = escapeValue(value);
switch(numRel) {
case EQUAL:
return (key + ":" + queryValue);
case NOT_EQUAL:
return ("-" + key + ":" + queryValue);
default:
throw new IllegalArgumentException("Boolean types only support EQUAL or NOT_EQUAL");
}
} else if (value instanceof UUID) {
if (titanPredicate == EQUAL) {
return (key + ":\"" + escapeValue(value) + "\"");
} else if (titanPredicate == NOT_EQUAL) {
return ("-" + key + ":\"" + escapeValue(value) + "\"");
} else {
throw new IllegalArgumentException("Relation is not supported for uuid value: " + titanPredicate);
}
} else
throw new IllegalArgumentException("Unsupported type: " + value);
} else if (condition instanceof Not) {
String sub = buildQueryFilter(((Not) condition).getChild(), informations);
if (StringUtils.isNotBlank(sub))
return "-(" + sub + ")";
else
return "";
} else if (condition instanceof And) {
int numChildren = ((And) condition).size();
StringBuilder sb = new StringBuilder();
for (Condition<TitanElement> c : condition.getChildren()) {
String sub = buildQueryFilter(c, informations);
if (StringUtils.isBlank(sub))
continue;
// b. expression is a single statement in the AND.
if (!sub.startsWith("-") && numChildren > 1)
sb.append("+");
sb.append(sub).append(" ");
}
return sb.toString();
} else if (condition instanceof Or) {
StringBuilder sb = new StringBuilder();
int element = 0;
for (Condition<TitanElement> c : condition.getChildren()) {
String sub = buildQueryFilter(c, informations);
if (StringUtils.isBlank(sub))
continue;
if (element == 0)
sb.append("(");
else
sb.append(" OR ");
sb.append(sub);
element++;
}
if (element > 0)
sb.append(")");
return sb.toString();
} else {
throw new IllegalArgumentException("Invalid condition: " + condition);
}
return null;
}
use of com.thinkaurelius.titan.core.attribute.Geoshape in project titan by thinkaurelius.
the class GeoshapeHandler method convert.
@Override
public Geoshape convert(Object value) {
if (value.getClass().isArray() && (value.getClass().getComponentType().isPrimitive() || Number.class.isAssignableFrom(value.getClass().getComponentType()))) {
Geoshape shape = null;
int len = Array.getLength(value);
double[] arr = new double[len];
for (int i = 0; i < len; i++) arr[i] = ((Number) Array.get(value, i)).doubleValue();
if (len == 2)
shape = Geoshape.point(arr[0], arr[1]);
else if (len == 3)
shape = Geoshape.circle(arr[0], arr[1], arr[2]);
else if (len == 4)
shape = Geoshape.box(arr[0], arr[1], arr[2], arr[3]);
else
throw new IllegalArgumentException("Expected 2-4 coordinates to create Geoshape, but given: " + value);
return shape;
} else if (value instanceof String) {
String[] components = null;
for (String delimiter : new String[] { ",", ";" }) {
components = ((String) value).split(delimiter);
if (components.length >= 2 && components.length <= 4)
break;
else
components = null;
}
Preconditions.checkArgument(components != null, "Could not parse coordinates from string: %s", value);
double[] coords = new double[components.length];
try {
for (int i = 0; i < components.length; i++) {
coords[i] = Double.parseDouble(components[i]);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Could not parse coordinates from string: " + value, e);
}
return convert(coords);
} else
return null;
}
use of com.thinkaurelius.titan.core.attribute.Geoshape in project titan by thinkaurelius.
the class TitanIndexTest method testCollection.
private void testCollection(Cardinality cardinality, String property, Object value1, Object value2) {
clopen();
Vertex v1 = graph.addVertex();
//Adding properties one at a time
v1.property(property, value1);
//Flush the index
clopen();
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
v1 = getV(graph, v1.id());
v1.property(property, value2);
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Flush the index
clopen();
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Remove the properties
v1 = getV(graph, v1.id());
v1.properties(property).forEachRemaining(p -> {
if (p.value().equals(value1)) {
p.remove();
}
});
assertFalse(graph.query().has(property, value1).vertices().iterator().hasNext());
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Flush the index
clopen();
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
assertFalse(graph.query().has(property, value1).vertices().iterator().hasNext());
//Re add the properties
v1 = getV(graph, v1.id());
v1.property(property, value1);
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Flush the index
clopen();
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Add a duplicate property
v1 = getV(graph, v1.id());
v1.property(property, value1);
assertEquals(Cardinality.SET.equals(cardinality) ? 2 : 3, Iterators.size(getOnlyVertex(graph.query().has(property, value1)).properties(property)));
//Flush the index
clopen();
assertEquals(Cardinality.SET.equals(cardinality) ? 2 : 3, Iterators.size(getOnlyVertex(graph.query().has(property, value1)).properties(property)));
//Add two properties at once to a fresh vertex
graph.vertices().forEachRemaining(v -> v.remove());
v1 = graph.addVertex();
v1.property(property, value1);
v1.property(property, value2);
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//Flush the index
clopen();
assertEquals(v1, getOnlyElement(graph.query().has(property, value1).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, value2).vertices()));
//If this is a geo test then try a within query
if (value1 instanceof Geoshape) {
assertEquals(v1, getOnlyElement(graph.query().has(property, Geo.WITHIN, Geoshape.circle(1.0, 1.0, 0.1)).vertices()));
assertEquals(v1, getOnlyElement(graph.query().has(property, Geo.WITHIN, Geoshape.circle(2.0, 2.0, 0.1)).vertices()));
}
}
use of com.thinkaurelius.titan.core.attribute.Geoshape in project titan by thinkaurelius.
the class GeoToWktConverterTest method testConvertGeoshapePointToWktString.
/**
* Titan Geoshapes are converted to a string that gets sent to its respective index. Unfortunately, the string format
* is not compatible with Solr 4. The GeoToWktConverter transforms the Geoshape's string value into a Well-Known Text
* format understood by Solr.
*/
@Test
public void testConvertGeoshapePointToWktString() throws BackendException {
//no spaces, no negative values
Geoshape p1 = Geoshape.point(35.4, 48.9);
//negative longitude value
Geoshape p2 = Geoshape.point(-35.4, 48.9);
//negative latitude value
Geoshape p3 = Geoshape.point(35.4, -48.9);
String wkt1 = "POINT(48.9 35.4)";
String actualWkt1 = GeoToWktConverter.convertToWktString(p1);
String wkt2 = "POINT(48.9 -35.4)";
String actualWkt2 = GeoToWktConverter.convertToWktString(p2);
String wkt3 = "POINT(-48.9 35.4)";
String actualWkt3 = GeoToWktConverter.convertToWktString(p3);
assertEquals(wkt1, actualWkt1);
assertEquals(wkt2, actualWkt2);
assertEquals(wkt3, actualWkt3);
}
Aggregations