incubator-blur-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amccu...@apache.org
Subject [28/92] [abbrv] [partial] Fixed BLUR-126.
Date Tue, 11 Jun 2013 02:41:14 GMT
http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/IOUtil.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/IOUtil.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/IOUtil.java
new file mode 100644
index 0000000..64a611c
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/IOUtil.java
@@ -0,0 +1,30 @@
+package org.apache.blur.lucene.serializer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IOUtil {
+
+  private static final String UTF_8 = "UTF-8";
+
+  public static void writeString(DataOutput out, String s) throws IOException {
+    if (s == null) {
+      out.writeInt(-1);
+    }
+    byte[] bytes = s.getBytes(UTF_8);
+    out.writeInt(bytes.length);
+    out.write(bytes);
+  }
+
+  public static String readString(DataInput in) throws IOException {
+    int length = in.readInt();
+    if (length == -1) {
+      return null;
+    }
+    byte[] bs = new byte[length];
+    in.readFully(bs);
+    return new String(bs, UTF_8);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/MatchAllDocsQueryWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/MatchAllDocsQueryWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/MatchAllDocsQueryWritable.java
new file mode 100644
index 0000000..8828b00
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/MatchAllDocsQueryWritable.java
@@ -0,0 +1,40 @@
+package org.apache.blur.lucene.serializer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.lucene.search.MatchAllDocsQuery;
+
+public class MatchAllDocsQueryWritable extends AbtractQueryWritable<MatchAllDocsQuery> {
+
+  private MatchAllDocsQuery query;
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    out.writeFloat(query.getBoost());
+  }
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    float boost = in.readFloat();
+    query = new MatchAllDocsQuery();
+    query.setBoost(boost);
+  }
+
+  @Override
+  public MatchAllDocsQuery getQuery() {
+    return query;
+  }
+
+  @Override
+  public void setQuery(MatchAllDocsQuery query) {
+    this.query = query;
+  }
+
+  @Override
+  public Class<MatchAllDocsQuery> getType() {
+    return MatchAllDocsQuery.class;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/ProtoSerializer.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/ProtoSerializer.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/ProtoSerializer.java
new file mode 100644
index 0000000..37ac3a4
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/ProtoSerializer.java
@@ -0,0 +1,88 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.IOException;
+
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.hadoop.io.DataInputBuffer;
+import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.Version;
+
+public class ProtoSerializer {
+
+  public static void main(String[] args) throws ParseException, IOException {
+
+    QueryParser parser = new QueryParser(Version.LUCENE_40, "", new StandardAnalyzer(Version.LUCENE_40));
+
+    Query query = parser.parse("a:v1 b:v2 c:v3~ c:asda*asda");
+    
+    SuperQuery superQuery = new SuperQuery(query,ScoreType.SUPER,new Term("_primedoc_"));
+
+    QueryWritable queryWritable = new QueryWritable(superQuery);
+    DataOutputBuffer buffer = new DataOutputBuffer();
+    queryWritable.write(buffer);
+    buffer.close();
+
+    System.out.println(new String(buffer.getData(), 0, buffer.getLength()));
+
+    QueryWritable qw = new QueryWritable();
+
+    DataInputBuffer in = new DataInputBuffer();
+    in.reset(buffer.getData(), 0, buffer.getLength());
+    qw.readFields(in);
+
+    System.out.println("------------");
+    
+    System.out.println(qw.getQuery());
+    
+    System.out.println("------------");
+
+    while (true) {
+      run(superQuery);
+    }
+  }
+
+  private static void run(Query query) throws IOException {
+
+    DataOutputBuffer buffer = new DataOutputBuffer();
+    DataInputBuffer in = new DataInputBuffer();
+    QueryWritable outQw = new QueryWritable();
+    QueryWritable inQw = new QueryWritable();
+
+    long s = System.nanoTime();
+    int count = 100000;
+    for (int i = 0; i < count; i++) {
+      outQw.setQuery(query);
+      outQw.write(buffer);
+
+      in.reset(buffer.getData(), 0, buffer.getLength());
+      inQw.readFields(in);
+
+      buffer.reset();
+    }
+    long e = System.nanoTime();
+    System.out.println((e - s) / 1000000.0 / (double) count);
+    // System.out.println((e - s) / (double) count);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritable.java
new file mode 100644
index 0000000..9e9c227
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritable.java
@@ -0,0 +1,74 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.lucene.search.Query;
+
+public class QueryWritable extends AbtractQueryWritable<Query> {
+
+  private Query query;
+  private QueryWritableMapper lookup;
+
+  public QueryWritable() {
+
+  }
+
+  public QueryWritable(Query query) {
+    this.query = query;
+    this.lookup = QueryWritableMapper.lookup(query);
+  }
+
+  public Query getQuery() {
+    return query;
+  }
+
+  public void setQuery(Query query) {
+    this.query = query;
+    this.lookup = QueryWritableMapper.lookup(query);
+  }
+
+  public QueryWritableMapper getLookup() {
+    return lookup;
+  }
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    out.writeInt(lookup.getType());
+    AbtractQueryWritable<Query> writable = QueryWritableMapper.getNewQueryWritable(lookup, Query.class);
+    writable.setQuery(query);
+    writable.write(out);
+  }
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    int t = in.readInt();
+    lookup = QueryWritableMapper.lookup(t);
+    AbtractQueryWritable<Query> writable = QueryWritableMapper.getNewQueryWritable(lookup, Query.class);
+    writable.readFields(in);
+    query = writable.getQuery();
+  }
+
+  @Override
+  public Class<Query> getType() {
+    return Query.class;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritableMapper.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritableMapper.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritableMapper.java
new file mode 100644
index 0000000..268b676
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/QueryWritableMapper.java
@@ -0,0 +1,81 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.lucene.search.Query;
+
+public class QueryWritableMapper {
+
+  private static Map<Class<? extends Query>, QueryWritableMapper> queryToType = new ConcurrentHashMap<Class<? extends Query>, QueryWritableMapper>();
+  private static Map<Integer, QueryWritableMapper> idsToWritable = new ConcurrentHashMap<Integer, QueryWritableMapper>();
+
+  static {
+    register(0, new BooleanQueryWritable());
+    register(1, new TermQueryWritable());
+    register(2, new FuzzyQueryWritable());
+    register(3, new MatchAllDocsQueryWritable());
+    register(4, new WildcardQueryWritable());
+    register(5, new SuperQueryWritable());
+  }
+
+  private static synchronized void register(int id, AbtractQueryWritable<? extends Query> queryWritable) {
+    QueryWritableMapper qt = new QueryWritableMapper(id, queryWritable);
+    idsToWritable.put(id, qt);
+    queryToType.put(queryWritable.getType(), qt);
+  }
+
+  private final int id;
+  private final AbtractQueryWritable<? extends Query> queryWritable;
+
+  private QueryWritableMapper(int id, AbtractQueryWritable<? extends Query> queryWritable) {
+    this.id = id;
+    this.queryWritable = queryWritable;
+  }
+
+  public int getType() {
+    return id;
+  }
+
+  public AbtractQueryWritable<?> instance() {
+    return queryWritable.clone();
+  }
+
+  public static QueryWritableMapper lookup(int id) {
+    QueryWritableMapper type = idsToWritable.get(id);
+    if (type == null) {
+      throw new RuntimeException("Type [" + id + "] not found");
+    }
+    return type;
+  }
+
+  public static QueryWritableMapper lookup(Query query) {
+    QueryWritableMapper type = queryToType.get(query.getClass());
+    if (type == null) {
+      throw new RuntimeException("Type [" + query.getClass() + "] for query [" + query + "] not found");
+    }
+    return type;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <R extends Query> AbtractQueryWritable<R> getNewQueryWritable(QueryWritableMapper lookup, Class<R> clazz) {
+    QueryWritableMapper type = lookup(lookup.getType());
+    return (AbtractQueryWritable<R>) type.instance();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/SerializerUtil.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/SerializerUtil.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/SerializerUtil.java
new file mode 100644
index 0000000..a43ac0e
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/SerializerUtil.java
@@ -0,0 +1,53 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.UnicodeUtil;
+
+public class SerializerUtil {
+
+  public static void writeString(String s, DataOutput out) throws IOException {
+    BytesRef bytes = new BytesRef();
+    UnicodeUtil.UTF16toUTF8(s, 0, s.length(), bytes);
+    writeBytesRef(bytes, out);
+  }
+
+  public static void writeBytesRef(BytesRef bytes, DataOutput out) throws IOException {
+    out.writeInt(bytes.length);
+    out.write(bytes.bytes, bytes.offset, bytes.length);
+  }
+
+  public static String readString(DataInput in) throws IOException {
+    BytesRef bytes = readBytesRef(in);
+    return bytes.utf8ToString();
+  }
+
+  public static BytesRef readBytesRef(DataInput in) throws IOException {
+    int length = in.readInt();
+    BytesRef bytes = new BytesRef(length);
+    in.readFully(bytes.bytes);
+    bytes.offset = 0;
+    bytes.length = length;
+    return bytes;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/SuperQueryWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/SuperQueryWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/SuperQueryWritable.java
new file mode 100644
index 0000000..b93206d
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/SuperQueryWritable.java
@@ -0,0 +1,60 @@
+package org.apache.blur.lucene.serializer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Query;
+
+public class SuperQueryWritable extends AbtractQueryWritable<SuperQuery> {
+
+  private SuperQuery query;
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    QueryWritable queryWritable = new QueryWritable();
+    queryWritable.readFields(in);
+    Query subQuery = queryWritable.getQuery();
+    float boost = in.readFloat();
+    TermWritable termWritable = new TermWritable();
+    termWritable.readFields(in);
+    Term primeDocTerm = termWritable.getTerm();
+    String scoreType = IOUtil.readString(in);
+    
+    query = new SuperQuery(subQuery, ScoreType.valueOf(scoreType), primeDocTerm);
+    query.setBoost(boost);
+  }
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    Query subQuery = query.getQuery();
+    float boost = query.getBoost();
+    Term primeDocTerm = query.getPrimeDocTerm();
+    ScoreType scoreType = query.getScoreType();
+
+    // Start writing
+    new QueryWritable(subQuery).write(out);
+    out.writeFloat(boost);
+    new TermWritable(primeDocTerm).write(out);
+    IOUtil.writeString(out, scoreType.name());
+  }
+
+  @Override
+  public SuperQuery getQuery() {
+    return query;
+  }
+
+  @Override
+  public void setQuery(SuperQuery query) {
+    this.query = query;
+  }
+
+  @Override
+  public Class<SuperQuery> getType() {
+    return SuperQuery.class;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermQueryWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermQueryWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermQueryWritable.java
new file mode 100644
index 0000000..069eee7
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermQueryWritable.java
@@ -0,0 +1,67 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.TermQuery;
+
+public class TermQueryWritable extends AbtractQueryWritable<TermQuery> {
+
+  private TermQuery query;
+
+  public TermQuery getQuery() {
+    return query;
+  }
+
+  public void setQuery(TermQuery query) {
+    this.query = query;
+  }
+
+  public TermQueryWritable() {
+
+  }
+
+  public TermQueryWritable(TermQuery termQuery) {
+    this.query = termQuery;
+  }
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    out.writeFloat(query.getBoost());
+    Term term = query.getTerm();
+    new TermWritable(term).write(out);
+  }
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    float boost = in.readFloat();
+    TermWritable termWritable = new TermWritable();
+    termWritable.readFields(in);
+    query = new TermQuery(termWritable.getTerm());
+    query.setBoost(boost);
+  }
+
+  @Override
+  public Class<TermQuery> getType() {
+    return TermQuery.class;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermWritable.java
new file mode 100644
index 0000000..9c008b5
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/TermWritable.java
@@ -0,0 +1,62 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.hadoop.io.Writable;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.util.BytesRef;
+
+public class TermWritable implements Writable {
+
+  private Term term;
+
+  public TermWritable() {
+
+  }
+
+  public TermWritable(Term term) {
+    this.term = term;
+  }
+
+  public Term getTerm() {
+    return term;
+  }
+
+  public void setTerm(Term term) {
+    this.term = term;
+  }
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    String field = term.field();
+    BytesRef bytes = term.bytes();
+    SerializerUtil.writeString(field, out);
+    SerializerUtil.writeBytesRef(bytes, out);
+  }
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    String field = SerializerUtil.readString(in);
+    BytesRef bytes = SerializerUtil.readBytesRef(in);
+    term = new Term(field, bytes);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/lucene/serializer/WildcardQueryWritable.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/serializer/WildcardQueryWritable.java b/blur-query/src/main/java/org/apache/blur/lucene/serializer/WildcardQueryWritable.java
new file mode 100644
index 0000000..04028ed
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/lucene/serializer/WildcardQueryWritable.java
@@ -0,0 +1,61 @@
+package org.apache.blur.lucene.serializer;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.WildcardQuery;
+
+public class WildcardQueryWritable extends AbtractQueryWritable<WildcardQuery> {
+
+  private WildcardQuery query;
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    out.writeFloat(query.getBoost());
+    Term term = query.getTerm();
+    new TermWritable(term).write(out);
+  }
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    float boost = in.readFloat();
+    TermWritable termWritable = new TermWritable();
+    termWritable.readFields(in);
+    query = new WildcardQuery(termWritable.getTerm());
+    query.setBoost(boost);
+  }
+
+  @Override
+  public WildcardQuery getQuery() {
+    return query;
+  }
+
+  @Override
+  public void setQuery(WildcardQuery query) {
+    this.query = query;
+  }
+
+  @Override
+  public Class<WildcardQuery> getType() {
+    return WildcardQuery.class;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/main/java/org/apache/blur/util/BlurConstants.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/util/BlurConstants.java b/blur-query/src/main/java/org/apache/blur/util/BlurConstants.java
new file mode 100644
index 0000000..5239e18
--- /dev/null
+++ b/blur-query/src/main/java/org/apache/blur/util/BlurConstants.java
@@ -0,0 +1,28 @@
+package org.apache.blur.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+public class BlurConstants {
+  public static final String PRIME_DOC = "_prime_";
+  public static final String PRIME_DOC_VALUE = "true";
+  public static final String ROW_ID = "rowid";
+  public static final String RECORD_ID = "recordid";
+  public static final String SUPER = "super";
+  public static final String FAMILY = "family";
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/analysis/BlurAnalyzerTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/analysis/BlurAnalyzerTest.java b/blur-query/src/test/java/org/apache/blur/analysis/BlurAnalyzerTest.java
new file mode 100644
index 0000000..f974123
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/analysis/BlurAnalyzerTest.java
@@ -0,0 +1,152 @@
+package org.apache.blur.analysis;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.blur.thrift.generated.AlternateColumnDefinition;
+import org.apache.blur.thrift.generated.AnalyzerDefinition;
+import org.apache.blur.thrift.generated.ColumnDefinition;
+import org.apache.blur.thrift.generated.ColumnFamilyDefinition;
+import org.junit.Test;
+
+public class BlurAnalyzerTest {
+
+  private static final String STANDARD = "org.apache.lucene.analysis.standard.StandardAnalyzer";
+
+  @Test
+  public void testToAndFromJSONDef1() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef1());
+    String json = analyzer.toJSON();
+    BlurAnalyzer analyzer2 = BlurAnalyzer.create(json);
+    assertEquals(analyzer.getAnalyzerDefinition(), analyzer2.getAnalyzerDefinition());
+  }
+
+  @Test
+  public void testStoringOfFieldDef1() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef1());
+    assertFalse(analyzer.getFieldType("b.c.sub1").stored());
+    assertTrue(analyzer.getFieldType("b.c").stored());
+  }
+
+  @Test
+  public void testGetSubFieldsDef1() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef1());
+    assertNull(analyzer.getSubIndexNames("b.d"));
+    Set<String> subIndexNames = analyzer.getSubIndexNames("b.c");
+    TreeSet<String> set = new TreeSet<String>();
+    set.add("b.c.sub1");
+    set.add("b.c.sub2");
+    assertEquals(set, subIndexNames);
+  }
+
+  @Test
+  public void testFullTextFieldsDef1() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef1());
+    assertTrue(analyzer.isFullTextField("a.b"));
+    assertFalse(analyzer.isFullTextField("a.d"));
+  }
+
+  @Test
+  public void testToAndFromJSONDef2() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef2());
+    String json = analyzer.toJSON();
+    BlurAnalyzer analyzer2 = BlurAnalyzer.create(json);
+    assertEquals(analyzer.getAnalyzerDefinition(), analyzer2.getAnalyzerDefinition());
+  }
+
+  @Test
+  public void testStoringOfFieldDef2() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef2());
+    assertTrue(analyzer.getFieldType("a.b").stored());
+    assertTrue(analyzer.getFieldType("b.c").stored());
+  }
+
+  @Test
+  public void testGetSubFieldsDef2() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef2());
+    assertNull(analyzer.getSubIndexNames("b.d"));
+  }
+
+  @Test
+  public void testFullTextFieldsDef2() throws IOException {
+    BlurAnalyzer analyzer = new BlurAnalyzer(getDef2());
+    assertTrue(analyzer.isFullTextField("a.b"));
+    assertFalse(analyzer.isFullTextField("d.a"));
+  }
+
+  private AnalyzerDefinition getDef1() {
+
+    AnalyzerDefinition analyzerDefinition = new AnalyzerDefinition().setDefaultDefinition(
+        new ColumnDefinition(STANDARD, false, null)).setFullTextAnalyzerClassName(STANDARD);
+    Map<String, ColumnFamilyDefinition> colFamDefs = new HashMap<String, ColumnFamilyDefinition>();
+
+    ColumnFamilyDefinition aColFamDef;
+    Map<String, ColumnDefinition> aColDef;
+    Map<String, ColumnDefinition> bColDef;
+    Map<String, ColumnDefinition> cColDef;
+    Map<String, AlternateColumnDefinition> alternates;
+    ColumnFamilyDefinition bColFamDef;
+    ColumnFamilyDefinition cColFamDef;
+    
+    aColFamDef = new ColumnFamilyDefinition();
+    
+    aColDef = new HashMap<String, ColumnDefinition>();
+    aColDef.put("b", new ColumnDefinition(STANDARD, true, null));
+    aColFamDef.setColumnDefinitions(aColDef);
+    colFamDefs.put("a", aColFamDef);
+    
+    bColDef = new HashMap<String, ColumnDefinition>();
+
+    alternates = new HashMap<String, AlternateColumnDefinition>();
+    alternates.put("sub1", new AlternateColumnDefinition(STANDARD));
+    alternates.put("sub2", new AlternateColumnDefinition(STANDARD));
+    bColDef.put("c", new ColumnDefinition(STANDARD, true, alternates));
+
+    bColFamDef = new ColumnFamilyDefinition();
+    bColFamDef.setColumnDefinitions(bColDef);
+    colFamDefs.put("b", bColFamDef);
+    
+    cColFamDef = new ColumnFamilyDefinition();
+    cColDef = new HashMap<String, ColumnDefinition>();
+    cColDef.put("cint", new ColumnDefinition(BlurAnalyzer.TYPE.INTEGER.name(), true, null));
+    cColFamDef.setColumnDefinitions(cColDef);
+    
+    colFamDefs.put("c", cColFamDef);
+
+    analyzerDefinition.setColumnFamilyDefinitions(colFamDefs);
+    return analyzerDefinition;
+  }
+
+  private AnalyzerDefinition getDef2() {
+    AnalyzerDefinition analyzerDefinition = new AnalyzerDefinition().setDefaultDefinition(
+        new ColumnDefinition(STANDARD, false, null)).setFullTextAnalyzerClassName(STANDARD);
+    analyzerDefinition.putToColumnFamilyDefinitions("a",
+        new ColumnFamilyDefinition().setDefaultDefinition(new ColumnDefinition(STANDARD, true, null)));
+    return analyzerDefinition;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/search/FacetQueryTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/FacetQueryTest.java b/blur-query/src/test/java/org/apache/blur/lucene/search/FacetQueryTest.java
new file mode 100644
index 0000000..fadd0d5
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/FacetQueryTest.java
@@ -0,0 +1,105 @@
+package org.apache.blur.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.RAMDirectory;
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class FacetQueryTest {
+
+  private IndexReader reader;
+
+  @Before
+  public void setup() throws CorruptIndexException, LockObtainFailedException, IOException {
+    reader = createIndex();
+  }
+
+  @After
+  public void tearDown() {
+
+  }
+
+  @Test
+  public void testFacetQueryNoSuper() throws IOException {
+    BooleanQuery bq = new BooleanQuery();
+    bq.add(new TermQuery(new Term("f1", "value")), Occur.SHOULD);
+    bq.add(new TermQuery(new Term("f2", "v3")), Occur.SHOULD);
+
+    Query f1 = new TermQuery(new Term("f2", "v4"));
+
+    BooleanQuery f2 = new BooleanQuery();
+    f2.add(new TermQuery(new Term("f1", "value")), Occur.MUST);
+    f2.add(new TermQuery(new Term("f2", "v3")), Occur.MUST);
+
+    Query[] facets = new Query[] { f1, f2 };
+
+    AtomicLongArray counts = new AtomicLongArray(facets.length);
+    FacetQuery facetQuery = new FacetQuery(bq, facets, counts);
+
+    IndexSearcher indexSearcher = new IndexSearcher(reader);
+    indexSearcher.search(facetQuery, 10);
+
+    //@TODO add actual assertion
+    for (int i = 0; i < counts.length(); i++) {
+      System.out.println(counts.get(i));
+    }
+  }
+
+  private IndexReader createIndex() throws CorruptIndexException, LockObtainFailedException, IOException {
+    RAMDirectory directory = new RAMDirectory();
+    IndexWriterConfig conf = new IndexWriterConfig(LUCENE_VERSION, new KeywordAnalyzer());
+    IndexWriter writer = new IndexWriter(directory, conf);
+    FieldType fieldType = new FieldType();
+    fieldType.setStored(true);
+    fieldType.setIndexed(true);
+    fieldType.setOmitNorms(true);
+    for (int i = 0; i < 10; i++) {
+      Document document = new Document();
+      
+      document.add(new Field("f1", "value", fieldType));
+      document.add(new Field("f2", "v" + i, fieldType));
+      writer.addDocument(document);
+    }
+    writer.close();
+    return DirectoryReader.open(directory);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/search/RandomSuperQueryTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/RandomSuperQueryTest.java b/blur-query/src/test/java/org/apache/blur/lucene/search/RandomSuperQueryTest.java
new file mode 100644
index 0000000..ceaca80
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/RandomSuperQueryTest.java
@@ -0,0 +1,152 @@
+package org.apache.blur.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static junit.framework.Assert.assertTrue;
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.RAMDirectory;
+import org.junit.Test;
+
+public class RandomSuperQueryTest {
+
+  private static final int MOD_COLS_USED_FOR_SKIPPING = 3;
+  private static final int MAX_NUM_OF_DOCS = 10000;// 10000
+  private static final int MIN_NUM_COL_FAM = 3;// 3
+  private static final int MAX_NUM_COL_FAM = 20;// 20
+  private static final int MAX_NUM_DOCS_PER_COL_FAM = 25;// 25
+  private static final int MAX_NUM_COLS = 21;// 21
+  private static final int MIN_NUM_COLS = 3;// 3
+  private static final int MAX_NUM_OF_WORDS = 1000;
+  private static final int MOD_USED_FOR_SAMPLING = 7;//
+  private static final String PRIME_DOC = "_p_";
+  private static final String PRIME_DOC_VALUE = "_true_";
+
+  private Random seedGen = new Random(1);
+
+  @Test
+  public void testRandomSuperQuery() throws CorruptIndexException, IOException, InterruptedException, ParseException {
+    long seed = seedGen.nextLong();
+
+    Random random = new Random(seed);
+    Collection<Query> sampler = new HashSet<Query>();
+    System.out.print("Creating index... ");
+    System.out.flush();
+    Directory directory = createIndex(random, sampler);
+    IndexReader reader = DirectoryReader.open(directory);
+    System.out.print("Running searches [" + sampler.size() + "]... ");
+    System.out.flush();
+    assertTrue(!sampler.isEmpty());
+    IndexSearcher searcher = new IndexSearcher(reader);
+    long s = System.currentTimeMillis();
+    for (Query query : sampler) {
+      TopDocs topDocs = searcher.search(query, 10);
+      assertTrue("seed [" + seed + "] {" + query + "} {" + s + "}", topDocs.totalHits > 0);
+    }
+    long e = System.currentTimeMillis();
+    System.out.println("Finished in [" + (e - s) + "] ms");
+  }
+
+  private Directory createIndex(Random random, Collection<Query> sampler) throws CorruptIndexException, LockObtainFailedException, IOException {
+    Directory directory = new RAMDirectory();
+    String[] columnFamilies = genWords(random, MIN_NUM_COL_FAM, MAX_NUM_COL_FAM, "colfam");
+    Map<String, String[]> columns = new HashMap<String, String[]>();
+    for (int i = 0; i < columnFamilies.length; i++) {
+      columns.put(columnFamilies[i], genWords(random, MIN_NUM_COLS, MAX_NUM_COLS, "col"));
+    }
+    IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(LUCENE_VERSION, new StandardAnalyzer(LUCENE_VERSION)));
+    int numberOfDocs = random.nextInt(MAX_NUM_OF_DOCS) + 1;
+    for (int i = 0; i < numberOfDocs; i++) {
+      writer.addDocuments(generatSuperDoc(random, columns, sampler));
+    }
+    writer.close();
+    return directory;
+  }
+
+  private String[] genWords(Random random, int min, int max, String prefix) {
+    int numberOfColFam = random.nextInt(max - min) + min;
+    String[] str = new String[numberOfColFam];
+    for (int i = 0; i < numberOfColFam; i++) {
+      str[i] = genWord(random, prefix);
+    }
+    return str;
+  }
+
+  private List<Document> generatSuperDoc(Random random, Map<String, String[]> columns, Collection<Query> sampler) {
+    List<Document> docs = new ArrayList<Document>();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    for (String colFam : columns.keySet()) {
+      String[] cols = columns.get(colFam);
+      for (int i = 0; i < random.nextInt(MAX_NUM_DOCS_PER_COL_FAM); i++) {
+        Document doc = new Document();
+        for (String column : cols) {
+          if (random.nextInt() % MOD_COLS_USED_FOR_SKIPPING == 0) {
+            String word = genWord(random, "word");
+            doc.add(new StringField(colFam + "." + column, word, Store.YES));
+            if (random.nextInt() % MOD_USED_FOR_SAMPLING == 0) {
+              TermQuery termQuery = new TermQuery(new Term(colFam + "." + column, word));
+              SuperQuery query = new SuperQuery(termQuery, ScoreType.SUPER, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+              booleanQuery.add(query, Occur.MUST);
+            }
+          }
+        }
+        docs.add(doc);
+      }
+    }
+    if (!booleanQuery.clauses().isEmpty()) {
+      sampler.add(booleanQuery);
+    }
+    Document document = docs.get(0);
+    document.add(new StringField(PRIME_DOC, PRIME_DOC_VALUE, Store.NO));
+    return docs;
+  }
+
+  private String genWord(Random random, String prefix) {
+    return prefix + random.nextInt(MAX_NUM_OF_WORDS);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/search/SuperParserTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/SuperParserTest.java b/blur-query/src/test/java/org/apache/blur/lucene/search/SuperParserTest.java
new file mode 100644
index 0000000..5a33b46
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/SuperParserTest.java
@@ -0,0 +1,336 @@
+package org.apache.blur.lucene.search;
+
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
+import org.apache.blur.analysis.BlurAnalyzer;
+import org.apache.blur.thrift.generated.AnalyzerDefinition;
+import org.apache.blur.thrift.generated.ColumnDefinition;
+import org.apache.blur.thrift.generated.ColumnFamilyDefinition;
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.NumericRangeQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.util.BytesRef;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SuperParserTest {
+
+  private SuperParser parser;
+  private BlurAnalyzer analyzer;
+
+  @Before
+  public void setup() {
+    AnalyzerDefinition ad = new AnalyzerDefinition();
+    ad.setDefaultDefinition(new ColumnDefinition(StandardAnalyzer.class.getName(), true, null));
+    ColumnFamilyDefinition cfDef = new ColumnFamilyDefinition();
+    cfDef.putToColumnDefinitions("id_l", new ColumnDefinition("long", false, null));
+    cfDef.putToColumnDefinitions("id_d", new ColumnDefinition("double", false, null));
+    cfDef.putToColumnDefinitions("id_f", new ColumnDefinition("float", false, null));
+    cfDef.putToColumnDefinitions("id_i", new ColumnDefinition("integer", false, null));
+    ad.putToColumnFamilyDefinitions("a", cfDef);
+    analyzer = new BlurAnalyzer(ad);
+    parser = new SuperParser(LUCENE_VERSION, new BlurAnalyzer(new WhitespaceAnalyzer(LUCENE_VERSION)), true, null,  ScoreType.SUPER, new Term("_primedoc_"));
+  }
+
+  @Test
+  public void testParser1() throws ParseException {
+    Query query = parser.parse(" +super:<a:a d:e b:b> ");
+
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(new TermQuery(new Term("a", "a")), Occur.SHOULD);
+    booleanQuery.add(new TermQuery(new Term("d", "e")), Occur.SHOULD);
+    booleanQuery.add(new TermQuery(new Term("b", "b")), Occur.SHOULD);
+    SuperQuery superQuery = new SuperQuery(booleanQuery, ScoreType.SUPER, new Term("_primedoc_"));
+
+    BooleanQuery bq = new BooleanQuery();
+    bq.add(superQuery, Occur.MUST);
+    
+    assertEquals(bq, query);
+
+  }
+
+  @Test
+  public void testParser2() throws ParseException {
+    Query query = parser.parse("super:<c:c d:d>");
+
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(new TermQuery(new Term("c", "c")), Occur.SHOULD);
+    booleanQuery.add(new TermQuery(new Term("d", "d")), Occur.SHOULD);
+    SuperQuery superQuery = new SuperQuery(booleanQuery, ScoreType.SUPER, new Term("_primedoc_"));
+
+    BooleanQuery bq = new BooleanQuery();
+    bq.add(superQuery, Occur.SHOULD);
+
+    assertEquals(bq, query);
+  }
+
+  @Test
+  public void testParser3() throws ParseException {
+    Query query = parser.parse("a:a d:e b:b");
+
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(new TermQuery(new Term("a", "a")), Occur.SHOULD);
+    booleanQuery.add(new TermQuery(new Term("d", "e")), Occur.SHOULD);
+    booleanQuery.add(new TermQuery(new Term("b", "b")), Occur.SHOULD);
+    assertEquals(booleanQuery, query);
+  }
+
+  @Test
+  public void testParser4() throws ParseException {
+    Query query = parser.parse("super:<a:a d:e b:b>  - super:<c:c d:d>");
+
+    BooleanQuery booleanQuery1 = new BooleanQuery();
+    booleanQuery1.add(new TermQuery(new Term("a", "a")), Occur.SHOULD);
+    booleanQuery1.add(new TermQuery(new Term("d", "e")), Occur.SHOULD);
+    booleanQuery1.add(new TermQuery(new Term("b", "b")), Occur.SHOULD);
+
+    BooleanQuery booleanQuery2 = new BooleanQuery();
+    booleanQuery2.add(new TermQuery(new Term("c", "c")), Occur.SHOULD);
+    booleanQuery2.add(new TermQuery(new Term("d", "d")), Occur.SHOULD);
+
+    SuperQuery superQuery1 = new SuperQuery(booleanQuery1, ScoreType.SUPER, new Term("_primedoc_"));
+    SuperQuery superQuery2 = new SuperQuery(booleanQuery2, ScoreType.SUPER, new Term("_primedoc_"));
+
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(superQuery1, Occur.SHOULD);
+    booleanQuery.add(superQuery2, Occur.MUST_NOT);
+
+    assertEquals(booleanQuery, query);
+  }
+
+  @Test
+  public void testParser5() throws ParseException {
+
+    Query query = parser.parse("super:<a:a d:{e TO f} b:b test:hello\\<> - super:<c:c d:d>");
+
+    BooleanQuery booleanQuery1 = new BooleanQuery();
+    booleanQuery1.add(new TermQuery(new Term("a", "a")), Occur.SHOULD);
+    booleanQuery1.add(new TermRangeQuery("d", new BytesRef("e"), new BytesRef("f"), false, false), Occur.SHOULD);
+    booleanQuery1.add(new TermQuery(new Term("b", "b")), Occur.SHOULD);
+    // std analyzer took the "<" out
+    booleanQuery1.add(new TermQuery(new Term("test", "hello<")), Occur.SHOULD);
+
+    BooleanQuery booleanQuery2 = new BooleanQuery();
+    booleanQuery2.add(new TermQuery(new Term("c", "c")), Occur.SHOULD);
+    booleanQuery2.add(new TermQuery(new Term("d", "d")), Occur.SHOULD);
+
+    SuperQuery superQuery1 = new SuperQuery(booleanQuery1, ScoreType.SUPER, new Term("_primedoc_"));
+    SuperQuery superQuery2 = new SuperQuery(booleanQuery2, ScoreType.SUPER, new Term("_primedoc_"));
+
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(superQuery1, Occur.SHOULD);
+    booleanQuery.add(superQuery2, Occur.MUST_NOT);
+
+    assertEquals(booleanQuery, query);
+  }
+
+  @Test
+  public void testParser6() throws ParseException {
+    SuperParser parser = new SuperParser(LUCENE_VERSION, analyzer, true, null,  ScoreType.SUPER, new Term("_primedoc_"));
+    try {
+      parser.parse("super : <a:a d:{e TO d} b:b super:<test:hello\\<>> super:<c:c d:d>");
+      fail();
+    } catch (ParseException e) {
+      // should throw an error
+    }
+  }
+  
+  @Test
+  public void test7() throws ParseException {
+    Query q = parseSq("(a.b:cool) (+a.c:cool a.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc_m(tq("a.c", "cool")), bc(tq("a.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test8() throws ParseException {
+    Query q = parseSq("(a.b:cool) (a.c:cool a.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc(tq("a.c", "cool")), bc(tq("a.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test9() throws ParseException {
+    Query q = parseSq("a.b:cool (a.c:cool a.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc(tq("a.c", "cool")), bc(tq("a.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test10() throws ParseException {
+    Query q = parseSq("a.b:cool a.c:cool a.b:cool");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(tq("a.c", "cool")), bc(tq("a.b", "cool"))), q);
+  }
+
+  @Test
+  public void test11() throws ParseException {
+    Query q = parseSq("(a.b:cool) (+a.c:cool c.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc_m(tq("a.c", "cool")), bc(tq("c.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test12() throws ParseException {
+    Query q = parseSq("(a.b:cool) (a.c:cool c.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc(tq("a.c", "cool")), bc(tq("c.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test13() throws ParseException {
+    Query q = parseSq("a.b:cool (a.c:cool c.b:cool)");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(bq(bc(tq("a.c", "cool")), bc(tq("c.b", "cool"))))), q);
+  }
+
+  @Test
+  public void test14() throws ParseException {
+    Query q = parseSq("a.b:cool a.c:cool c.b:cool");
+    assertQuery(bq(bc(tq("a.b", "cool")), bc(tq("a.c", "cool")), bc(tq("c.b", "cool"))), q);
+  }
+
+  @Test
+  public void test15() throws ParseException {
+    Query q = parseSq("a.id_l:[0 TO 2]");
+    Query q1 = rq_i("a.id_l", 0L, 2L);
+    assertQuery(q1, q);
+  }
+  
+  @Test
+  public void test16() throws ParseException {
+    Query q = parseSq("a.id_d:[0 TO 2]");
+    assertQuery(rq_i("a.id_d", 0.0D, 2.0D), q);
+  }
+  
+  @Test
+  public void test17() throws ParseException {
+    Query q = parseSq("a.id_f:[0 TO 2]");
+    assertQuery(rq_i("a.id_f", 0.0F, 2.0F), q);
+  }
+  
+  @Test
+  public void test18() throws ParseException {
+    Query q = parseSq("a.id_i:[0 TO 2]");
+    Query q1 = rq_i("a.id_i", 0, 2);
+    assertQuery(q1, q);
+  }
+
+  public static BooleanClause bc_m(Query q) {
+    return new BooleanClause(q, Occur.MUST);
+  }
+
+  public static BooleanClause bc_n(Query q) {
+    return new BooleanClause(q, Occur.MUST_NOT);
+  }
+
+  public static BooleanClause bc(Query q) {
+    return new BooleanClause(q, Occur.SHOULD);
+  }
+
+  public static void assertQuery(Query expected, Query actual) {
+    System.out.println(expected);
+    System.out.println(actual);
+    assertEqualsQuery(expected, actual);
+  }
+
+  public static void assertEqualsQuery(Query expected, Query actual) {
+    assertEquals(expected.getClass(), actual.getClass());
+    if (expected instanceof BooleanQuery) {
+      assertEqualsBooleanQuery((BooleanQuery) expected, (BooleanQuery) actual);
+    } else if (expected instanceof SuperQuery) {
+      assertEqualsSuperQuery((SuperQuery) expected, (SuperQuery) actual);
+    } else if (expected instanceof TermQuery) {
+      assertEqualsTermQuery((TermQuery) expected, (TermQuery) actual);
+    } else if (expected instanceof NumericRangeQuery<?>) {
+      assertEqualsNumericRangeQuery((NumericRangeQuery<?>) expected, (NumericRangeQuery<?>) actual);
+    }
+    else {
+      fail("Type [" + expected.getClass() + "] not supported");
+    }
+  }
+
+  public static void assertEqualsTermQuery(TermQuery expected, TermQuery actual) {
+    Term term1 = expected.getTerm();
+    Term term2 = actual.getTerm();
+    assertEquals(term1, term2);
+  }
+
+  public static void assertEqualsNumericRangeQuery(NumericRangeQuery<?> expected, NumericRangeQuery<?> actual) {
+    assertEquals(expected, actual);
+  }
+  
+  public static void assertEqualsSuperQuery(SuperQuery expected, SuperQuery actual) {
+    assertEquals(expected.getQuery(), actual.getQuery());
+  }
+
+  public static void assertEqualsBooleanQuery(BooleanQuery expected, BooleanQuery actual) {
+    List<BooleanClause> clauses1 = expected.clauses();
+    List<BooleanClause> clauses2 = actual.clauses();
+    assertEqualsBooleanClause(clauses1, clauses2);
+  }
+
+  public static void assertEqualsBooleanClause(List<BooleanClause> clauses1, List<BooleanClause> clauses2) {
+    if (clauses1 == null && clauses2 == null) {
+      return;
+    }
+    if (clauses1 == null || clauses2 == null) {
+      fail();
+    }
+    if (clauses1.size() != clauses2.size()) {
+      fail();
+    }
+    int size = clauses1.size();
+    for (int i = 0; i < size; i++) {
+      assertEqualsBooleanClause(clauses1.get(i), clauses2.get(i));
+    }
+  }
+
+  public static void assertEqualsBooleanClause(BooleanClause booleanClause1, BooleanClause booleanClause2) {
+    assertEquals(booleanClause1.getOccur(), booleanClause2.getOccur());
+    assertEqualsQuery(booleanClause1.getQuery(), booleanClause2.getQuery());
+  }
+  
+  private Query rq_i(String field, float min, float max) {
+    return NumericRangeQuery.newFloatRange(field, min, max, true, true);
+  }
+  
+  private Query rq_i(String field, int min, int max) {
+    return NumericRangeQuery.newIntRange(field, min, max, true, true);
+  }
+  
+  private Query rq_i(String field, double min, double max) {
+    return NumericRangeQuery.newDoubleRange(field, min, max, true, true);
+  }
+
+  private Query rq_i(String field, long min, long max) {
+    return NumericRangeQuery.newLongRange(field, min, max, true, true);
+  }
+
+  private BooleanQuery bq(BooleanClause... bcs) {
+    BooleanQuery bq = new BooleanQuery();
+    for (BooleanClause bc : bcs) {
+      bq.add(bc);
+    }
+    return bq;
+  }
+
+  private SuperQuery sq(Query q) {
+    return new SuperQuery(q, ScoreType.SUPER, new Term("_primedoc_"));
+  }
+
+  private TermQuery tq(String field, String text) {
+    return new TermQuery(new Term(field, text));
+  }
+
+  private Query parseSq(String qstr) throws ParseException {
+    SuperParser superParser = new SuperParser(LUCENE_VERSION, analyzer, true, null,  ScoreType.SUPER, new Term("_primedoc_"));
+    return superParser.parse(qstr);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/search/SuperQueryTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/SuperQueryTest.java b/blur-query/src/test/java/org/apache/blur/lucene/search/SuperQueryTest.java
new file mode 100644
index 0000000..37346c9
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/SuperQueryTest.java
@@ -0,0 +1,199 @@
+package org.apache.blur.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static junit.framework.Assert.assertEquals;
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import org.apache.blur.lucene.search.FacetQuery;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.RAMDirectory;
+import org.junit.Test;
+
+public class SuperQueryTest {
+
+  private static final String PERSON_NAME = "person.name";
+  private static final String ADDRESS_STREET = "address.street";
+
+  private static final String PRIME_DOC = "_p_";
+  private static final String PRIME_DOC_VALUE = "_true_";
+
+  private static final String NAME1 = "jon";
+  private static final String NAME2 = "jane";
+  private static final String STREET2 = "main st";
+  private static final String STREET1 = "main";
+  private static final String ROW_ID = "rowid";
+
+  @Test
+  public void testSimpleSuperQuery() throws CorruptIndexException, IOException, InterruptedException {
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(new TermQuery(new Term(PERSON_NAME, NAME1))), Occur.MUST);
+    booleanQuery.add(wrapSuper(new TermQuery(new Term(ADDRESS_STREET, STREET1))), Occur.MUST);
+
+    Directory directory = createIndex();
+    IndexReader reader = DirectoryReader.open(directory);
+
+    IndexSearcher searcher = new IndexSearcher(reader);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(2, topDocs.totalHits);
+    assertEquals("1", searcher.doc(topDocs.scoreDocs[0].doc).get(ROW_ID));
+    assertEquals("3", searcher.doc(topDocs.scoreDocs[1].doc).get(ROW_ID));
+  }
+
+  @Test
+  public void testAggregateScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.AGGREGATE), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.AGGREGATE), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    printTopDocs(topDocs);
+    assertEquals(3, topDocs.totalHits);
+  }
+
+  @Test
+  public void testBestScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.BEST), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.BEST), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  private void printTopDocs(TopDocs topDocs) {
+    for (int i = 0; i < topDocs.totalHits; i++) {
+      System.out.println("doc " + i + " score " + topDocs.scoreDocs[i].score);
+    }
+
+  }
+
+  @Test
+  public void testConstantScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.CONSTANT), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.CONSTANT), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  @Test
+  public void testSuperScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.SUPER), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.SUPER), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  @Test
+  public void testSuperScoreTypesWithFacet() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.SUPER), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.SUPER), Occur.MUST);
+
+    BooleanQuery f1 = new BooleanQuery();
+    f1.add(new TermQuery(new Term(PERSON_NAME, NAME1)), Occur.MUST);
+    f1.add(new TermQuery(new Term(PERSON_NAME, NAME2)), Occur.MUST);
+
+    Query[] facets = new Query[] { new SuperQuery(f1, ScoreType.CONSTANT, new Term(PRIME_DOC, PRIME_DOC_VALUE)) };
+    AtomicLongArray counts = new AtomicLongArray(facets.length);
+    FacetQuery query = new FacetQuery(booleanQuery, facets, counts);
+
+    TopDocs topDocs = searcher.search(query, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  private static IndexSearcher createSearcher() throws Exception {
+    Directory directory = createIndex();
+    IndexReader reader = DirectoryReader.open(directory);
+    return new IndexSearcher(reader);
+  }
+
+  public static Directory createIndex() throws CorruptIndexException, LockObtainFailedException, IOException {
+    Directory directory = new RAMDirectory();
+    IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(LUCENE_VERSION, new StandardAnalyzer(LUCENE_VERSION)));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "1"), newStringField(PERSON_NAME, NAME1)),
+        newDocument(newStringField(ROW_ID, "1"), newStringField(PERSON_NAME, NAME1)), newDocument(newStringField(ROW_ID, "1"), newStringField(ADDRESS_STREET, STREET1)))));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "2"), newStringField(PERSON_NAME, NAME2)),
+        newDocument(newStringField(ROW_ID, "2"), newStringField(ADDRESS_STREET, STREET1)))));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "3"), newStringField(PERSON_NAME, NAME1)),
+        newDocument(newStringField(ROW_ID, "3"), newStringField(ADDRESS_STREET, STREET1)), newDocument(newStringField(ROW_ID, "3"), newStringField(ADDRESS_STREET, STREET2)))));
+    writer.close();
+    return directory;
+  }
+
+  private static List<Document> addPrime(List<Document> docs) {
+    Document document = docs.get(0);
+    document.add(new StringField(PRIME_DOC, PRIME_DOC_VALUE, Store.NO));
+    return docs;
+  }
+
+  private static Document newDocument(IndexableField... fields) {
+    Document document = new Document();
+    for (IndexableField field : fields) {
+      document.add(field);
+    }
+    return document;
+  }
+
+  private static IndexableField newStringField(String name, String value) {
+    return new StringField(name, value, Store.YES);
+  }
+
+  private Query wrapSuper(Query query) {
+    return new SuperQuery(query, ScoreType.AGGREGATE, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+  }
+
+  private Query wrapSuper(String field, String value, ScoreType scoreType) {
+    return new SuperQuery(new TermQuery(new Term(field, value)), scoreType, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java b/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
new file mode 100644
index 0000000..9358eb2
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
@@ -0,0 +1,84 @@
+package org.apache.blur.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.blur.lucene.search.IterablePaging;
+import org.apache.blur.lucene.search.IterablePaging.ProgressRef;
+import org.apache.blur.lucene.search.IterablePaging.TotalHitsRef;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Field.Index;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.store.RAMDirectory;
+import org.junit.Test;
+
+/**
+ * Testing the paging collector.
+ * 
+ * @author Aaron McCurry
+ */
+public class TestingPagingCollector {
+
+  @Test
+  public void testNothingYet() {
+
+  }
+
+  public static void main(String[] args) throws Exception {
+    IndexReader reader = getReaderFlatScore(13245);
+    IndexSearcher searcher = new IndexSearcher(reader);
+
+    TotalHitsRef totalHitsRef = new TotalHitsRef();
+    ProgressRef progressRef = new ProgressRef();
+
+    TermQuery query = new TermQuery(new Term("f1", "value"));
+    IterablePaging paging = new IterablePaging(new AtomicBoolean(true), searcher, query, 100, null, null);
+
+    for (ScoreDoc sd : paging.skipTo(90).gather(20).totalHits(totalHitsRef).progress(progressRef)) {
+
+      System.out.println("time [" + progressRef.queryTime() + "] " + "total hits [" + totalHitsRef.totalHits() + "] "
+          + "searches [" + progressRef.searchesPerformed() + "] " + "position [" + progressRef.currentHitPosition()
+          + "] " + "doc id [" + sd.doc + "] " + "score [" + sd.score + "]");
+    }
+  }
+
+  private static IndexReader getReaderFlatScore(int length) throws Exception {
+    RAMDirectory directory = new RAMDirectory();
+    IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(LUCENE_VERSION, new KeywordAnalyzer()));
+    for (int i = 0; i < length; i++) {
+      Document document = new Document();
+      document.add(new Field("f1", "value", Store.NO, Index.ANALYZED_NO_NORMS));
+      indexWriter.addDocument(document);
+    }
+    indexWriter.close();
+    return IndexReader.open(directory);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/lucene/serializer/QueryWritableTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/serializer/QueryWritableTest.java b/blur-query/src/test/java/org/apache/blur/lucene/serializer/QueryWritableTest.java
new file mode 100644
index 0000000..2b1e87c
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/lucene/serializer/QueryWritableTest.java
@@ -0,0 +1,38 @@
+package org.apache.blur.lucene.serializer;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.hadoop.io.DataInputBuffer;
+import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.junit.Test;
+
+public class QueryWritableTest {
+  
+  @Test
+  public void testTermQuery() throws IOException {
+    TermQuery query = new TermQuery(new Term("field","value"));
+    QueryWritable queryWritable = new QueryWritable();
+    queryWritable.setQuery(query);
+    DataOutputBuffer out = new DataOutputBuffer();
+    queryWritable.write(out);
+    byte[] data = out.getData();
+    int length = out.getLength();
+    
+    DataInputBuffer in = new DataInputBuffer();
+    in.reset(data, length);
+    
+    QueryWritable newQueryWritable = new QueryWritable();
+    newQueryWritable.readFields(in);
+    
+    Query termQuery = newQueryWritable.getQuery();
+    
+    assertEquals(query,termQuery);
+    
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/search/RandomSuperQueryTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/search/RandomSuperQueryTest.java b/blur-query/src/test/java/org/apache/blur/search/RandomSuperQueryTest.java
new file mode 100644
index 0000000..707916c
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/search/RandomSuperQueryTest.java
@@ -0,0 +1,152 @@
+package org.apache.blur.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static junit.framework.Assert.assertTrue;
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.RAMDirectory;
+import org.junit.Test;
+
+public class RandomSuperQueryTest {
+
+  private static final int MOD_COLS_USED_FOR_SKIPPING = 3;
+  private static final int MAX_NUM_OF_DOCS = 10000;// 10000
+  private static final int MIN_NUM_COL_FAM = 3;// 3
+  private static final int MAX_NUM_COL_FAM = 20;// 20
+  private static final int MAX_NUM_DOCS_PER_COL_FAM = 25;// 25
+  private static final int MAX_NUM_COLS = 21;// 21
+  private static final int MIN_NUM_COLS = 3;// 3
+  private static final int MAX_NUM_OF_WORDS = 1000;
+  private static final int MOD_USED_FOR_SAMPLING = 7;//
+  private static final String PRIME_DOC = "_p_";
+  private static final String PRIME_DOC_VALUE = "_true_";
+
+  private Random seedGen = new Random(1);
+
+  @Test
+  public void testRandomSuperQuery() throws CorruptIndexException, IOException, InterruptedException, ParseException {
+    long seed = seedGen.nextLong();
+
+    Random random = new Random(seed);
+    Collection<Query> sampler = new HashSet<Query>();
+    System.out.print("Creating index... ");
+    System.out.flush();
+    Directory directory = createIndex(random, sampler);
+    IndexReader reader = DirectoryReader.open(directory);
+    System.out.print("Running searches [" + sampler.size() + "]... ");
+    System.out.flush();
+    assertTrue(!sampler.isEmpty());
+    IndexSearcher searcher = new IndexSearcher(reader);
+    long s = System.currentTimeMillis();
+    for (Query query : sampler) {
+      TopDocs topDocs = searcher.search(query, 10);
+      assertTrue("seed [" + seed + "] {" + query + "} {" + s + "}", topDocs.totalHits > 0);
+    }
+    long e = System.currentTimeMillis();
+    System.out.println("Finished in [" + (e - s) + "] ms");
+  }
+
+  private Directory createIndex(Random random, Collection<Query> sampler) throws CorruptIndexException, LockObtainFailedException, IOException {
+    Directory directory = new RAMDirectory();
+    String[] columnFamilies = genWords(random, MIN_NUM_COL_FAM, MAX_NUM_COL_FAM, "colfam");
+    Map<String, String[]> columns = new HashMap<String, String[]>();
+    for (int i = 0; i < columnFamilies.length; i++) {
+      columns.put(columnFamilies[i], genWords(random, MIN_NUM_COLS, MAX_NUM_COLS, "col"));
+    }
+    IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(LUCENE_VERSION, new StandardAnalyzer(LUCENE_VERSION)));
+    int numberOfDocs = random.nextInt(MAX_NUM_OF_DOCS) + 1;
+    for (int i = 0; i < numberOfDocs; i++) {
+      writer.addDocuments(generatSuperDoc(random, columns, sampler));
+    }
+    writer.close();
+    return directory;
+  }
+
+  private String[] genWords(Random random, int min, int max, String prefix) {
+    int numberOfColFam = random.nextInt(max - min) + min;
+    String[] str = new String[numberOfColFam];
+    for (int i = 0; i < numberOfColFam; i++) {
+      str[i] = genWord(random, prefix);
+    }
+    return str;
+  }
+
+  private List<Document> generatSuperDoc(Random random, Map<String, String[]> columns, Collection<Query> sampler) {
+    List<Document> docs = new ArrayList<Document>();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    for (String colFam : columns.keySet()) {
+      String[] cols = columns.get(colFam);
+      for (int i = 0; i < random.nextInt(MAX_NUM_DOCS_PER_COL_FAM); i++) {
+        Document doc = new Document();
+        for (String column : cols) {
+          if (random.nextInt() % MOD_COLS_USED_FOR_SKIPPING == 0) {
+            String word = genWord(random, "word");
+            doc.add(new StringField(colFam + "." + column, word, Store.YES));
+            if (random.nextInt() % MOD_USED_FOR_SAMPLING == 0) {
+              TermQuery termQuery = new TermQuery(new Term(colFam + "." + column, word));
+              SuperQuery query = new SuperQuery(termQuery, ScoreType.SUPER, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+              booleanQuery.add(query, Occur.MUST);
+            }
+          }
+        }
+        docs.add(doc);
+      }
+    }
+    if (!booleanQuery.clauses().isEmpty()) {
+      sampler.add(booleanQuery);
+    }
+    Document document = docs.get(0);
+    document.add(new StringField(PRIME_DOC, PRIME_DOC_VALUE, Store.NO));
+    return docs;
+  }
+
+  private String genWord(Random random, String prefix) {
+    return prefix + random.nextInt(MAX_NUM_OF_WORDS);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/b0e26648/blur-query/src/test/java/org/apache/blur/search/SuperQueryTest.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/search/SuperQueryTest.java b/blur-query/src/test/java/org/apache/blur/search/SuperQueryTest.java
new file mode 100644
index 0000000..fffb348
--- /dev/null
+++ b/blur-query/src/test/java/org/apache/blur/search/SuperQueryTest.java
@@ -0,0 +1,199 @@
+package org.apache.blur.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static junit.framework.Assert.assertEquals;
+import static org.apache.blur.lucene.LuceneVersionConstant.LUCENE_VERSION;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import org.apache.blur.lucene.search.FacetQuery;
+import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.blur.thrift.generated.ScoreType;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.LockObtainFailedException;
+import org.apache.lucene.store.RAMDirectory;
+import org.junit.Test;
+
+public class SuperQueryTest {
+
+  private static final String PERSON_NAME = "person.name";
+  private static final String ADDRESS_STREET = "address.street";
+
+  private static final String PRIME_DOC = "_p_";
+  private static final String PRIME_DOC_VALUE = "_true_";
+
+  private static final String NAME1 = "jon";
+  private static final String NAME2 = "jane";
+  private static final String STREET2 = "main st";
+  private static final String STREET1 = "main";
+  private static final String ROW_ID = "rowid";
+
+  @Test
+  public void testSimpleSuperQuery() throws CorruptIndexException, IOException, InterruptedException {
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(new TermQuery(new Term(PERSON_NAME, NAME1))), Occur.MUST);
+    booleanQuery.add(wrapSuper(new TermQuery(new Term(ADDRESS_STREET, STREET1))), Occur.MUST);
+
+    Directory directory = createIndex();
+    IndexReader reader = DirectoryReader.open(directory);
+
+    IndexSearcher searcher = new IndexSearcher(reader);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(2, topDocs.totalHits);
+    assertEquals("1", searcher.doc(topDocs.scoreDocs[0].doc).get(ROW_ID));
+    assertEquals("3", searcher.doc(topDocs.scoreDocs[1].doc).get(ROW_ID));
+  }
+
+  @Test
+  public void testAggregateScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.AGGREGATE), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.AGGREGATE), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    printTopDocs(topDocs);
+    assertEquals(3, topDocs.totalHits);
+  }
+
+  @Test
+  public void testBestScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.BEST), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.BEST), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  private void printTopDocs(TopDocs topDocs) {
+    for (int i = 0; i < topDocs.totalHits; i++) {
+      System.out.println("doc " + i + " score " + topDocs.scoreDocs[i].score);
+    }
+
+  }
+
+  @Test
+  public void testConstantScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.CONSTANT), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.CONSTANT), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  @Test
+  public void testSuperScoreTypes() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.SUPER), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.SUPER), Occur.MUST);
+    TopDocs topDocs = searcher.search(booleanQuery, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  @Test
+  public void testSuperScoreTypesWithFacet() throws Exception {
+    IndexSearcher searcher = createSearcher();
+    BooleanQuery booleanQuery = new BooleanQuery();
+    booleanQuery.add(wrapSuper(PERSON_NAME, NAME1, ScoreType.SUPER), Occur.SHOULD);
+    booleanQuery.add(wrapSuper(ADDRESS_STREET, STREET1, ScoreType.SUPER), Occur.MUST);
+
+    BooleanQuery f1 = new BooleanQuery();
+    f1.add(new TermQuery(new Term(PERSON_NAME, NAME1)), Occur.MUST);
+    f1.add(new TermQuery(new Term(PERSON_NAME, NAME2)), Occur.MUST);
+
+    Query[] facets = new Query[] { new SuperQuery(f1, ScoreType.CONSTANT, new Term(PRIME_DOC, PRIME_DOC_VALUE)) };
+    AtomicLongArray counts = new AtomicLongArray(facets.length);
+    FacetQuery query = new FacetQuery(booleanQuery, facets, counts);
+
+    TopDocs topDocs = searcher.search(query, 10);
+    assertEquals(3, topDocs.totalHits);
+    printTopDocs(topDocs);
+  }
+
+  private static IndexSearcher createSearcher() throws Exception {
+    Directory directory = createIndex();
+    IndexReader reader = DirectoryReader.open(directory);
+    return new IndexSearcher(reader);
+  }
+
+  public static Directory createIndex() throws CorruptIndexException, LockObtainFailedException, IOException {
+    Directory directory = new RAMDirectory();
+    IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(LUCENE_VERSION, new StandardAnalyzer(LUCENE_VERSION)));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "1"), newStringField(PERSON_NAME, NAME1)),
+        newDocument(newStringField(ROW_ID, "1"), newStringField(PERSON_NAME, NAME1)), newDocument(newStringField(ROW_ID, "1"), newStringField(ADDRESS_STREET, STREET1)))));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "2"), newStringField(PERSON_NAME, NAME2)),
+        newDocument(newStringField(ROW_ID, "2"), newStringField(ADDRESS_STREET, STREET1)))));
+    writer.addDocuments(addPrime(Arrays.asList(newDocument(newStringField(ROW_ID, "3"), newStringField(PERSON_NAME, NAME1)),
+        newDocument(newStringField(ROW_ID, "3"), newStringField(ADDRESS_STREET, STREET1)), newDocument(newStringField(ROW_ID, "3"), newStringField(ADDRESS_STREET, STREET2)))));
+    writer.close();
+    return directory;
+  }
+
+  private static List<Document> addPrime(List<Document> docs) {
+    Document document = docs.get(0);
+    document.add(new StringField(PRIME_DOC, PRIME_DOC_VALUE, Store.NO));
+    return docs;
+  }
+
+  private static Document newDocument(IndexableField... fields) {
+    Document document = new Document();
+    for (IndexableField field : fields) {
+      document.add(field);
+    }
+    return document;
+  }
+
+  private static IndexableField newStringField(String name, String value) {
+    return new StringField(name, value, Store.YES);
+  }
+
+  private Query wrapSuper(Query query) {
+    return new SuperQuery(query, ScoreType.AGGREGATE, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+  }
+
+  private Query wrapSuper(String field, String value, ScoreType scoreType) {
+    return new SuperQuery(new TermQuery(new Term(field, value)), scoreType, new Term(PRIME_DOC, PRIME_DOC_VALUE));
+  }
+
+}


Mime
View raw message