You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/02/21 19:21:18 UTC
[05/21] Rename index to query index, add working query parser code.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityIndexTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityIndexTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityIndexTest.java
new file mode 100644
index 0000000..ee884f7
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityIndexTest.java
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.usergrid.persistence.index.impl;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.usergrid.persistence.collection.CollectionScope;
+import org.apache.usergrid.persistence.collection.util.EntityUtils;
+import org.apache.usergrid.persistence.index.EntityCollectionIndex;
+import org.apache.usergrid.persistence.index.EntitySearchResults;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.entity.SimpleId;
+import org.apache.usergrid.persistence.model.field.BooleanField;
+import org.apache.usergrid.persistence.model.field.DoubleField;
+import org.apache.usergrid.persistence.model.field.EntityObjectField;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.ListField;
+import org.apache.usergrid.persistence.model.field.LongField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+import org.apache.usergrid.persistence.utils.ElasticSearchRule;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import static org.junit.Assert.assertEquals;
+import org.junit.Rule;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class EntityIndexTest {
+ private static final Logger logger = LoggerFactory.getLogger( EntityIndexTest.class );
+
+ @Rule
+ public ElasticSearchRule elasticSearchRule = new ElasticSearchRule();
+
+
+ @Test
+ public void testIndex() throws IOException {
+
+ Client client = elasticSearchRule.getClient();
+ final CollectionScope scope = mock( CollectionScope.class );
+ when( scope.getName() ).thenReturn( "contacts" );
+ String index = RandomStringUtils.randomAlphanumeric(20 ).toLowerCase();
+ String type = scope.getName();
+
+ EntityCollectionIndex entityIndex =
+ new EntityCollectionIndexImpl( client, index, scope, true );
+
+ InputStream is = this.getClass().getResourceAsStream( "/sample-large.json" );
+ ObjectMapper mapper = new ObjectMapper();
+ List<Object> sampleJson = mapper.readValue( is, new TypeReference<List<Object>>() {} );
+
+ int count = 0;
+ StopWatch timer = new StopWatch();
+ timer.start();
+ for ( Object o : sampleJson ) {
+
+ Map<String, Object> item = (Map<String, Object>)o;
+
+ Entity entity = new Entity(new SimpleId(UUIDGenerator.newTimeUUID(), scope.getName()));
+ entity = EntityIndexTest.mapToEntity( scope.getName(), entity, item );
+ EntityUtils.setVersion( entity, UUIDGenerator.newTimeUUID() );
+
+ entityIndex.index( entity );
+
+ count++;
+ }
+ timer.stop();
+ logger.info( "Total time to index {} entries {}ms, average {}ms/entry",
+ count, timer.getTime(), timer.getTime() / count );
+
+ // test queries via Java API QueryBuilder
+ testQueries( client, index, type );
+
+ // test queries via Lucene syntax
+ testQueries( entityIndex );
+
+ client.close();
+ }
+
+
+ private void testQuery( Client client, String index, String type, QueryBuilder qb, int num ) {
+
+ StopWatch timer = new StopWatch();
+ timer.start();
+ SearchResponse sr = client.prepareSearch( index ).setTypes( type )
+ .setQuery( qb ).setFrom( 0 ).setSize( 999 ).execute().actionGet();
+ timer.stop();
+
+ assertEquals( num, sr.getHits().getTotalHits() );
+ logger.debug( "Query1 time {}ms", timer.getTime() );
+ }
+
+
+ private void testQueries( Client client, String index, String type ) {
+
+ testQuery( client, index, type,
+ QueryBuilders.termQuery( "name", "Morgan Pierce" ), 1 );
+
+ // term query is exact match
+ testQuery( client, index, type,
+ QueryBuilders.termQuery("name", "Pierce" ), 0 );
+
+ // match query allows partial match
+ testQuery( client, index, type,
+ QueryBuilders.matchQuery( "name_ug_analyzed", "Pierce" ), 2 );
+
+ testQuery( client, index, type,
+ QueryBuilders.termQuery( "company", "Blurrybus" ), 1 );
+
+ testQuery( client, index, type,
+ QueryBuilders.termQuery( "gender", "female" ), 433 );
+
+ // query of nested object fields supported
+ testQuery( client, index, type,
+ QueryBuilders.termQuery( "contact.email", "nadiabrown@concility.com" ), 1 );
+ }
+
+
+ private void testQuery( EntityCollectionIndex entityIndex, String query, int num ) {
+
+ StopWatch timer = new StopWatch();
+ timer.start();
+ EntitySearchResults results = entityIndex.simpleQuery( query, 0, 999);
+ timer.stop();
+
+ assertEquals( num, results.count() );
+ logger.debug( "Query2 time {}ms", timer.getTime() );
+ }
+
+
+ private void testQueries( EntityCollectionIndex entityIndex ) {
+
+ testQuery( entityIndex, "name:\"Morgan Pierce\"", 1);
+
+ testQuery( entityIndex, "name:\"Morgan\"", 0);
+
+ testQuery( entityIndex, "name_ug_analyzed:\"Morgan\"", 1);
+
+ testQuery( entityIndex, "gender:female", 433);
+ }
+
+
+ @Test
+ public void testRemoveIndex() {
+ }
+
+
+ /**
+ * Test of mapToEntity method, of class EntityUtils.
+ */
+ @Test
+ public void testMapToEntityRoundTrip() throws IOException {
+
+ InputStream is = this.getClass().getResourceAsStream( "/sample-large.json" );
+ ObjectMapper mapper = new ObjectMapper();
+ List<Object> contacts = mapper.readValue( is, new TypeReference<List<Object>>() {} );
+
+ for ( Object o : contacts ) {
+
+ Map<String, Object> map1 = (Map<String, Object>)o;
+
+ // convert map to entity
+ Entity entity1 = EntityIndexTest.mapToEntity( "testscope", map1 );
+
+ // convert entity back to map
+ Map map2 = EntityCollectionIndexImpl.entityToMap( entity1 );
+
+ // the two maps should be the same except for the two new _ug_analyzed properties
+ Map diff = Maps.difference( map1, map2 ).entriesDiffering();
+ assertEquals( 2, diff.size() );
+ }
+ }
+
+
+ public static Entity mapToEntity( String scope, Map<String, Object> item ) {
+ return mapToEntity( scope, null, item );
+ }
+
+
+ public static Entity mapToEntity( String scope, Entity entity, Map<String, Object> map ) {
+
+ if ( entity == null ) {
+ entity = new Entity();
+ }
+
+ for ( String fieldName : map.keySet() ) {
+
+ Object value = map.get( fieldName );
+
+ if ( value instanceof String ) {
+ entity.setField( new StringField(fieldName, (String)value ));
+
+ } else if ( value instanceof Boolean ) {
+ entity.setField( new BooleanField(fieldName, (Boolean)value ));
+
+ } else if ( value instanceof Integer ) {
+ entity.setField( new IntegerField(fieldName, (Integer)value ));
+
+ } else if ( value instanceof Double ) {
+ entity.setField( new DoubleField(fieldName, (Double)value ));
+
+ } else if ( value instanceof Long ) {
+ entity.setField( new LongField(fieldName, (Long)value ));
+
+ } else if ( value instanceof List) {
+ entity.setField( listToListField( scope, fieldName, (List)value ));
+
+ } else if ( value instanceof Map ) {
+ entity.setField( new EntityObjectField( fieldName,
+ mapToEntity( scope, (Map<String, Object>)value ))); // recursion
+
+ } else {
+ throw new RuntimeException("Unknown type " + value.getClass().getName());
+ }
+ }
+
+ return entity;
+ }
+
+
+ private static ListField listToListField( String scope, String fieldName, List list ) {
+
+ if (list.isEmpty()) {
+ return new ListField( fieldName );
+ }
+
+ Object sample = list.get(0);
+
+ if ( sample instanceof Map ) {
+ return new ListField<Entity>( fieldName, processListForField( scope, list ));
+
+ } else if ( sample instanceof List ) {
+ return new ListField<List>( fieldName, processListForField( scope, list ));
+
+ } else if ( sample instanceof String ) {
+ return new ListField<String>( fieldName, (List<String>)list );
+
+ } else if ( sample instanceof Boolean ) {
+ return new ListField<Boolean>( fieldName, (List<Boolean>)list );
+
+ } else if ( sample instanceof Integer ) {
+ return new ListField<Integer>( fieldName, (List<Integer>)list );
+
+ } else if ( sample instanceof Double ) {
+ return new ListField<Double>( fieldName, (List<Double>)list );
+
+ } else if ( sample instanceof Long ) {
+ return new ListField<Long>( fieldName, (List<Long>)list );
+
+ } else {
+ throw new RuntimeException("Unknown type " + sample.getClass().getName());
+ }
+ }
+
+
+ private static List processListForField( String scope, List list ) {
+ if ( list.isEmpty() ) {
+ return list;
+ }
+ Object sample = list.get(0);
+
+ if ( sample instanceof Map ) {
+ List<Entity> newList = new ArrayList<Entity>();
+ for ( Map<String, Object> map : (List<Map<String, Object>>)list ) {
+ newList.add( mapToEntity( scope, map ) );
+ }
+ return newList;
+
+ } else if ( sample instanceof List ) {
+ return processListForField( scope, list ); // recursion
+
+ } else {
+ return list;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/QueryTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/QueryTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/QueryTest.java
new file mode 100644
index 0000000..fa46f4c
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/QueryTest.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.usergrid.persistence.query;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.usergrid.persistence.query.Query.SortDirection;
+import org.apache.usergrid.persistence.query.Query.SortPredicate;
+import org.apache.usergrid.persistence.exceptions.QueryParseException;
+import org.apache.usergrid.persistence.query.Query;
+import org.apache.usergrid.persistence.query.tree.AndOperand;
+import org.apache.usergrid.persistence.query.tree.ContainsOperand;
+import org.apache.usergrid.persistence.query.tree.Equal;
+import org.apache.usergrid.persistence.query.tree.FloatLiteral;
+import org.apache.usergrid.persistence.query.tree.GreaterThan;
+import org.apache.usergrid.persistence.query.tree.GreaterThanEqual;
+import org.apache.usergrid.persistence.query.tree.LessThan;
+import org.apache.usergrid.persistence.query.tree.LessThanEqual;
+import org.apache.usergrid.persistence.query.tree.LongLiteral;
+import org.apache.usergrid.persistence.query.tree.NotOperand;
+import org.apache.usergrid.persistence.query.tree.StringLiteral;
+import org.apache.usergrid.persistence.query.tree.WithinOperand;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+//@Concurrent()
+public class QueryTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger( QueryTest.class );
+
+
+ @Test
+ public void testQueryTree() throws Exception {
+ LOG.info( "testQuery" );
+
+ Query q = new Query();
+
+ try {
+ q.addFilter( "blah" );
+ fail( "'blah' shouldn't be a valid operation." );
+ }
+ catch ( RuntimeException e ) {
+ // this is correct
+ }
+
+ q.addFilter( "a=5" );
+ q.addFilter( "b='hello'" );
+ q.addFilter( "c < 7" );
+ q.addFilter( "d gt 5" );
+ // q.addFilter("e in 5,6");
+ q.addFilter( "f = 6.0" );
+ q.addFilter( "g = .05" );
+ q.addFilter( "loc within .05 of 5.0,6.0" );
+ q.addFilter( "not h eq 4" );
+
+ AndOperand and = ( AndOperand ) q.getRootOperand();
+
+ NotOperand not = ( NotOperand ) and.getRight();
+ Equal equal = ( Equal ) not.getOperation();
+ assertEquals( "h", equal.getProperty().getValue() );
+ assertEquals( 4.0f, ( ( LongLiteral ) equal.getLiteral() ).getValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ WithinOperand op = ( WithinOperand ) and.getRight();
+
+ assertEquals( "loc", op.getProperty().getValue() );
+ assertEquals( .05f, op.getDistance().getFloatValue(), 0 );
+ assertEquals( 5f, op.getLattitude().getFloatValue(), 0 );
+ assertEquals( 6f, op.getLongitude().getFloatValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ equal = ( Equal ) and.getRight();
+
+ assertEquals( "g", equal.getProperty().getValue() );
+ assertEquals( .05f, ( ( FloatLiteral ) equal.getLiteral() ).getValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ equal = ( Equal ) and.getRight();
+
+ assertEquals( "f", equal.getProperty().getValue() );
+ assertEquals( 6.0f, ( ( FloatLiteral ) equal.getLiteral() ).getValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ GreaterThan gt = ( GreaterThan ) and.getRight();
+
+ assertEquals( "d", gt.getProperty().getValue() );
+ assertEquals( 5, ( ( LongLiteral ) gt.getLiteral() ).getValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ LessThan lt = ( LessThan ) and.getRight();
+
+ assertEquals( "c", lt.getProperty().getValue() );
+ assertEquals( 7, ( ( LongLiteral ) lt.getLiteral() ).getValue(), 0 );
+
+ and = ( AndOperand ) and.getLeft();
+ equal = ( Equal ) and.getRight();
+
+ assertEquals( "b", equal.getProperty().getValue() );
+ assertEquals( "hello", ( ( StringLiteral ) equal.getLiteral() ).getValue() );
+
+ equal = ( Equal ) and.getLeft();
+
+ assertEquals( "a", equal.getProperty().getValue() );
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ @Test
+ public void testCodeEquals() {
+ Query query = new Query();
+ query.addEqualityFilter( "foo", "bar" );
+
+ Equal equal = ( Equal ) query.getRootOperand();
+
+ assertEquals( "foo", equal.getProperty().getValue() );
+ assertEquals( "bar", equal.getLiteral().getValue() );
+ }
+
+
+ @Test
+ public void testCodeLessThan() {
+ Query query = new Query();
+ query.addLessThanFilter( "foo", 5 );
+
+ LessThan equal = ( LessThan ) query.getRootOperand();
+
+ assertEquals( "foo", equal.getProperty().getValue() );
+ assertEquals( 5l, equal.getLiteral().getValue() );
+ }
+
+
+ @Test
+ public void testCodeLessThanEqual() {
+ Query query = new Query();
+ query.addLessThanEqualFilter( "foo", 5 );
+
+ LessThanEqual equal = ( LessThanEqual ) query.getRootOperand();
+
+ assertEquals( "foo", equal.getProperty().getValue() );
+ assertEquals( 5l, equal.getLiteral().getValue() );
+ }
+
+
+ @Test
+ public void testCodeGreaterThan() {
+ Query query = new Query();
+ query.addGreaterThanFilter( "foo", 5 );
+
+ GreaterThan equal = ( GreaterThan ) query.getRootOperand();
+
+ assertEquals( "foo", equal.getProperty().getValue() );
+ assertEquals( 5l, equal.getLiteral().getValue() );
+ }
+
+
+ @Test
+ public void testCodeGreaterThanEqual() {
+ Query query = new Query();
+ query.addGreaterThanEqualFilter( "foo", 5 );
+
+ GreaterThanEqual equal = ( GreaterThanEqual ) query.getRootOperand();
+
+ assertEquals( "foo", equal.getProperty().getValue() );
+ assertEquals( 5l, equal.getLiteral().getValue() );
+ }
+
+
+ @Test
+ public void testFromJson() throws QueryParseException {
+ String s = "{\"filter\":\"a contains 'ed'\"}";
+ Query q = Query.fromJsonString( s );
+ assertNotNull( q );
+
+ ContainsOperand contains = ( ContainsOperand ) q.getRootOperand();
+
+ assertEquals( "a", contains.getProperty().getValue() );
+ assertEquals( "ed", contains.getString().getValue() );
+ }
+
+
+ @Test
+ public void testCompoundQueryWithNot() throws QueryParseException {
+ String s = "name contains 'm' and not name contains 'grover'";
+ Query q = Query.fromQL( s );
+ assertNotNull( q );
+
+ AndOperand and = ( AndOperand ) q.getRootOperand();
+
+ ContainsOperand contains = ( ContainsOperand ) and.getLeft();
+ assertEquals( "name", contains.getProperty().getValue() );
+ assertEquals( "m", contains.getString().getValue() );
+
+ NotOperand not = ( NotOperand ) and.getRight();
+ contains = ( ContainsOperand ) not.getOperation();
+ assertEquals( "name", contains.getProperty().getValue() );
+ assertEquals( "grover", contains.getString().getValue() );
+ }
+
+
+ @Test
+ public void badGrammar() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * from where name = 'bob'";
+
+ String error = null;
+
+ try {
+ Query.fromQL( s );
+ }
+ catch ( QueryParseException qpe ) {
+ error = qpe.getMessage();
+ }
+ assertNotNull( error );
+ assertTrue( error.startsWith("The query cannot be parsed") );
+ }
+
+
+ @Test
+ public void testTruncation() {
+
+ Query query = new Query();
+ query.setLimit( Query.MAX_LIMIT * 2 );
+
+ assertEquals( Query.MAX_LIMIT, query.getLimit() );
+ }
+
+
+ @Test
+ public void testTruncationFromParams() throws QueryParseException {
+
+ HashMap<String, List<String>> params = new HashMap<String, List<String>>();
+
+ params.put( "limit", Collections.singletonList( "2000" ) );
+
+ Query query = Query.fromQueryParams( params );
+
+ assertEquals( Query.MAX_LIMIT, query.getLimit() );
+ }
+
+
+ @Test
+ public void badOrderByBadGrammar() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * where name = 'bob' order by";
+
+ String error = null;
+
+ try {
+ Query.fromQL( s );
+ }
+ catch ( QueryParseException qpe ) {
+ error = qpe.getMessage();
+ }
+
+ assertEquals( "The query cannot be parsed. The token '<EOF>' at column 13 on line 1 cannot be parsed", error );
+ }
+
+
+ @Test
+ public void badOrderByGrammarAsc() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * where name = 'bob' order by name asc";
+
+ Query q = Query.fromQL( s );
+
+ List<SortPredicate> sorts = q.getSortPredicates();
+
+ assertEquals( 1, sorts.size() );
+
+ assertEquals( "name", sorts.get( 0 ).getPropertyName() );
+ assertEquals( SortDirection.ASCENDING, sorts.get( 0 ).getDirection() );
+ }
+
+
+ @Test
+ public void badOrderByGrammarDesc() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * where name = 'bob' order by name desc";
+
+ Query q = Query.fromQL( s );
+
+ List<SortPredicate> sorts = q.getSortPredicates();
+
+ assertEquals( 1, sorts.size() );
+
+ assertEquals( "name", sorts.get( 0 ).getPropertyName() );
+ assertEquals( SortDirection.DESCENDING, sorts.get( 0 ).getDirection() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/GrammarTreeTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/GrammarTreeTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/GrammarTreeTest.java
new file mode 100644
index 0000000..10324d1
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/GrammarTreeTest.java
@@ -0,0 +1,608 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.usergrid.persistence.query.tree;
+
+
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.TokenRewriteStream;
+import org.junit.Test;
+import org.apache.usergrid.persistence.query.Query;
+import org.apache.usergrid.persistence.exceptions.QueryParseException;
+import org.apache.usergrid.persistence.query.ir.OrNode;
+
+import antlr.NoViableAltException;
+import org.apache.usergrid.persistence.query.tree.AndOperand;
+import org.apache.usergrid.persistence.query.tree.ContainsOperand;
+import org.apache.usergrid.persistence.query.tree.Equal;
+import org.apache.usergrid.persistence.query.tree.GreaterThan;
+import org.apache.usergrid.persistence.query.tree.GreaterThanEqual;
+import org.apache.usergrid.persistence.query.tree.LessThan;
+import org.apache.usergrid.persistence.query.tree.LessThanEqual;
+import org.apache.usergrid.persistence.query.tree.LongLiteral;
+import org.apache.usergrid.persistence.query.tree.NotOperand;
+import org.apache.usergrid.persistence.query.tree.Operand;
+import org.apache.usergrid.persistence.query.tree.OrOperand;
+import org.apache.usergrid.persistence.query.tree.QueryFilterLexer;
+import org.apache.usergrid.persistence.query.tree.QueryFilterParser;
+import org.apache.usergrid.persistence.query.tree.StringLiteral;
+import org.apache.usergrid.persistence.query.tree.UUIDLiteral;
+import org.apache.usergrid.persistence.query.tree.WithinOperand;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+/** @author tnine */
+public class GrammarTreeTest {
+
+ /** Simple test that constructs and AST from the ANTLR generated files */
+ @Test
+ public void equality() throws RecognitionException {
+
+ String queryString = "select * where a = 5";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ Equal equal = ( Equal ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Simple test that constructs and AST from the ANTLR generated files */
+ @Test
+ public void lessThan() throws RecognitionException {
+
+ String queryString = "select * where a < 5";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ LessThan equal = ( LessThan ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ // TODO Todd fix this.
+
+ queryString = "select * where a lt 5";
+
+ in = new ANTLRStringStream( queryString );
+ lexer = new QueryFilterLexer( in );
+ tokens = new TokenRewriteStream( lexer );
+ parser = new QueryFilterParser( tokens );
+
+ query = parser.ql().query;
+
+ root = query.getRootOperand();
+
+ equal = ( LessThan ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Simple test that constructs and AST from the ANTLR generated files */
+ @Test
+ public void lessThanEqual() throws RecognitionException {
+
+ String queryString = "select * where a <= 5";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ LessThanEqual equal = ( LessThanEqual ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ queryString = "select * where a lte 5";
+
+ in = new ANTLRStringStream( queryString );
+ lexer = new QueryFilterLexer( in );
+ tokens = new TokenRewriteStream( lexer );
+ parser = new QueryFilterParser( tokens );
+
+ query = parser.ql().query;
+
+ root = query.getRootOperand();
+
+ equal = ( LessThanEqual ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Simple test that constructs and AST from the ANTLR generated files */
+ @Test
+ public void greaterThan() throws RecognitionException {
+
+ String queryString = "select * where a > 5";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ GreaterThan equal = ( GreaterThan ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ queryString = "select * where a gt 5";
+
+ in = new ANTLRStringStream( queryString );
+ lexer = new QueryFilterLexer( in );
+ tokens = new TokenRewriteStream( lexer );
+ parser = new QueryFilterParser( tokens );
+
+ query = parser.ql().query;
+
+ root = query.getRootOperand();
+
+ equal = ( GreaterThan ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Simple test that constructs and AST from the ANTLR generated files */
+ @Test
+ public void greaterThanEqual() throws RecognitionException {
+
+ String queryString = "select * where a >= 5";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ GreaterThanEqual equal = ( GreaterThanEqual ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ queryString = "select * where a gte 5";
+
+ in = new ANTLRStringStream( queryString );
+ lexer = new QueryFilterLexer( in );
+ tokens = new TokenRewriteStream( lexer );
+ parser = new QueryFilterParser( tokens );
+
+ query = parser.ql().query;
+
+ root = query.getRootOperand();
+
+ equal = ( GreaterThanEqual ) root;
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 5, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Test basic && expression */
+ @Test
+ public void andExpression() throws RecognitionException {
+
+ String queryString = "select * where a = 1 and b > 2";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ AndOperand and = ( AndOperand ) root;
+
+ Equal equal = ( Equal ) and.getLeft();
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 1, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ GreaterThan greater = ( GreaterThan ) and.getRight();
+
+ assertEquals( "b", greater.getProperty().getValue() );
+ assertEquals( 2, ( ( LongLiteral ) greater.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Test basic || expression */
+ @Test
+ public void orExpression() throws RecognitionException {
+
+ String queryString = "select * where a = 1 or b > 2";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ OrOperand and = ( OrOperand ) root;
+
+ Equal equal = ( Equal ) and.getLeft();
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 1, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+
+ GreaterThan greater = ( GreaterThan ) and.getRight();
+
+ assertEquals( "b", greater.getProperty().getValue() );
+ assertEquals( 2, ( ( LongLiteral ) greater.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Test basic not expression */
+ @Test
+ public void notExpression() throws RecognitionException {
+
+ String queryString = "select * where not a = 1";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ NotOperand not = ( NotOperand ) root;
+
+ Equal equal = ( Equal ) not.getOperation();
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 1, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Test basic not expression */
+ @Test
+ public void complexExpression() throws RecognitionException {
+
+ String queryString = "select * where not a = 1";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Operand root = query.getRootOperand();
+
+ NotOperand not = ( NotOperand ) root;
+
+ Equal equal = ( Equal ) not.getOperation();
+
+ assertEquals( "a", equal.getProperty().getValue() );
+
+ assertEquals( 1, ( ( LongLiteral ) equal.getLiteral() ).getValue().intValue() );
+ }
+
+
+ /** Test basic || expression */
+ @Test
+ public void selectAll() throws RecognitionException {
+
+ String queryString = "select * where a = 1 or b > 2";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Set<String> identifiers = query.getSelectSubjects();
+
+ assertEquals( 0, identifiers.size() );
+ }
+
+
+ @Test
+ public void selectGeo() throws RecognitionException {
+ String queryString = "select * where a within .1 of -40.343666, 175.630917";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ WithinOperand operand = ( WithinOperand ) query.getRootOperand();
+
+ assertEquals( "a", operand.getProperty().getValue() );
+ assertEquals( .1f, operand.getDistance().getFloatValue(), 0 );
+ assertEquals( -40.343666f, operand.getLattitude().getFloatValue(), 0 );
+ assertEquals( 175.630917f, operand.getLongitude().getFloatValue(), 0 );
+ }
+
+
+ @Test
+ public void selectGeoWithInt() throws RecognitionException {
+ String queryString = "select * where a within 1 of -40.343666, 175.630917";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ WithinOperand operand = ( WithinOperand ) query.getRootOperand();
+
+ assertEquals( "a", operand.getProperty().getValue() );
+ assertEquals( 1, operand.getDistance().getFloatValue(), 0 );
+ assertEquals( -40.343666f, operand.getLattitude().getFloatValue(), 0 );
+ assertEquals( 175.630917f, operand.getLongitude().getFloatValue(), 0 );
+ }
+
+
+ @Test
+ public void selectDistance() throws RecognitionException {
+ String queryString = "select * where a contains 'foo'";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ ContainsOperand operand = ( ContainsOperand ) query.getRootOperand();
+
+ assertEquals( "a", operand.getProperty().getValue() );
+ assertEquals( "foo", operand.getString().getValue() );
+ }
+
+
+ @Test
+ public void selectField() throws RecognitionException {
+
+ String queryString = "select c where a = 1 or b > 2";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Set<String> identifiers = query.getSelectSubjects();
+
+ assertTrue( identifiers.contains( "c" ) );
+ }
+
+
+ @Test
+ public void selectRename() throws RecognitionException {
+
+ String queryString = "select {source:target} where a = 1 or b > 2";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Map<String, String> identifiers = query.getSelectAssignments();
+
+ assertEquals( "target", identifiers.get( "source" ) );
+ }
+
+
+ @Test
+ public void containsOr() throws Exception {
+ String queryString = "select * where keywords contains 'hot' or title contains 'hot'";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ OrOperand rootNode = ( OrOperand ) query.getRootOperand();
+
+ assertNotNull( rootNode );
+
+ ContainsOperand left = ( ContainsOperand ) rootNode.getLeft();
+
+ assertEquals( "keywords", left.getProperty().getValue() );
+
+ assertEquals( "hot", left.getString().getValue() );
+ assertEquals( "hot", left.getString().getEndValue() );
+
+ ContainsOperand right = ( ContainsOperand ) rootNode.getRight();
+
+ assertEquals( "title", right.getProperty().getValue() );
+
+ assertEquals( "hot", right.getString().getValue() );
+ assertEquals( "hot", right.getString().getEndValue() );
+ }
+
+
+ @Test
+ public void stringLower() throws Exception {
+ String queryString = "select * where title = 'Hot'";
+
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Equal rootNode = ( Equal ) query.getRootOperand();
+
+ assertEquals( "title", rootNode.getProperty().getValue() );
+ assertEquals( "hot", ( ( StringLiteral ) rootNode.getLiteral() ).getValue() );
+ }
+
+
+ @Test
+ public void nestedBooleanLogic() throws Exception {
+ String queryString = "select * where field1 = 'foo' AND (field2 = 'bar' OR field2 = 'baz')";
+
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ AndOperand rootNode = ( AndOperand ) query.getRootOperand();
+
+ //left should be field1
+ Equal field1Equal = ( Equal ) rootNode.getLeft();
+
+ assertEquals( "field1", field1Equal.getProperty().getValue() );
+ assertEquals( "foo", ( ( StringLiteral ) field1Equal.getLiteral() ).getValue() );
+
+
+ OrOperand orNode = ( OrOperand ) rootNode.getRight();
+
+ Equal field2Bar = ( Equal ) orNode.getLeft();
+ Equal field2Baz = ( Equal ) orNode.getRight();
+
+ assertEquals( "field2", field2Bar.getProperty().getValue() );
+ assertEquals( "bar", ( ( StringLiteral ) field2Bar.getLiteral() ).getValue() );
+
+ assertEquals( "field2", field2Baz.getProperty().getValue() );
+ assertEquals( "baz", ( ( StringLiteral ) field2Baz.getLiteral() ).getValue() );
+ }
+
+
+ @Test
+ public void uuidParse() throws RecognitionException {
+ String queryString = "select * where title = c6ee8a1c-3ef4-11e2-8861-02e81adcf3d0";
+
+ ANTLRStringStream in = new ANTLRStringStream( queryString );
+ QueryFilterLexer lexer = new QueryFilterLexer( in );
+ TokenRewriteStream tokens = new TokenRewriteStream( lexer );
+ QueryFilterParser parser = new QueryFilterParser( tokens );
+
+ Query query = parser.ql().query;
+
+ Equal rootNode = ( Equal ) query.getRootOperand();
+
+ assertEquals( "title", rootNode.getProperty().getValue() );
+ assertEquals( UUID.fromString( "c6ee8a1c-3ef4-11e2-8861-02e81adcf3d0" ),
+ ( ( UUIDLiteral ) rootNode.getLiteral() ).getValue() );
+ }
+
+
+ @Test
+ public void badOrderByGrammar() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * where name = 'bob' order by";
+
+ String error = null;
+
+ try {
+ Query.fromQL( s );
+ }
+ catch ( QueryParseException qpe ) {
+ error = qpe.getMessage();
+ }
+
+ assertEquals( "The query cannot be parsed. The token '<EOF>' " + "at column 13 on line 1 cannot be parsed",
+ error );
+ }
+
+ @Test
+ public void badOperand() throws QueryParseException {
+ // from isn't allowed
+ String s = "select * where name != 'bob'";
+
+ String error = null;
+
+ try {
+ Query.fromQL( s );
+ fail("should throw an exception");
+ }
+ catch ( RuntimeException qpe ) {
+ error = qpe.getMessage();
+ }
+
+ assertEquals( "NoViableAltException('!'@[1:1: Tokens : ( T__31 | T__32 | T__33 | T__34 | T__35 | T__36 | T__37 | T__38 | T__39 | T__40 | LT | LTE | EQ | GT | GTE | BOOLEAN | AND | OR | NOT | ASC | DESC | CONTAINS | WITHIN | OF | UUID | ID | LONG | FLOAT | STRING | WS );])",
+ error );
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/LongLiteralTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/LongLiteralTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/LongLiteralTest.java
new file mode 100644
index 0000000..b2e2eba
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/LongLiteralTest.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.usergrid.persistence.query.tree;
+
+
+import org.antlr.runtime.CommonToken;
+import org.apache.usergrid.persistence.query.tree.LongLiteral;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+
+/** @author tnine */
+public class LongLiteralTest {
+
+
+ /**
+ * Test method for {@link org.apache.usergrid.persistence.query.tree.LongLiteral#IntegerLiteral(org.antlr.runtime
+ * .Token)}.
+ */
+ @Test
+ public void longMin() {
+
+ long value = Long.MIN_VALUE;
+
+ String stringVal = String.valueOf( value );
+
+ LongLiteral literal = new LongLiteral( new CommonToken( 0, stringVal ) );
+
+ assertEquals( value, literal.getValue().longValue() );
+ }
+
+
+ /**
+ * Test method for {@link org.apache.usergrid.persistence.query.tree.LongLiteral#IntegerLiteral(org.antlr.runtime
+ * .Token)}.
+ */
+ @Test
+ public void longMax() {
+
+ long value = Long.MAX_VALUE;
+
+ String stringVal = String.valueOf( value );
+
+ LongLiteral literal = new LongLiteral( new CommonToken( 0, stringVal ) );
+
+ assertEquals( value, literal.getValue().longValue() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/StringLiteralTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/StringLiteralTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/StringLiteralTest.java
new file mode 100644
index 0000000..56ef54d
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/query/tree/StringLiteralTest.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.usergrid.persistence.query.tree;
+
+
+import org.antlr.runtime.CommonToken;
+import org.apache.usergrid.persistence.query.tree.StringLiteral;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+
+/** @author tnine */
+public class StringLiteralTest {
+
+ @Test
+ public void exactToken() {
+
+ StringLiteral literal = new StringLiteral( new CommonToken( 0, "'value'" ) );
+
+ assertEquals( "value", literal.getValue() );
+ assertEquals( "value", literal.getEndValue() );
+ }
+
+
+ @Test
+ public void exactString() {
+
+ StringLiteral literal = new StringLiteral( "value" );
+
+ assertEquals( "value", literal.getValue() );
+ assertEquals( "value", literal.getEndValue() );
+ }
+
+
+ @Test
+ public void wildcardToken() {
+
+ StringLiteral literal = new StringLiteral( new CommonToken( 0, "'*'" ) );
+
+ assertNull( literal.getValue() );
+ assertNull( literal.getEndValue() );
+ }
+
+
+ @Test
+ public void wildcardString() {
+
+ StringLiteral literal = new StringLiteral( "*" );
+
+ assertNull( literal.getValue() );
+ assertNull( literal.getEndValue() );
+ }
+
+
+ @Test
+ public void wildcardEndToken() {
+
+ StringLiteral literal = new StringLiteral( new CommonToken( 0, "'value*'" ) );
+
+ assertEquals( "value", literal.getValue() );
+ assertEquals( "value\uffff", literal.getEndValue() );
+ }
+
+
+ @Test
+ public void wildcardEndString() {
+
+ StringLiteral literal = new StringLiteral( "value*" );
+
+ assertEquals( "value", literal.getValue() );
+ assertEquals( "value\uffff", literal.getEndValue() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/utils/ElasticSearchRule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/utils/ElasticSearchRule.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/utils/ElasticSearchRule.java
new file mode 100644
index 0000000..0068fad
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/utils/ElasticSearchRule.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.usergrid.persistence.utils;
+
+import org.apache.usergrid.persistence.collection.util.AvailablePortFinder;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.NodeBuilder;
+import org.junit.rules.ExternalResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ElasticSearchRule extends ExternalResource {
+ private static final Logger log = LoggerFactory.getLogger( ElasticSearchRule.class );
+
+ private Client client;
+
+ @Override
+ protected void after() {
+ client.close();
+ }
+
+ @Override
+ protected void before() throws Throwable {
+
+ // use unique port and directory names so multiple instances of ES can run concurrently.
+ int port = AvailablePortFinder.getNextAvailable(2000);
+ Settings settings = ImmutableSettings.settingsBuilder()
+ .put("node.http.enabled", true)
+ .put("transport.tcp.port", port )
+ .put("path.logs","target/elasticsearch/logs_" + port )
+ .put("path.data","target/elasticsearch/data_" + port )
+ .put("gateway.type", "none" )
+ .put("index.store.type", "memory" )
+ .put("index.number_of_shards", 1 )
+ .put("index.number_of_replicas", 1).build();
+
+ Node node = NodeBuilder.nodeBuilder().local(true).settings(settings).node();
+ client = node.client();
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c0543f5f/stack/corepersistence/queryindex/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/resources/log4j.properties b/stack/corepersistence/queryindex/src/test/resources/log4j.properties
new file mode 100644
index 0000000..5d830ee
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/test/resources/log4j.properties
@@ -0,0 +1,15 @@
+log4j.rootLogger=INFO,stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %c{3}.%M(%L)<%t>- %m%n
+
+log4j.logger.org.safehaus.chop.plugin=DEBUG
+log4j.logger.org.safehaus.guicyfig=ERROR
+log4j.logger.org.safehaus.chop.api.store.amazon=DEBUG
+log4j.logger.org.apache.http=ERROR
+log4j.logger.com.amazonaws.request=ERROR
+
+log4j.logger.org.apache.usergrid=DEBUG
+
+log4j.logger.org.apache.usergrid.persistence.index=DEBUG