blob: 72c640fc3c872c6ec074ce46272b5973ec3a855a [file] [log] [blame]
Index: src/org/apache/lucene/luke/core/HighFreqTerms.java
===================================================================
--- src/org/apache/lucene/luke/core/HighFreqTerms.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/HighFreqTerms.java (working copy)
@@ -100,10 +100,10 @@
}
/**
- *
- * @param reader
- * @param numTerms
- * @param field
+ * // TODO move this method to org.apache.lucene.misc.HighFreqTerms
+ * @param reader IndexReader
+ * @param numTerms the max number of terms
+ * @param fieldNames tye array of field names
* @return TermStats[] ordered by terms with highest docFreq first.
* @throws Exception
*/
Index: src/org/apache/lucene/luke/core/IndexInfo.java
===================================================================
--- src/org/apache/lucene/luke/core/IndexInfo.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/IndexInfo.java (working copy)
@@ -177,6 +177,7 @@
}
}
}
+
/**
* @return the reader
Index: src/org/apache/lucene/luke/core/TableComparator.java
===================================================================
--- src/org/apache/lucene/luke/core/TableComparator.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/TableComparator.java (working copy)
@@ -1,63 +0,0 @@
-package org.apache.lucene.luke.core;
-
-/*
- * 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.Comparator;
-
-import org.apache.pivot.collections.Dictionary;
-import org.apache.pivot.collections.Map;
-import org.apache.pivot.wtk.SortDirection;
-import org.apache.pivot.wtk.TableView;
-
-public class TableComparator implements Comparator<Map<String,String>> {
- private TableView tableView;
-
- public TableComparator(TableView fieldsTable) {
- if (fieldsTable == null) {
- throw new IllegalArgumentException();
- }
-
- this.tableView = fieldsTable;
- }
-
- @Override
- public int compare(Map<String,String> o1, Map<String,String> o2) {
- Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
-
- int result;
- if (sort.key.equals("name")) {
- // sort by name
- result = o1.get(sort.key).compareTo(o2.get(sort.key));
- } else if (sort.key.equals("termCount")) {
- // sort by termCount
- Integer c1 = Integer.parseInt(o1.get(sort.key));
- Integer c2 = Integer.parseInt(o2.get(sort.key));
- result = c1.compareTo(c2);
- } else {
- // other (ignored)
- result = 0;
- }
- //int result = o1.get("name").compareTo(o2.get("name"));
- //SortDirection sortDirection = tableView.getSort().get("name");
- SortDirection sortDirection = sort.value;
- result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
-
- return result * -1;
- }
-
-}
\ No newline at end of file
Index: src/org/apache/lucene/luke/core/TermStats.java
===================================================================
--- src/org/apache/lucene/luke/core/TermStats.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/TermStats.java (working copy)
@@ -26,13 +26,15 @@
public long totalTermFreq;
TermStats(String field, BytesRef termtext, int df) {
- this.termtext = (BytesRef)termtext.clone();
+ //this.termtext = (BytesRef)termtext.clone();
+ this.termtext = BytesRef.deepCopyOf(termtext);
this.field = field;
this.docFreq = df;
}
TermStats(String field, BytesRef termtext, int df, long tf) {
- this.termtext = (BytesRef)termtext.clone();
+ //this.termtext = (BytesRef)termtext.clone();
+ this.termtext = BytesRef.deepCopyOf(termtext);
this.field = field;
this.docFreq = df;
this.totalTermFreq = tf;
Index: src/org/apache/lucene/luke/core/Util.java
===================================================================
--- src/org/apache/lucene/luke/core/Util.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/Util.java (working copy)
@@ -19,11 +19,19 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.luke.core.decoders.*;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.MMapDirectory;
@@ -161,18 +169,20 @@
return sb.toString();
}
- public static String fieldFlags(IndexableField f) {
- if (f == null) {
- return "-----------";
- }
+ public static String fieldFlags(IndexableField f, FieldInfo info) {
+ //if (f == null) {
+ // return "-----------";
+ //}
StringBuffer flags = new StringBuffer();
- if (f != null && f.fieldType().indexed()) flags.append("I");
+ //if (f != null && f.fieldType().indexed()) flags.append("I");
+ if (info != null && info.isIndexed()) flags.append("I");
else flags.append("-");
if (f != null && f.fieldType().tokenized()) flags.append("T");
else flags.append("-");
if (f != null && f.fieldType().stored()) flags.append("S");
else flags.append("-");
- if (f != null && f.fieldType().storeTermVectors()) flags.append("V");
+ //if (f != null && f.fieldType().storeTermVectors()) flags.append("V");
+ if (info != null && info.hasVectors()) flags.append("V");
else flags.append("-");
if (f != null && f.fieldType().storeTermVectorOffsets()) flags.append("o");
else flags.append("-");
@@ -180,9 +190,13 @@
else flags.append("-");
if (f != null && f.fieldType().storeTermVectorPayloads()) flags.append("a");
else flags.append("-");
- IndexOptions opts = f.fieldType().indexOptions();
+ if (info != null && info.hasPayloads()) flags.append("P");
+ else flags.append("-");
+ //IndexOptions opts = f.fieldType().indexOptions();
+ IndexOptions opts = info.getIndexOptions();
// TODO: how to handle these codes
- if (f.fieldType().indexed() && opts != null) {
+ //if (f.fieldType().indexed() && opts != null) {
+ if (info.isIndexed() && opts != null) {
switch (opts) {
case DOCS_ONLY:
flags.append("1");
@@ -199,13 +213,32 @@
} else {
flags.append("-");
}
- if (f != null && f.fieldType().omitNorms()) flags.append("O");
+ //if (f != null && f.fieldType().omitNorms()) flags.append("O");
+ if (info != null && !info.hasNorms()) flags.append("O");
else flags.append("-");
+ // TODO lazy
+ flags.append("-");
+ if (f != null && f.binaryValue() != null) flags.append("B");
+ else flags.append("-");
return flags.toString();
}
-
+
+ public static String docValuesType(FieldInfo info) {
+ if (info == null || !info.hasDocValues() || info.getDocValuesType() == null) {
+ return "---";
+ }
+ return info.getDocValuesType().name();
+ }
+
+ public static String normType(FieldInfo info) {
+ if (info == null || !info.hasNorms() || info.getNormType() == null) {
+ return "---";
+ }
+ return info.getNormType().name();
+ }
+
public static Resolution getResolution(String key) {
if (key == null || key.trim().length() == 0) {
return Resolution.MILLISECOND;
@@ -270,4 +303,56 @@
return String.valueOf(len / 1048576);
}
}
+
+ public static float decodeNormValue(long v, String fieldName, TFIDFSimilarity sim) throws Exception {
+ try {
+ return sim.decodeNormValue(v);
+ } catch (Exception e) {
+ throw new Exception("ERROR decoding norm for field " + fieldName + ":" + e.toString());
+ }
+ }
+
+ public static long encodeNormValue(float v, String fieldName, TFIDFSimilarity sim) throws Exception {
+ try {
+ return sim.encodeNormValue(v);
+ } catch (Exception e) {
+ throw new Exception("ERROR encoding norm for field " + fieldName + ":" + e.toString());
+ }
+ }
+
+
+ public static List<Decoder> loadDecoders() {
+ List decoders = new ArrayList();
+ // default decoders
+ decoders.add(new BinaryDecoder());
+ decoders.add(new DateDecoder());
+ decoders.add(new NumDoubleDecoder());
+ decoders.add(new NumFloatDecoder());
+ decoders.add(new NumIntDecoder());
+ decoders.add(new NumLongDecoder());
+ decoders.add(new StringDecoder());
+
+ // load external decoders
+ try {
+ String extLoaders = System.getProperty("luke.ext.decoder.loader");
+ if (extLoaders != null) {
+ String[] classes = extLoaders.split(",");
+ for (String className : classes) {
+ Class clazz = Class.forName(className);
+ Class[] interfaces = clazz.getInterfaces();
+ if (Arrays.asList(interfaces).indexOf(DecoderLoader.class) < 0) {
+ throw new Exception(className + " is not a DecoderLoader.");
+ }
+ DecoderLoader loader = (DecoderLoader)clazz.newInstance();
+ List<Decoder> extDecoders = loader.loadDecoders();
+ for (Decoder dec : extDecoders) {
+ decoders.add(dec);
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return decoders;
+ }
}
Index: src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java (working copy)
@@ -19,23 +19,18 @@
import org.apache.lucene.document.Field;
import org.apache.lucene.luke.core.Util;
+import org.apache.lucene.util.BytesRef;
public class BinaryDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) throws Exception {
- byte[] data;
- if (value instanceof byte[]) {
- data = (byte[])value;
- } else {
- data = value.toString().getBytes();
- }
- return Util.bytesToHex(data, 0, data.length, false);
+ public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+ return Util.bytesToHex(value.bytes, 0, value.length, false);
}
@Override
public String decodeStored(String fieldName, Field value) throws Exception {
- return decodeTerm(fieldName, value);
+ return decodeTerm(fieldName, new BytesRef(value.stringValue()));
}
public String toString() {
Index: src/org/apache/lucene/luke/core/decoders/DateDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/DateDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/DateDecoder.java (working copy)
@@ -19,17 +19,18 @@
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
public class DateDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) throws Exception {
+ public String decodeTerm(String fieldName, BytesRef value) throws Exception {
return DateTools.stringToDate(value.toString()).toString();
}
@Override
public String decodeStored(String fieldName, Field value) throws Exception {
- return decodeTerm(fieldName, value.stringValue());
+ return decodeTerm(fieldName, new BytesRef(value.stringValue()));
}
public String toString() {
Index: src/org/apache/lucene/luke/core/decoders/Decoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/Decoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/Decoder.java (working copy)
@@ -18,9 +18,10 @@
*/
import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
public interface Decoder {
- public String decodeTerm(String fieldName, Object value) throws Exception;
+ public String decodeTerm(String fieldName, BytesRef value) throws Exception;
public String decodeStored(String fieldName, Field value) throws Exception;
}
Index: src/org/apache/lucene/luke/core/decoders/DecoderLoader.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/DecoderLoader.java (revision 0)
+++ src/org/apache/lucene/luke/core/decoders/DecoderLoader.java (working copy)
@@ -0,0 +1,24 @@
+package org.apache.lucene.luke.core.decoders;
+
+/*
+ * 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.List;
+
+public interface DecoderLoader {
+ public List<Decoder> loadDecoders();
+}
Index: src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java (working copy)
@@ -1,5 +1,22 @@
package org.apache.lucene.luke.core.decoders;
+/*
+ * 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 org.apache.lucene.document.Field;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.NumericUtils;
@@ -7,9 +24,8 @@
public class NumDoubleDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) {
- BytesRef ref = new BytesRef(value.toString());
- return Double.toString(NumericUtils.sortableLongToDouble(NumericUtils.prefixCodedToLong(ref)));
+ public String decodeTerm(String fieldName, BytesRef value) {
+ return Double.toString(NumericUtils.sortableLongToDouble(NumericUtils.prefixCodedToLong(value)));
}
@Override
@@ -18,7 +34,7 @@
}
public String toString() {
- return "numeric-double";
+ return "numeric double";
}
}
Index: src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java (working copy)
@@ -6,9 +6,9 @@
public class NumFloatDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) {
- BytesRef ref = new BytesRef(value.toString());
- return Float.toString(NumericUtils.sortableIntToFloat(NumericUtils.prefixCodedToInt(ref)));
+ public String decodeTerm(String fieldName, BytesRef value) {
+ //BytesRef ref = new BytesRef(value.toString());
+ return Float.toString(NumericUtils.sortableIntToFloat(NumericUtils.prefixCodedToInt(value)));
}
@Override
@@ -17,7 +17,7 @@
}
public String toString() {
- return "numeric-float";
+ return "numeric float";
}
}
Index: src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java (working copy)
@@ -24,9 +24,8 @@
public class NumIntDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) {
- BytesRef ref = new BytesRef(value.toString());
- return Integer.toString(NumericUtils.prefixCodedToInt(ref));
+ public String decodeTerm(String fieldName, BytesRef value) {
+ return Integer.toString(NumericUtils.prefixCodedToInt(value));
}
@Override
@@ -35,7 +34,7 @@
}
public String toString() {
- return "numeric-int";
+ return "numeric int";
}
}
Index: src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java (working copy)
@@ -24,9 +24,8 @@
public class NumLongDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) {
- BytesRef ref = new BytesRef(value.toString());
- return Long.toString(NumericUtils.prefixCodedToLong(ref));
+ public String decodeTerm(String fieldName, BytesRef value) {
+ return Long.toString(NumericUtils.prefixCodedToLong(value));
}
@Override
@@ -35,7 +34,7 @@
}
public String toString() {
- return "numeric-long";
+ return "numeric long";
}
}
Index: src/org/apache/lucene/luke/core/decoders/SolrDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/SolrDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/SolrDecoder.java (working copy)
@@ -24,8 +24,14 @@
import org.apache.lucene.document.Field;
import org.apache.lucene.luke.core.ClassFinder;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.CharsRef;
import org.apache.solr.schema.FieldType;
+/**
+ * NOT Used.
+ * The logic here has moved to org.apache.lucene.ext.SolrDecoderLoader.
+ */
public class SolrDecoder implements Decoder {
private static final String solr_prefix = "org.apache.solr.schema.";
@@ -86,8 +92,9 @@
name = type;
}
- public String decodeTerm(String fieldName, Object value) throws Exception {
- return fieldType.indexedToReadable(value.toString());
+ public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+ CharsRef chars = fieldType.indexedToReadable(value, new CharsRef());
+ return chars.toString();
}
public String decodeStored(String fieldName, Field value)
@@ -100,3 +107,4 @@
}
}
+
Index: src/org/apache/lucene/luke/core/decoders/StringDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/StringDecoder.java (revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/StringDecoder.java (working copy)
@@ -18,17 +18,18 @@
*/
import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
public class StringDecoder implements Decoder {
@Override
- public String decodeTerm(String fieldName, Object value) {
- return value != null ? value.toString() : "(null)";
+ public String decodeTerm(String fieldName, BytesRef value) {
+ return value != null ? value.utf8ToString() : "(null)";
}
@Override
public String decodeStored(String fieldName, Field value) {
- return decodeTerm(fieldName, value.stringValue());
+ return value.stringValue();
}
public String toString() {
Index: src/org/apache/lucene/luke/ext/SolrDecoderLoader.java
===================================================================
--- src/org/apache/lucene/luke/ext/SolrDecoderLoader.java (revision 0)
+++ src/org/apache/lucene/luke/ext/SolrDecoderLoader.java (working copy)
@@ -0,0 +1,81 @@
+package org.apache.lucene.luke.ext;
+
+/*
+ * 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 org.apache.lucene.document.Field;
+import org.apache.lucene.luke.core.ClassFinder;
+import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.core.decoders.DecoderLoader;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.CharsRef;
+import org.apache.solr.schema.FieldType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SolrDecoderLoader implements DecoderLoader {
+ private static final String solr_prefix = "org.apache.solr.schema.";
+
+ @Override
+ public List<Decoder> loadDecoders() {
+ List<Decoder> decoders = new ArrayList<Decoder>();
+ try {
+ Class[] classes = ClassFinder.getInstantiableSubclasses(FieldType.class);
+ if (classes == null || classes.length == 0) {
+ throw new ClassNotFoundException("Missing Solr types???");
+ }
+ for (Class cls : classes) {
+ FieldType ft = (FieldType) cls.newInstance();
+ if (cls.getName().startsWith(solr_prefix)) {
+ String name = "solr." + cls.getName().substring(solr_prefix.length());
+ decoders.add(new SolrDecoder(name, ft));
+ }
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return decoders;
+ }
+}
+
+class SolrDecoder implements Decoder {
+ private String name;
+ private FieldType fieldType;
+
+ public SolrDecoder(String name, FieldType fieldType) {
+ this.name = name;
+ this.fieldType = fieldType;
+ }
+
+ public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+ CharsRef chars = fieldType.indexedToReadable(value, new CharsRef());
+ return chars.toString();
+ }
+
+ public String decodeStored(String fieldName, Field value)
+ throws Exception {
+ return fieldType.storedToReadable(value);
+ }
+
+ public String toString() {
+ return name;
+ }
+
+}
+
Index: src/org/apache/lucene/luke/ui/DocumentsTab.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/DocumentsTab.bxml (revision 1655665)
+++ src/org/apache/lucene/luke/ui/DocumentsTab.bxml (working copy)
@@ -1,169 +1,259 @@
<?xml version="1.0" encoding="UTF-8"?>
<luke:DocumentsTab bxml:id="DocumentsTab"
- styles="{verticalSpacing:2,horizontalSpacing:2,padding:4,backgroundColor:11}"
xmlns:bxml="http://pivot.apache.org/bxml" xmlns:content="org.apache.pivot.wtk.content"
- xmlns="org.apache.pivot.wtk" xmlns:luke="org.apache.lucene.luke.ui">
+ xmlns="org.apache.pivot.wtk" xmlns:luke="org.apache.lucene.luke.ui"
+ orientation="vertical" splitRatio="0.30">
+ <bxml:define>
+ <bxml:include bxml:id="posAndOffsetsWindow" src="PosAndOffsetsWindow.bxml" />
+ </bxml:define>
+ <bxml:define>
+ <bxml:include bxml:id="tvWindow" src="TermVectorWindow.bxml" />
+ </bxml:define>
+ <bxml:define>
+ <bxml:include bxml:id="fieldDataWindow" src="FieldDataWindow.bxml" />
+ </bxml:define>
+ <bxml:define>
+ <bxml:include bxml:id="fieldNormWindow" src="FieldNormWindow.bxml" />
+ </bxml:define>
- <columns>
- <TablePane.Column width="1*" />
- </columns>
- <rows>
- <TablePane.Row>
- <FlowPane styles="{padding:10}">
- <BoxPane orientation="vertical">
- <Label text="%documentsTab_browseByDocNum" />
- <BoxPane>
- <Label text="Doc. #:" />
- <Label text="0" />
- <PushButton preferredHeight="20" action="prevDoc">
- <buttonData>
- <content:ButtonData icon="/img/prev.png" />
- </buttonData>
- </PushButton>
- <TextInput preferredWidth="48" bxml:id="docNum" />
- <PushButton preferredHeight="20" action="nextDoc">
- <buttonData>
- <content:ButtonData icon="/img/next.png" />
- </buttonData>
- </PushButton>
- <Label bxml:id="maxDocs" text="?" />
+ <top>
+ <SplitPane orientation="horizontal" splitRatio="0.20" styles="{useShadow:true}">
+ <left>
+ <Border styles="{padding:1}">
+ <content>
+ <TablePane styles="{verticalSpacing:1,horizontalSpacing:1,padding:5,backgroundColor:11}">
+ <columns>
+ <TablePane.Column width="1*" />
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <BoxPane orientation="vertical">
+ <Label text="%documentsTab_browseByDocNum" styles="{padding:2,font:{bold:true}}"/>
+ <Label text="Doc. #" styles="{padding:2}"/>
+ <BoxPane orientation="horizontal">
+ <Label text="0" styles="{padding:2}"/>
+ <PushButton preferredHeight="20" action="prevDoc">
+ <buttonData>
+ <content:ButtonData icon="/img/prev.png" />
+ </buttonData>
+ </PushButton>
+ <TextInput preferredWidth="48" bxml:id="docNum" />
+ <PushButton preferredHeight="20" action="nextDoc">
+ <buttonData>
+ <content:ButtonData icon="/img/next.png" />
+ </buttonData>
+ </PushButton>
+ <Label bxml:id="maxDocs" text="?" styles="{padding:2}"/>
+ </BoxPane>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+ </Border>
+ </left>
+ <right>
+ <SplitPane orientation="horizontal" splitRatio="0.50" styles="{useShadow:true}">
+ <left>
+ <Border styles="{padding:1}">
+ <content>
+ <TablePane styles="{verticalSpacing:2,horizontalSpacing:1,padding:5,backgroundColor:11}">
+ <columns>
+ <TablePane.Column width="1*" />
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <BoxPane orientation="vertical">
+ <Label text="%documentsTab_browseByTerm" styles="{padding:1,font:{bold:true}}"/>
+ <Label text="%documentsTab_selectField" styles="{wrapText:true}"/>
+ <Label text="%documentsTab_enterTermHint" styles="{wrapText:true}"/>
+ <ListButton bxml:id="fieldsList" listSize="20" />
+ <Label text="%documentsTab_term" />
+ <BoxPane>
+ <PushButton buttonData="%documentsTab_firstTerm"
+ action="showFirstTerm" />
+ <TextInput bxml:id="termText" />
+ <PushButton action="showNextTerm">
+ <buttonData>
+ <content:ButtonData icon="/img/next.png" />
+ </buttonData>
+ </PushButton>
+ </BoxPane>
+ </BoxPane>
+ </TablePane.Row>
- </BoxPane>
- </BoxPane>
+ <TablePane.Row>
+ <BoxPane>
+ <Label text="%documentsTab_decodedValue" />
+ <TextArea bxml:id="decText" />
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+ </Border>
+ </left>
+ <right>
+ <Border styles="{padding:1}">
+ <content>
+ <TablePane styles="{verticalSpacing:2,horizontalSpacing:1,padding:5,backgroundColor:11}">
+ <columns>
+ <TablePane.Column width="1*" />
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <BoxPane orientation="vertical">
+ <Label text="%documentsTab_browseDocsWithTerm" styles="{padding:1,font:{bold:true}}"/>
+ <Label text="%documentsTab_selectTerm" styles="{wrapText:true}"/>
+ <BoxPane>
+ <!--Label text="%documentsTab_document" /-->
+ <PushButton buttonData="%documentsTab_firstDoc" action="showFirstTermDoc" />
+ <PushButton action="showNextTermDoc">
+ <buttonData>
+ <content:ButtonData icon="/img/next.png" />
+ </buttonData>
+ </PushButton>
- <BoxPane orientation="vertical">
- <Label text="%documentsTab_browseByTerm" />
- <Label text="%documentsTab_enterTermHint" />
- <BoxPane>
- <PushButton buttonData="%documentsTab_firstTerm"
- action="showFirstTerm" />
- <Label text="%documentsTab_term" />
- <ListButton bxml:id="fieldsList" listSize="20" />
- <TextInput bxml:id="termText" />
- <PushButton action="showNextTerm">
- <buttonData>
- <content:ButtonData icon="/img/next.png" />
- </buttonData>
- </PushButton>
- </BoxPane>
- </BoxPane>
+ <Label text=" ("/>
+ <Label bxml:id="tdNum" text="?" />
+ <Label text=" of " />
+ <Label bxml:id="tdMax" text="?" />
+ <Label text=" documents )" />
+ </BoxPane>
+ </BoxPane>
+ </TablePane.Row>
+ <TablePane.Row>
+ <BoxPane orientation="vertical">
+ <BoxPane>
+ <Label text="%documentsTab_termFreqInDoc" />
+ <Label bxml:id="tFreq" text="?" />
+ </BoxPane>
+ <PushButton bxml:id="bPos" buttonData="%documentsTab_showPositions"
+ action="showPositions" />
+ </BoxPane>
+ </TablePane.Row>
- <!-- second row -->
- <Label text="%documentsTab_decodedValue" />
- <TextArea bxml:id="decText" />
+ <TablePane.Row>
+ <Separator/>
+ </TablePane.Row>
- <Separator />
- <BoxPane orientation="vertical">
- <BoxPane>
- <Label text="%documentsTab_browseDocsWithTerm" />
- <Label text="( " />
- <Label bxml:id="dFreq" text="0" />
- <Label text=" documents)" />
- </BoxPane>
+ <TablePane.Row>
+ <BoxPane>
+ <PushButton buttonData="%documentsTab_showAllDocs"
+ action="showAllTermDoc"/>
+ <BoxPane>
+ <PushButton action="deleteTermDoc">
+ <buttonData>
+ <content:ButtonData icon="/img/delete.gif" />
+ </buttonData>
+ </PushButton>
+ <Label text="%documentsTab_deleteAllDocs" styles="{padding:1}"/>
+ </BoxPane>
+ </BoxPane>
+ </TablePane.Row>
- <BoxPane>
- <Label text="%documentsTab_document" />
- <Label bxml:id="tdNum" text="?" />
- <Label text=" of " />
- <Label bxml:id="tdMax" text="?" />
- <PushButton buttonData="%documentsTab_firstDoc" action="showFirstTermDoc" />
- <PushButton action="showNextTermDoc">
- <buttonData>
- <content:ButtonData icon="/img/next.png" />
- </buttonData>
- </PushButton>
- </BoxPane>
+ </rows>
+ </TablePane>
+ </content>
+ </Border>
+ </right>
+ </SplitPane>
+ </right>
+ </SplitPane>
+ </top>
- </BoxPane>
- <BoxPane orientation="vertical">
- <PushButton buttonData="%documentsTab_showAllDocs"
- action="showAllTermDoc" />
- <PushButton buttonData="%documentsTab_deleteAllDocs"
- action="deleteTermDoc">
- <buttonData>
- <content:ButtonData icon="/img/delete.gif" />
- </buttonData>
- </PushButton>
- </BoxPane>
- <Label text=" " />
- <Label text="%documentsTab_termFreqInDoc" />
-
- <Label bxml:id="tFreq" text="?" />
- <PushButton bxml:id="bPos" buttonData="%documentsTab_showPositions"
- action="showPositions" />
- </FlowPane>
- </TablePane.Row>
- <TablePane.Row>
- <TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
- <columns>
- <TablePane.Column width="1*" />
- <TablePane.Column />
- </columns>
- <rows>
- <TablePane.Row>
- <FlowPane>
- <Label text="Doc #:" />
- <Label bxml:id="docNum2" text="?" />
- <Label text=" " />
- </FlowPane>
- <FlowPane>
- <TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
- <columns>
- <TablePane.Column />
- <TablePane.Column />
- <TablePane.Column />
- <TablePane.Column />
- <TablePane.Column />
- <TablePane.Column />
- </columns>
- <rows>
- <TablePane.Row>
- <Label text="Flags: " />
- <Label text=" I - Indexed " />
- <Label text=" T - Tokenized " />
- <Label text=" S - Stored " />
- <Label text=" V - Term Vector " />
- <Label text=" (o - offsets; p - positions) " />
- </TablePane.Row>
- <TablePane.Row>
- <TablePane.Filler />
-
- <Label text=" O - Omit Norms " />
- <Label text=" f - Omit TF " />
- <Label text=" L - Lazy " />
- <Label text=" B - Binary " />
- </TablePane.Row>
- </rows>
- </TablePane>
- </FlowPane>
- </TablePane.Row>
- </rows>
- </TablePane>
- </TablePane.Row>
- <TablePane.Row height="1*">
- <ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
- <view>
- <TableView bxml:id="docTable">
+ <bottom>
+ <TablePane styles="{verticalSpacing:5,horizontalSpacing:1,padding:5,backgroundColor:11}">
+ <columns>
+ <TablePane.Column width="1*" />
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <TablePane>
<columns>
- <TableView.Column name="field"
- headerData="%documentsTab_docTable_col1" />
- <TableView.Column name="itsvopfolb"
- headerData="%documentsTab_docTable_col2" />
- <TableView.Column name="norm"
- headerData="%documentsTab_docTable_col3" />
- <TableView.Column name="value"
- headerData="%documentsTab_docTable_col4" width="1*" />
+ <TablePane.Column width="1*" />
+ <TablePane.Column />
</columns>
+ <rows>
+ <TablePane.Row>
+ <FlowPane>
+ <Label text="Doc #:" />
+ <Label bxml:id="docNum2" text="?" />
+ <Label text=" " />
+ </FlowPane>
+ <FlowPane>
+ <TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
+ <columns>
+ <TablePane.Column />
+ <TablePane.Column />
+ <TablePane.Column />
+ <TablePane.Column />
+ <TablePane.Column />
+ <TablePane.Column />
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <Label text="Flags: " />
+ <Label text=" I - Indexed " />
+ <Label text=" T - Tokenized " />
+ <Label text=" S - Stored " />
+ <Label text=" V - Term Vector " />
+ <Label text=" (o - offsets; p - positions; a - payloads) " />
+ </TablePane.Row>
+ <TablePane.Row>
+ <TablePane.Filler />
+ <Label text=" P - Payloads" />
+ <Label text=" t - Index options" />
+ <Label text=" O - Omit Norms " />
+ <!--Label text=" f - Omit TF " /-->
+ <Label text=" L - Lazy " />
+ <Label text=" B - Binary " />
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </FlowPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </TablePane.Row>
+ <TablePane.Row height="1*">
+ <Border styles="{padding:1}">
+ <content>
+ <ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
+ <view>
+ <TableView bxml:id="docTable">
+ <columns>
+ <TableView.Column name="name"
+ headerData="%documentsTab_docTable_col1" />
+ <TableView.Column name="itsvopatolb"
+ headerData="%documentsTab_docTable_col2" />
+ <TableView.Column name="docvaluestype"
+ headerData="%documentsTab_docTable_col3" />
+ <TableView.Column name="norm"
+ headerData="%documentsTab_docTable_col4" />
+ <TableView.Column name="value"
+ headerData="%documentsTab_docTable_col5" width="1*" />
+ </columns>
- </TableView>
- </view>
- <columnHeader>
- <TableViewHeader tableView="$docTable" />
- </columnHeader>
- </ScrollPane>
- </TablePane.Row>
- </rows>
+ </TableView>
+ </view>
+ <columnHeader>
+ <TableViewHeader tableView="$docTable" />
+ </columnHeader>
+ </ScrollPane>
+ </content>
+ </Border>
+ </TablePane.Row>
+ <TablePane.Row>
+ <BoxPane orientation="vertical">
+ <Label text="%documentsTab_indexOptionsNote1" styles="{wrapText:true}"/>
+ <Label text="%documentsTab_indexOptionsNote2" styles="{wrapText:true}"/>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </bottom>
</luke:DocumentsTab>
Index: src/org/apache/lucene/luke/ui/DocumentsTab.java
===================================================================
--- src/org/apache/lucene/luke/ui/DocumentsTab.java (revision 1655665)
+++ src/org/apache/lucene/luke/ui/DocumentsTab.java (working copy)
@@ -17,8 +17,9 @@
* limitations under the License.
*/
-import java.io.IOException;
+import java.io.*;
import java.net.URL;
+import java.util.Arrays;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
@@ -41,31 +42,25 @@
import org.apache.lucene.luke.core.Util;
import org.apache.lucene.luke.core.decoders.Decoder;
import org.apache.lucene.luke.ui.LukeWindow.LukeMediator;
+import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
+import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.Bindable;
-import org.apache.pivot.collections.ArrayList;
-import org.apache.pivot.collections.HashMap;
-import org.apache.pivot.collections.List;
-import org.apache.pivot.collections.Map;
+import org.apache.pivot.collections.*;
import org.apache.pivot.util.Resources;
import org.apache.pivot.util.concurrent.Task;
import org.apache.pivot.util.concurrent.TaskExecutionException;
import org.apache.pivot.util.concurrent.TaskListener;
-import org.apache.pivot.wtk.Action;
-import org.apache.pivot.wtk.Component;
-import org.apache.pivot.wtk.Label;
-import org.apache.pivot.wtk.ListButton;
-import org.apache.pivot.wtk.TablePane;
-import org.apache.pivot.wtk.TableView;
-import org.apache.pivot.wtk.TaskAdapter;
-import org.apache.pivot.wtk.TextArea;
-import org.apache.pivot.wtk.TextInput;
+import org.apache.pivot.wtk.*;
-public class DocumentsTab extends TablePane implements Bindable {
+public class DocumentsTab extends SplitPane implements Bindable {
private int iNum;
@BXML
@@ -91,6 +86,20 @@
@BXML
private TextArea decText;
+ @BXML
+ private PushButton bPos;
+ @BXML
+ private PosAndOffsetsWindow posAndOffsetsWindow;
+
+ @BXML
+ private TermVectorWindow tvWindow;
+
+ @BXML
+ private FieldDataWindow fieldDataWindow;
+
+ @BXML
+ private FieldNormWindow fieldNormWindow;
+
private java.util.List<String> fieldNames = null;
// this gets injected by LukeWindow at init
@@ -99,7 +108,8 @@
private Resources resources;
private TermsEnum te;
- private DocsAndPositionsEnum td;
+ //private DocsAndPositionsEnum td;
+ private DocsEnum td;
private String fld;
private Term lastTerm;
@@ -218,6 +228,15 @@
fieldsList.setSelectedIndex(0);
}
maxDocs.setText(String.valueOf(ir.maxDoc() - 1));
+
+ bPos.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ showPositionsWindow();
+ }
+ });
+
+ addlListenerToDocTable();
}
private void showDoc(int incr) {
@@ -242,6 +261,11 @@
}
docNum.setText(String.valueOf(iNum));
+ td = null;
+ tdNum.setText("?");
+ tFreq.setText("?");
+ tdMax.setText("?");
+
org.apache.lucene.util.Bits live = ar.getLiveDocs();
if (live == null || live.get(iNum)) {
Task<Object> populateTableTask = new Task<Object>() {
@@ -314,7 +338,7 @@
public void popTableWithDoc(int docid, Document doc) {
docNum.setText(String.valueOf(docid));
- List<Map<String,String>> tableData = new ArrayList<Map<String,String>>();
+ List<Map<String,Object>> tableData = new ArrayList<Map<String,Object>>();
docTable.setTableData(tableData);
// putProperty(table, "doc", doc);
@@ -326,10 +350,9 @@
docNum2.setText(String.valueOf(docid));
for (int i = 0; i < indexFields.size(); i++) {
- Map<String,String> row = new HashMap<String,String>();
-
IndexableField[] fields = doc.getFields(indexFields.get(i));
- if (fields == null) {
+ if (fields == null || fields.length == 0) {
+ Map<String,Object> row = new HashMap<String,Object>();
tableData.add(row);
addFieldRow(row, indexFields.get(i), null, docid);
continue;
@@ -339,6 +362,7 @@
// System.out.println("f.len=" + fields[j].getBinaryLength() +
// ", doc.len=" + doc.getBinaryValue(indexFields[i]).length);
// }
+ Map<String,Object> row = new HashMap<String,Object>();
tableData.add(row);
addFieldRow(row, indexFields.get(i), fields[j], docid);
}
@@ -345,7 +369,14 @@
}
}
- private void addFieldRow(Map<String,String> row, String fName, IndexableField field, int docid) {
+ private static final String FIELDROW_KEY_NAME = "name";
+ private static final String FIELDROW_KEY_FLAGS = "itsvopatolb";
+ private static final String FIELDROW_KEY_DVTYPE = "docvaluestype";
+ private static final String FIELDROW_KEY_NORM = "norm";
+ private static final String FIELDROW_KEY_VALUE = "value";
+ private static final String FIELDROW_KEY_FIELD = "field";
+
+ private void addFieldRow(Map<String,Object> row, String fName, IndexableField field, int docid) {
java.util.Map<String,Decoder> decoders = lukeMediator.getDecoders();
Decoder defDecoder = lukeMediator.getDefDecoder();
@@ -353,29 +384,32 @@
// putProperty(row, "field", f);
// putProperty(row, "fName", fName);
- row.put("field", fName);
- row.put("itsvopfolb", Util.fieldFlags(f));
+ row.put(FIELDROW_KEY_FIELD, field);
+ row.put(FIELDROW_KEY_NAME, fName);
+ row.put(FIELDROW_KEY_FLAGS, Util.fieldFlags(f, infos.fieldInfo(fName)));
+ row.put(FIELDROW_KEY_DVTYPE, Util.docValuesType(infos.fieldInfo(fName)));
+
// if (f == null) {
// setBoolean(cell, "enabled", false);
// }
- if (f != null) {
+ if (fName != null) {
try {
FieldInfo info = infos.fieldInfo(fName);
if (info.hasNorms()) {
NumericDocValues norms = ar.getNormValues(fName);
- String val = Long.toString(norms.get(docid));
- row.put("norm", String.valueOf(norms.get(docid)));
+ String norm = String.valueOf(norms.get(docid)) + " (" + Util.normType(info) + ")";
+ row.put(FIELDROW_KEY_NORM, norm);
} else {
- row.put("norm", "---");
+ row.put(FIELDROW_KEY_NORM, "---");
}
} catch (IOException ioe) {
ioe.printStackTrace();
- row.put("norm", "!?!");
+ row.put(FIELDROW_KEY_NORM, "!?!");
}
} else {
- row.put("norm", "---");
+ row.put(FIELDROW_KEY_NORM, "---");
// setBoolean(cell, "enabled", false);
}
@@ -395,15 +429,16 @@
if (f.fieldType().stored()) {
text = dec.decodeStored(f.name(), f);
} else {
- text = dec.decodeTerm(f.name(), text);
+ //text = dec.decodeTerm(f.name(), text);
+ text = dec.decodeTerm(f.name(), f.binaryValue());
}
} catch (Throwable e) {
// TODO:
// setColor(cell, "foreground", Color.RED);
}
- row.put("value", Util.escape(text));
+ row.put(FIELDROW_KEY_VALUE, Util.escape(text));
} else {
- row.put("value", "<not present or not stored>");
+ row.put(FIELDROW_KEY_VALUE, "<not present or not stored>");
// setBoolean(cell, "enabled", false);
}
}
@@ -428,7 +463,7 @@
try {
fld = (String) fieldsList.getSelectedItem();
- System.out.println("fld:" + fld);
+ //System.out.println("fld:" + fld);
Terms terms = MultiFields.getTerms(ir, fld);
te = terms.iterator(null);
BytesRef term = te.next();
@@ -472,7 +507,7 @@
@Override
public void taskExecuted(Task<Object> task) {
try {
- DocsAndPositionsEnum td = MultiFields.getTermPositionsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
+ DocsEnum td = MultiFields.getTermDocsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
td.nextDoc();
tdNum.setText("1");
DocumentsTab.this.td = td;
@@ -549,7 +584,7 @@
}
- private void showTerm(final Term t) {
+ protected void showTerm(final Term t) {
if (t == null) {
// TODO:
// showStatus("No terms?!");
@@ -571,7 +606,8 @@
String s = null;
boolean decodeErr = false;
try {
- s = dec.decodeTerm(t.field(), t.text());
+ //s = dec.decodeTerm(t.field(), t.text());
+ s = dec.decodeTerm(t.field(), t.bytes());
} catch (Throwable e) {
s = e.getMessage();
decodeErr = true;
@@ -580,7 +616,8 @@
termText.setText(t.text());
if (!s.equals(t.text())) {
- decText.setText(s);
+ String decoded = s + " (by " + dec.toString() + ")";
+ decText.setText(decoded);
if (decodeErr) {
// setColor(rawText, "foreground", Color.RED);
@@ -613,14 +650,11 @@
try {
int freq = ir.docFreq(t);
- dFreq.setText(String.valueOf(freq));
-
tdMax.setText(String.valueOf(freq));
} catch (Exception e) {
e.printStackTrace();
// TODO:
// showStatus(e.getMessage());
- dFreq.setText("?");
}
// ai.setActive(false);
}
@@ -670,17 +704,20 @@
String rawString = rawTerm != null ? rawTerm.utf8ToString() : null;
if (te == null || !DocumentsTab.this.fld.equals(fld) || !text.equals(rawString)) {
+ // seek for requested term
Terms terms = MultiFields.getTerms(ir, fld);
te = terms.iterator(null);
DocumentsTab.this.fld = fld;
status = te.seekCeil(new BytesRef(text));
- if (status.equals(SeekStatus.FOUND)) {
+ if (status.equals(SeekStatus.FOUND) || status.equals(SeekStatus.NOT_FOUND)) {
+ // precise term or different term after the requested term was found.
rawTerm = te.term();
} else {
rawTerm = null;
}
} else {
+ // move to next term
rawTerm = te.next();
}
if (rawTerm == null) { // proceed to next field
@@ -696,7 +733,7 @@
te = terms.iterator(null);
rawTerm = te.next();
DocumentsTab.this.fld = fld;
- break;
+ //break;
}
}
if (rawTerm == null) {
@@ -744,6 +781,7 @@
try {
Document doc = ir.document(td.docID());
docNum.setText(String.valueOf(td.docID()));
+ iNum = td.docID();
tFreq.setText(String.valueOf(td.freq()));
@@ -767,6 +805,38 @@
}
+ private void showPositionsWindow() {
+ try {
+ if (td == null) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_docNotSelected"), getWindow());
+ } else {
+ // create new Enum to show positions info
+ DocsAndPositionsEnum pe = MultiFields.getTermPositionsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
+ if (pe == null) {
+ Alert.alert(MessageType.INFO, (String)resources.get("documentsTab_msg_positionNotIndexed"), getWindow());
+ } else {
+ // enumerate docId to the current doc
+ while(pe.docID() != td.docID()) {
+ if (pe.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) {
+ // this must not happen!
+ Alert.alert(MessageType.ERROR, (String)resources.get("documentsTab_msg_noPositionInfo"), getWindow());
+ }
+ }
+ try {
+ posAndOffsetsWindow.initPositionInfo(pe, lastTerm);
+ posAndOffsetsWindow.open(getDisplay(), getWindow());
+ } catch (Exception e) {
+ // TODO:
+ e.printStackTrace();
+ }
+ }
+ }
+ } catch (Exception e) {
+ // TODO
+ e.printStackTrace();
+ }
+ }
+
public void showAllTermDoc() {
final IndexReader ir = lukeMediator.getIndexInfo().getReader();
if (ir == null) {
@@ -825,4 +895,178 @@
}
+ private void addlListenerToDocTable() {
+ docTable.getComponentMouseButtonListeners().add(new ComponentMouseButtonListener.Adapter() {
+ @Override
+ public boolean mouseClick(Component component, Mouse.Button button, int i, int i1, int i2) {
+ final Map<String, Object> row = (Map<String, Object>) docTable.getSelectedRow();
+ if (row == null) {
+ System.out.println("No field selected.");
+ return false;
+ }
+ if (button.name().equals(Mouse.Button.RIGHT.name())) {
+ MenuPopup popup = new MenuPopup();
+ Menu menu = new Menu();
+ Menu.Section section = new Menu.Section();
+ Menu.Item item1 = new Menu.Item(resources.get("documentsTab_docTable_popup_menu1"));
+ item1.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ String name = (String)row.get(FIELDROW_KEY_NAME);
+ try {
+ Terms terms = ir.getTermVector(iNum, name);
+ if (terms == null) {
+ String msg = "DocId: " + iNum + ", field: " + name;
+ Alert.alert(MessageType.WARNING, "Term vector not avalable for " + msg, getWindow());
+ } else {
+ showTermVectorWindow(name, terms);
+ }
+ } catch (IOException e) {
+ // TODO:
+ e.printStackTrace();
+ }
+
+ }
+ });
+ Menu.Item item2 = new Menu.Item(resources.get("documentsTab_docTable_popup_menu2"));
+ item2.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ String name = (String)row.get(FIELDROW_KEY_NAME);
+ IndexableField field = (IndexableField)row.get(FIELDROW_KEY_FIELD);
+ if (field == null) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_noDataAvailable"), getWindow());
+ } else {
+ showFieldDataWindow(name, field);
+ }
+ }
+ });
+ Menu.Item item3 = new Menu.Item(resources.get("documentsTab_docTable_popup_menu3"));
+ item3.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ String name = (String)row.get(FIELDROW_KEY_NAME);
+ IndexableField field = (IndexableField)row.get(FIELDROW_KEY_FIELD);
+ FieldInfo info = infos.fieldInfo(name);
+ if (field == null) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_noDataAvailable"), getWindow());
+ } else if (!info.isIndexed() || !info.hasNorms()) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_noNorm"), getWindow());
+ } else {
+ showFieldNormWindow(name);
+ }
+ }
+ });
+ Menu.Item item4 = new Menu.Item(resources.get("documentsTab_docTable_popup_menu4"));
+ item4.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ String name = (String)row.get(FIELDROW_KEY_NAME);
+ IndexableField field = (IndexableField)row.get(FIELDROW_KEY_FIELD);
+ if (ir == null) {
+ Alert.alert(MessageType.ERROR, (String)resources.get("documentsTab_noOrClosedIndex"), getWindow());
+ } else if (field == null) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_noDataAvailable"), getWindow());
+ } else {
+ saveFieldData(field);
+ }
+ }
+ });
+ section.add(item1);
+ section.add(item2);
+ section.add(item3);
+ section.add(item4);
+ menu.getSections().add(section);
+ popup.setMenu(menu);
+ popup.open(getWindow(), getMouseLocation().x + 20, getMouseLocation().y + 50);
+ return true;
+ }
+ return false;
+ }
+ });
+
+ }
+
+ private void showTermVectorWindow(String fieldName, Terms tv) {
+ try {
+ tvWindow.initTermVector(fieldName, tv);
+ } catch (IOException e) {
+ // TODO
+ e.printStackTrace();
+ }
+ tvWindow.open(getDisplay(), getWindow());
+ }
+
+ private void showFieldDataWindow(String fieldName, IndexableField field) {
+ fieldDataWindow.initFieldData(fieldName, field);
+ fieldDataWindow.open(getDisplay(), getWindow());
+ }
+
+ private static TFIDFSimilarity defaultSimilarity = new DefaultSimilarity();
+ private void showFieldNormWindow(String fieldName) {
+ if (ar != null) {
+ try {
+ NumericDocValues norms = ar.getNormValues(fieldName);
+ fieldNormWindow.initFieldNorm(iNum, fieldName, norms);
+ fieldNormWindow.open(getDisplay(), getWindow());
+ } catch (Exception e) {
+ Alert.alert(MessageType.ERROR, (String)resources.get("documentsTab_msg_errorNorm"), getWindow());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void saveFieldData(IndexableField field) {
+ byte[] data = null;
+ if (field.binaryValue() != null) {
+ BytesRef bytes = field.binaryValue();
+ data = new byte[bytes.length];
+ System.arraycopy(bytes.bytes, bytes.offset, data, 0,
+ bytes.length);
+ }
+ else {
+ try {
+ data = field.stringValue().getBytes("UTF-8");
+ } catch (UnsupportedEncodingException uee) {
+ uee.printStackTrace();
+ data = field.stringValue().getBytes();
+ }
+ }
+ if (data == null || data.length == 0) {
+ Alert.alert(MessageType.WARNING, (String)resources.get("documentsTab_msg_noDataAvailable"), getWindow());
+ }
+
+ final byte[] fieldData = Arrays.copyOf(data, data.length);
+ final FileBrowserSheet fileBrowserSheet = new FileBrowserSheet(FileBrowserSheet.Mode.SAVE_AS);
+ fileBrowserSheet.open(getWindow(), new SheetCloseListener() {
+ @Override
+ public void sheetClosed(Sheet sheet) {
+ if (sheet.getResult()) {
+ Sequence<File> selectedFiles = fileBrowserSheet.getSelectedFiles();
+ File file = selectedFiles.get(0);
+ try {
+ OutputStream os = new FileOutputStream(file);
+ int delta = fieldData.length / 100;
+ if (delta == 0) delta = 1;
+ for (int i = 0; i < fieldData.length; i++) {
+ os.write(fieldData[i]);
+ // TODO: show progress
+ //if (i % delta == 0) {
+ // setInteger(bar, "value", i / delta);
+ //}
+ }
+ os.flush();
+ os.close();
+ Alert.alert(MessageType.INFO, "Saved to " + file.getAbsolutePath(), getWindow());
+ } catch (IOException e) {
+ e.printStackTrace();
+ Alert.alert(MessageType.ERROR, "Can't save to : " + file.getAbsoluteFile(), getWindow());
+ }
+ } else {
+ Alert.alert(MessageType.INFO, "You didn't select anything.", getWindow());
+ }
+
+ }
+ });
+ }
}
Index: src/org/apache/lucene/luke/ui/FieldDataWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/FieldDataWindow.bxml (revision 0)
+++ src/org/apache/lucene/luke/ui/FieldDataWindow.bxml (working copy)
@@ -0,0 +1,57 @@
+<luke:FieldDataWindow bxml:id="fieldData" icon="/img/luke.gif"
+ title="%fieldDataWindow_title" xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:luke="org.apache.lucene.luke.ui" xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <content>
+ <TablePane styles="{verticalSpacing:10}">
+ <columns>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <TablePane styles="{verticalSpacing:1,horizontalSpacing:1}">
+ <columns>
+ <TablePane.Column />
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <Label text="Field name:" styles="{font:{bold:true},backgroundColor:'#dce0e7',padding:2}"/>
+ <Label bxml:id="name" text="?" styles="{backgroundColor:'#fcfdfd',padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Field length: " styles="{font:{bold:true},backgroundColor:'#f1f1f1',padding:2}"/>
+ <Label bxml:id="length" text="?" styles="{backgroundColor:11,padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Show content as: " styles="{font:{bold:true},backgroundColor:'#dce0e7',padding:2}"/>
+ <Spinner bxml:id="cDecoder" />
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <Label bxml:id="error" text="%fieldDataWindow_decodeError" visible="false"
+ styles="{color:'red',padding:2,wrapText:true}" preferredWidth="500"/>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <Border styles="{padding:1}">
+ <ScrollPane>
+ <TextArea bxml:id="data" preferredWidth="500" preferredHeight="250" editable="false"/>
+ </ScrollPane>
+ </Border>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <BoxPane orientation="horizontal" styles="{horizontalAlignment:'right'}">
+ <PushButton buttonData="%label_ok"
+ ButtonPressListener.buttonPressed="fieldData.close()">
+ </PushButton>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+</luke:FieldDataWindow>
\ No newline at end of file
Property changes on: src/org/apache/lucene/luke/ui/FieldDataWindow.bxml
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Index: src/org/apache/lucene/luke/ui/FieldDataWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/FieldDataWindow.java (revision 0)
+++ src/org/apache/lucene/luke/ui/FieldDataWindow.java (working copy)
@@ -0,0 +1,222 @@
+package org.apache.lucene.luke.ui;
+
+import org.apache.lucene.analysis.payloads.PayloadHelper;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.luke.core.Util;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.pivot.beans.BXML;
+import org.apache.pivot.beans.Bindable;
+import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.collections.List;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.serialization.SerializationException;
+import org.apache.pivot.util.Resources;
+import org.apache.pivot.wtk.*;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.util.Date;
+
+public class FieldDataWindow extends Dialog implements Bindable {
+
+ @BXML
+ private Label name;
+ @BXML
+ private Label length;
+ @BXML
+ private Spinner cDecoder;
+ @BXML
+ private Label error;
+ @BXML
+ private TextArea data;
+
+ private Resources resources;
+
+ private IndexableField field;
+
+ @Override
+ public void initialize(Map<String, Object> map, URL url, Resources resources) {
+ this.resources = resources;
+ }
+
+ public void initFieldData(String fieldName, IndexableField field) {
+ this.field = field;
+
+ setContentDecoders();
+
+ name.setText(fieldName);
+ ContentDecoder dec = ContentDecoder.defDecoder();
+ dec.decode(field);
+ data.setText(String.valueOf(dec.value));
+ length.setText(Integer.toString(dec.len));
+ }
+
+ private void setContentDecoders() {
+ ArrayList<Object> decoders = new ArrayList<Object>();
+ ContentDecoder[] contentDecoders = ContentDecoder.values();
+ for (int i = contentDecoders.length - 1; i >= 0; i--) {
+ decoders.add(contentDecoders[i]);
+ }
+ cDecoder.setSpinnerData(decoders);
+ cDecoder.setSelectedItem(ContentDecoder.STRING_UTF8);
+
+ cDecoder.getSpinnerSelectionListeners().add(new SpinnerSelectionListener.Adapter() {
+ @Override
+ public void selectedItemChanged(Spinner spinner, Object o) {
+ ContentDecoder dec = (ContentDecoder) spinner.getSelectedItem();
+ if (dec == null) {
+ dec = ContentDecoder.defDecoder();
+ }
+ dec.decode(field);
+ data.setText(dec.value);
+ length.setText(Integer.toString(dec.len));
+ if (dec.warn) {
+ error.setVisible(true);
+ try {
+ data.setStyles("{color:'#bdbdbd'}");
+ } catch (SerializationException e) {
+ e.printStackTrace();
+ }
+ data.setEnabled(false);
+ } else {
+ error.setVisible(false);
+ try {
+ data.setStyles("{color:'#000000'}");
+ } catch (SerializationException e) {
+ e.printStackTrace();
+ }
+ data.setEnabled(true);
+ }
+ }
+ });
+ }
+
+
+ enum ContentDecoder {
+ STRING_UTF8("String UTF-8"),
+ STRING("String default enc."),
+ HEXDUMP("Hexdump"),
+ DATETIME("Date / Time"),
+ NUMERIC("Numeric"),
+ LONG("Long (prefix-coded)"),
+ ARRAY_OF_INT("Array of int"),
+ ARRAY_OF_FLOAT("Array of float");
+
+ private String strExpr;
+ ContentDecoder(String strExpr) {
+ this.strExpr = strExpr;
+ }
+
+ @Override
+ public String toString() {
+ return strExpr;
+ }
+
+ public static ContentDecoder defDecoder() {
+ return STRING_UTF8;
+ }
+
+ String value = ""; // decoded value
+ int len; // length of decoded value
+ boolean warn; // set to true if decode failed
+
+ public void decode(IndexableField field) {
+ if (field == null) {
+ return ;
+ }
+ warn = false;
+ byte[] data = null;
+ if (field.binaryValue() != null) {
+ BytesRef bytes = field.binaryValue();
+ data = new byte[bytes.length];
+ System.arraycopy(bytes.bytes, bytes.offset, data, 0,
+ bytes.length);
+ }
+ else if (field.stringValue() != null) {
+ try {
+ data = field.stringValue().getBytes("UTF-8");
+ } catch (UnsupportedEncodingException uee) {
+ warn = true;
+ uee.printStackTrace();
+ data = field.stringValue().getBytes();
+ }
+ }
+ if (data == null) data = new byte[0];
+
+ switch(this) {
+ case STRING_UTF8:
+ value = field.stringValue();
+ if (value != null) len = value.length();
+ break;
+ case STRING:
+ value = new String(data);
+ len = value.length();
+ break;
+ case HEXDUMP:
+ value = Util.bytesToHex(data, 0, data.length, true);
+ len = data.length;
+ break;
+ case DATETIME:
+ try {
+ Date d = DateTools.stringToDate(field.stringValue());
+ value = d.toString();
+ len = 1;
+ } catch (Exception e) {
+ warn = true;
+ value = Util.bytesToHex(data, 0, data.length, true);
+ }
+ break;
+ case NUMERIC:
+ if (field.numericValue() != null) {
+ value = field.numericValue().toString() + " (" + field.numericValue().getClass().getSimpleName() + ")";
+ } else {
+ warn = true;
+ value = Util.bytesToHex(data, 0, data.length, true);
+ }
+ break;
+ case LONG:
+ try {
+ long num = NumericUtils.prefixCodedToLong(new BytesRef(field.stringValue()));
+ value = String.valueOf(num);
+ len = 1;
+ } catch (Exception e) {
+ warn = true;
+ value = Util.bytesToHex(data, 0, data.length, true);
+ }
+ break;
+ case ARRAY_OF_INT:
+ if (data.length % 4 == 0) {
+ len = data.length / 4;
+ StringBuilder sb = new StringBuilder();
+ for (int k = 0; k < data.length; k += 4) {
+ if (k > 0) sb.append(',');
+ sb.append(String.valueOf(PayloadHelper.decodeInt(data, k)));
+ }
+ value = sb.toString();
+ } else {
+ warn = true;
+ value = Util.bytesToHex(data, 0, data.length, true);
+ }
+ break;
+ case ARRAY_OF_FLOAT:
+ if (data.length % 4 == 0) {
+ len = data.length / 4;
+ StringBuilder sb = new StringBuilder();
+ for (int k = 0; k < data.length; k += 4) {
+ if (k > 0) sb.append(',');
+ sb.append(String.valueOf(PayloadHelper.decodeFloat(data, k)));
+ }
+ value = sb.toString();
+ } else {
+ warn = true;
+ value = Util.bytesToHex(data, 0, data.length, true);
+ }
+ break;
+ }
+ }
+
+ }
+}
Index: src/org/apache/lucene/luke/ui/FieldNormWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/FieldNormWindow.bxml (revision 0)
+++ src/org/apache/lucene/luke/ui/FieldNormWindow.bxml (working copy)
@@ -0,0 +1,75 @@
+<luke:FieldNormWindow bxml:id="fieldNorm" icon="/img/luke.gif"
+ title="%fieldNormWindow_title" xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:luke="org.apache.lucene.luke.ui" xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <content>
+ <TablePane styles="{verticalSpacing:10}">
+ <columns>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <TablePane styles="{verticalSpacing:5,horizontalSpacing:5}">
+ <columns>
+ <TablePane.Column />
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <Label text="Field name: " />
+ <Label bxml:id="field" text="?" styles="{font:{bold:true}}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Field norm: " />
+ <Label bxml:id="normVal" text="?" styles="{font:{bold:true}}"/>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <Separator/>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <BoxPane orientation="vertical" styles="{fill:true}">
+ <Label text="%fieldNormWindow_simClass"/>
+ <BoxPane styles="{fill:true}">
+ <TextInput bxml:id="simclass" preferredWidth="400"/>
+ <PushButton bxml:id="refreshButton">
+ <buttonData>
+ <content:ButtonData icon="/img/refresh.png" />
+ </buttonData>
+ </PushButton>
+ </BoxPane>
+ <Label bxml:id="simErr" text="" styles="{color:'red'}" visible="false"/>
+ <TablePane styles="{verticalSpacing:5,horizontalSpacing:5}">
+ <columns>
+ <TablePane.Column />
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <Label text="%fieldNormWindow_otherNorm"/>
+ <TextInput bxml:id="otherNorm" />
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="%fieldNormWindow_encNorm"/>
+ <Label bxml:id="encNorm" text="?"/>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </BoxPane>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <BoxPane orientation="horizontal" styles="{horizontalAlignment:'right'}">
+ <PushButton buttonData="%label_ok"
+ ButtonPressListener.buttonPressed="fieldNorm.close()">
+ </PushButton>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+</luke:FieldNormWindow>
\ No newline at end of file
Property changes on: src/org/apache/lucene/luke/ui/FieldNormWindow.bxml
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Index: src/org/apache/lucene/luke/ui/FieldNormWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/FieldNormWindow.java (revision 0)
+++ src/org/apache/lucene/luke/ui/FieldNormWindow.java (working copy)
@@ -0,0 +1,122 @@
+package org.apache.lucene.luke.ui;
+
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.luke.core.Util;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
+import org.apache.pivot.beans.BXML;
+import org.apache.pivot.beans.Bindable;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.util.Resources;
+import org.apache.pivot.wtk.*;
+
+import java.net.URL;
+
+public class FieldNormWindow extends Dialog implements Bindable {
+
+ @BXML
+ private Label field;
+ @BXML
+ private Label normVal;
+ @BXML
+ private TextInput simclass;
+ @BXML
+ private Label simErr;
+ @BXML
+ private PushButton refreshButton;
+ @BXML
+ private TextInput otherNorm;
+ @BXML
+ private Label encNorm;
+
+ private Resources resources;
+
+ private String fieldName;
+
+ private static TFIDFSimilarity defaultSimilarity = new DefaultSimilarity();
+
+ @Override
+ public void initialize(Map<String, Object> map, URL url, Resources resources) {
+ this.resources = resources;
+ }
+
+ public void initFieldNorm(int docId, String fieldName, NumericDocValues norms) throws Exception {
+ this.fieldName = fieldName;
+ TFIDFSimilarity sim = defaultSimilarity;
+ byte curBVal = (byte) norms.get(docId);
+ float curFVal = Util.decodeNormValue(curBVal, fieldName, sim);
+ field.setText(fieldName);
+ normVal.setText(Float.toString(curFVal));
+ simclass.setText(sim.getClass().getName());
+ otherNorm.setText(Float.toString(curFVal));
+ encNorm.setText(Float.toString(curFVal) + " (0x" + Util.byteToHex(curBVal) + ")");
+
+ refreshButton.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ changeNorms();
+ }
+ });
+ otherNorm.getTextInputContentListeners().add(new TextInputContentListener.Adapter(){
+ @Override
+ public void textChanged(TextInput textInput) {
+ changeNorms();
+ }
+ });
+ }
+
+ private void changeNorms() {
+ String simClassString = simclass.getText();
+
+ Similarity sim = createSimilarity(simClassString);
+ TFIDFSimilarity s = null;
+ if (sim != null && (sim instanceof TFIDFSimilarity)) {
+ s = (TFIDFSimilarity)sim;
+ } else {
+ s = defaultSimilarity;
+ }
+ if (s == null) {
+ s = defaultSimilarity;
+ }
+ //setString(sim, "text", s.getClass().getName());
+ simclass.setText(s.getClass().getName());
+ try {
+ float newFVal = Float.parseFloat(otherNorm.getText());
+ long newBVal = Util.encodeNormValue(newFVal, fieldName, s);
+ float encFVal = Util.decodeNormValue(newBVal, fieldName, s);
+ encNorm.setText(String.valueOf(encFVal) + " (0x" + Util.byteToHex((byte) (newBVal & 0xFF)) + ")");
+ } catch (Exception e) {
+ // TODO:
+ e.printStackTrace();
+ }
+ }
+
+ public Similarity createSimilarity(String simClass) {
+ //Object ckSimDef = find(srchOpts, "ckSimDef");
+ //Object ckSimSweet = find(srchOpts, "ckSimSweet");
+ //Object ckSimOther = find(srchOpts, "ckSimOther");
+ //Object simClass = find(srchOpts, "simClass");
+ //Object ckSimCust = find(srchOpts, "ckSimCust");
+ //if (getBoolean(ckSimDef, "selected")) {
+ // return new DefaultSimilarity();
+ //} else if (getBoolean(ckSimSweet, "selected")) {
+ // return new SweetSpotSimilarity();
+ //} else if (getBoolean(ckSimOther, "selected")) {
+ try {
+ Class clazz = Class.forName(simClass);
+ if (Similarity.class.isAssignableFrom(clazz)) {
+ Similarity sim = (Similarity) clazz.newInstance();
+ simErr.setVisible(false);
+ return sim;
+ } else {
+ simErr.setText("Not a subclass of Similarity: " + clazz.getName());
+ simErr.setVisible(true);
+ }
+ } catch (Exception e) {
+ simErr.setText("Invalid similarity class " + simClass + ", using DefaultSimilarity.");
+ simErr.setVisible(true);
+ }
+ return new DefaultSimilarity();
+ }
+}
Index: src/org/apache/lucene/luke/ui/LukeApplication_en.json
===================================================================
--- src/org/apache/lucene/luke/ui/LukeApplication_en.json (revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeApplication_en.json (working copy)
@@ -26,6 +26,9 @@
sandstoneTheme: "Sandstone Theme",
skyTheme: "Sky Theme",
navyTheme: "Navy Theme",
+
+ label_ok: "OK",
+ label_clipboard: "Copy to Clipboard",
lukeInitWindow_title: "Path to index directory:",
lukeInitWindow_path: "Path:",
@@ -58,9 +61,10 @@
overviewTab_userData: "Current commit user data:",
overviewTab_fieldsAndTermCounts: "Available fields and term counts per field:",
- overviewTab_topRankingTerms: "Top Ranking Terms (Right click for more options)",
+ overviewTab_topRankingTerms: "Top Ranking Terms (Select a row and right click for more options)",
overviewTab_decoderWarn: "Tokens marked in red indicate decoding errors, likely due to a mismatched decoder.",
overviewTab_fieldSelect: "Select fields from the list below, and press button to view top terms in these fields. No selection means all fields.",
+ overviewTab_fieldsHintDecoder: "Hint: Double click 'Decoder' column, select decoder class, and press Enter to set the suitable decoder.",
overviewTab_topTermsHint: "Hint: use Shift-Click to select ranges, or Ctrl-Click to select multiple fields (or unselect all).",
overviewTab_showTopTerms: "Show top terms >>",
@@ -68,28 +72,63 @@
overviewTab_topTermsTable_col2: "DF",
overviewTab_topTermsTable_col3: "Field",
overviewTab_topTermsTable_col4: "Text",
+
+ overviewTab_topTermTable_popup_menu1: "Browse term docs",
+ overviewTab_topTermTable_popup_menu2: "Show all term docs",
+ overviewTab_topTermTable_popup_menu3: "Copy to clipboard",
documentsTab_noOrClosedIndex: "FAILED: No index, or index is closed. Reopen it.",
documentsTab_docNumOutsideRange: "Document number outside valid range.",
documentsTab_browseByDocNum: "Browse by document number:",
documentsTab_browseByTerm: "Browse by term:",
+ documentsTab_selectField: "Select a field from the spinner below, press Next to browse terms.",
documentsTab_enterTermHint: "(Hint: enter a substring and press Next to start at the nearest term).",
documentsTab_firstTerm: "First Term",
documentsTab_term: "Term:",
documentsTab_decodedValue: "Decoded value:",
- documentsTab_browseDocsWithTerm: "Browse documents with this term",
+ documentsTab_browseDocsWithTerm: "Browse documents with this term:",
+ documentsTab_selectTerm: "After select term, press Next to browse docs with the term.",
documentsTab_showAllDocs: "Show All Docs",
documentsTab_deleteAllDocs: "Delete All Docs",
documentsTab_document: "Document:",
documentsTab_firstDoc: "First Doc",
documentsTab_termFreqInDoc: "Term freq in this doc:",
- documentsTab_showPositions: "Show Positions",
-
+ documentsTab_showPositions: "Show Positions and Offsets",
+ documentsTab_indexOptionsNote1: "Note: flag 't - Index options' means, 1: DOCS_ONLY; 2:DOCS_AND_FREQS; 3: DOCS_AND_FREQS_AND_POSITIONS; 4: DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS.",
+ documentsTab_indexOptionsNote2: "(See Javadocs about FieldInfo.IndexOptions for more info.)",
+
documentsTab_docTable_col1: "Field",
- documentsTab_docTable_col2: "ITSVopfOLB",
- documentsTab_docTable_col3: "Norm",
- documentsTab_docTable_col4: "Value",
-
+ documentsTab_docTable_col2: "ITSVopaPtOLB",
+ documentsTab_docTable_col3: "DocValues Type",
+ documentsTab_docTable_col4: "Norm (Norm Type)",
+ documentsTab_docTable_col5: "Value",
+
+ documentsTab_docTable_popup_menu1: "Field's Term Vector",
+ documentsTab_docTable_popup_menu2: "Show Full Text",
+ documentsTab_docTable_popup_menu3: "Set Norm",
+ documentsTab_docTable_popup_menu4: "Save Field",
+
+ documentsTab_msg_docNotSelected: "Please select a term and a document for showing term positions.",
+ documentsTab_msg_positionNotIndexed: "Positions are not indexed for this term.",
+ documentsTab_msg_noPositionInfo: "No positions info ???",
+ documentsTab_msg_noDataAvailable: "No data available for this field.",
+ documentsTab_msg_noNorm: "Cannot examine norm value - this field is not indexed.",
+ documentsTab_msg_errorNorm: "Error reading norm: ",
+ documentsTab_msg_cantOverwriteDir: "Can't overwrite a directory.",
+
+ posAndOffsetsWindow_title: "Term Positions and Offsets",
+
+ termVectorWindow_title: "Term Vector",
+ termVectorWindow_field: "Term vector for the field: ",
+
+ fieldDataWindow_title: "Field Data",
+ fieldDataWindow_decodeError: "Some values could not be properly represented in this format. They are marked in grey and presented as a hex dump.",
+
+ fieldNormWindow_title: "Field Norm",
+ fieldNormWindow_simClass: "Encode other field norm using this TFIDFSimilarity (full class name): ",
+ fieldNormWindow_otherNorm: "Enter norm value: ",
+ fieldNormWindow_encNorm: "Encoded value rounded to: ",
+
searchTab_searchPrompt: "Enter search expression here:",
searchTab_update: "Update",
searchTab_explainStructure: "Explain Structure",
Index: src/org/apache/lucene/luke/ui/LukeWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/LukeWindow.bxml (revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeWindow.bxml (working copy)
@@ -103,7 +103,7 @@
</content>
</Border>
- <Border>
+ <Border styles="{backgroundColor:11,thickness:0}">
<TabPane.tabData>
<content:ButtonData icon="/img/docs.gif"
text="%lukeWindow_documentsTabText" />
@@ -160,7 +160,10 @@
</TabPane>
</TablePane.Row>
<TablePane.Row>
- <Label bxml:id="statusLabel" text="" styles="{padding:2}" />
+ <BoxPane>
+ <Label bxml:id="indexName" text="" styles="{padding:2}"/>
+ <Label bxml:id="statusLabel" text="" styles="{padding:2}" />
+ </BoxPane>
</TablePane.Row>
</rows>
</TablePane>
Index: src/org/apache/lucene/luke/ui/LukeWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/LukeWindow.java (revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeWindow.java (working copy)
@@ -23,7 +23,6 @@
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import org.apache.lucene.analysis.Analyzer;
@@ -99,6 +98,8 @@
@BXML
private LukeInitWindow lukeInitWindow;
@BXML
+ private TabPane tabPane;
+ @BXML
private FilesTab filesTab;
@BXML
private DocumentsTab documentsTab;
@@ -108,6 +109,8 @@
private OverviewTab overviewTab;
@BXML
private AnalyzersTab analyzersTab;
+ @BXML
+ private Label indexName;
private LukeMediator lukeMediator = new LukeMediator();
@@ -439,6 +442,7 @@
// initPlugins();
showStatus("Index successfully open.");
+ indexName.setText("Index path: " + indexPath);
} catch (Exception e) {
e.printStackTrace();
errorMsg(e.getMessage());
@@ -622,8 +626,13 @@
setComponentColor(component, "scrollButtonBackgroundColor", theme[2]);
setComponentColor(component, "borderColor", theme[3]);
} else if (component instanceof PushButton || component instanceof ListButton) {
- component.getComponentMouseButtonListeners().add(mouseButtonPressedListener);
- component.getComponentMouseListeners().add(mouseMoveListener);
+ // Listeners are added at start-up time only.
+ if (component.getComponentMouseButtonListeners().isEmpty()) {
+ component.getComponentMouseButtonListeners().add(mouseButtonPressedListener);
+ }
+ if (component.getComponentMouseListeners().isEmpty()) {
+ component.getComponentMouseListeners().add(mouseMoveListener);
+ }
setComponentColor(component, "color", theme[1]);
setComponentColor(component, "backgroundColor", theme[0]);
setComponentColor(component, "borderColor", theme[3]);
@@ -679,7 +688,7 @@
private Directory directory;
- class LukeMediator {
+ public class LukeMediator {
// populated by LukeWindow#openIndex
private IndexInfo indexInfo;
@@ -700,6 +709,14 @@
return overviewTab;
}
+ public DocumentsTab getDocumentsTab() {
+ return documentsTab;
+ }
+
+ public TabPane getTabPane() {
+ return tabPane;
+ }
+
public LukeWindow getLukeWindow() {
return LukeWindow.this;
}
Index: src/org/apache/lucene/luke/ui/OverviewTab.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/OverviewTab.bxml (revision 1655665)
+++ src/org/apache/lucene/luke/ui/OverviewTab.bxml (working copy)
@@ -148,9 +148,12 @@
</columns>
<rows>
<TablePane.Row height="-1">
- <Label styles="{backgroundColor:11,padding:2}" text="%overviewTab_fieldSelect" />
+ <Label styles="{backgroundColor:11,padding:2,wrapText:true}" text="%overviewTab_fieldSelect" />
</TablePane.Row>
<TablePane.Row height="-1">
+ <Label styles="{backgroundColor:11,padding:2,wrapText:true}" text="%overviewTab_fieldsHintDecoder" />
+ </TablePane.Row>
+ <TablePane.Row height="-1">
<Label styles="{backgroundColor:11,font:{bold:true}}"
text="%overviewTab_fieldsAndTermCounts" />
</TablePane.Row>
Index: src/org/apache/lucene/luke/ui/OverviewTab.java
===================================================================
--- src/org/apache/lucene/luke/ui/OverviewTab.java (revision 1655665)
+++ src/org/apache/lucene/luke/ui/OverviewTab.java (working copy)
@@ -21,19 +21,16 @@
import java.text.NumberFormat;
import java.util.Collections;
-import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.IndexCommit;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.SegmentReader;
-import org.apache.lucene.luke.core.FieldTermCount;
+import org.apache.lucene.index.*;
+import org.apache.lucene.luke.core.*;
import org.apache.lucene.luke.core.HighFreqTerms;
-import org.apache.lucene.luke.core.IndexInfo;
-import org.apache.lucene.luke.core.TableComparator;
import org.apache.lucene.luke.core.TermStats;
-import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.core.decoders.*;
import org.apache.lucene.luke.ui.LukeWindow.LukeMediator;
+import org.apache.lucene.luke.ui.util.FieldsTableRow;
+import org.apache.lucene.luke.ui.util.TableComparator;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.Bindable;
import org.apache.pivot.collections.*;
@@ -43,6 +40,7 @@
import org.apache.pivot.util.concurrent.TaskExecutionException;
import org.apache.pivot.util.concurrent.TaskListener;
import org.apache.pivot.wtk.*;
+import org.apache.pivot.wtk.content.TableViewRowEditor;
public class OverviewTab extends SplitPane implements Bindable {
@@ -230,7 +228,6 @@
iTerms.setText(String.valueOf(numTerms));
initFieldList(null, null);
-
} catch (Exception e) {
// showStatus("ERROR: can't count terms per field");
numTerms = -1;
@@ -261,6 +258,7 @@
};
fListTask.execute(new TaskAdapter<String>(taskListener));
+ clearFieldsTableStatus();
String sDel = ir.hasDeletions() ? "Yes (" + ir.numDeletedDocs() + ")" : "No";
IndexCommit ic = ir instanceof DirectoryReader ? ((DirectoryReader) ir).getIndexCommit() : null;
@@ -347,16 +345,24 @@
Sequence<?> fields = fieldsTable.getSelectedRows();
- String[] flds = null;
+ final java.util.Map<String, Decoder> fldDecMap = new java.util.HashMap<String, Decoder>();
if (fields == null || fields.getLength() == 0) {
- flds = indexInfo.getFieldNames().toArray(new String[0]);
+ // no fields selected
+ for (String fld : indexInfo.getFieldNames()) {
+ Decoder dec = lukeMediator.getDecoders().get(fld);
+ if (dec == null) {
+ dec = lukeMediator.getDefDecoder();
+ }
+ fldDecMap.put(fld, dec);
+ }
} else {
- flds = new String[fields.getLength()];
+ // some fields selected
for (int i = 0; i < fields.getLength(); i++) {
- flds[i] = ((Map<String,String>) fields.get(i)).get("name");
+ String fld = ((FieldsTableRow)fields.get(i)).getName();
+ Decoder dec = ((FieldsTableRow)fields.get(i)).getDecoder();
+ fldDecMap.put(fld, dec);
}
}
- final String[] fflds = flds;
tTable.setTableData(new ArrayList(0));
@@ -387,6 +393,7 @@
public void taskExecuted(Task<Object> task) {
// this must happen here rather than in the task because it must happen in the UI dispatch thread
try {
+ final String[] fflds = fldDecMap.keySet().toArray(new String[0]);
TermStats[] topTerms = HighFreqTerms.getHighFreqTerms(ir, ndoc, fflds);
List<Map<String,String>> tableData = new ArrayList<Map<String,String>>();
@@ -409,12 +416,11 @@
row.put("field", topTerms[i].field);
- Decoder dec = lukeMediator.getDecoders().get(topTerms[i].field);
- if (dec == null)
- dec = lukeMediator.getDefDecoder();
+ Decoder dec = fldDecMap.get(topTerms[i].field);
+
String s;
try {
- s = dec.decodeTerm(topTerms[i].field, topTerms[i].termtext.utf8ToString());
+ s = dec.decodeTerm(topTerms[i].field, topTerms[i].termtext);
} catch (Throwable e) {
// e.printStackTrace();
s = topTerms[i].termtext.utf8ToString();
@@ -422,6 +428,8 @@
// setColor(cell, "foreground", Color.RED);
}
row.put("text", s);
+ // hidden field. would be used when the user select 'Browse term docs' menu at top terms table.
+ row.put("rawterm", topTerms[i].termtext.utf8ToString());
tableData.add(row);
}
tTable.setTableData(tableData);
@@ -443,8 +451,74 @@
};
topTermsTask.execute(new TaskAdapter<Object>(taskListener));
+
+ addListenerToTopTermsTable();
}
+ private void addListenerToTopTermsTable() {
+ // register mouse button listener for more options.
+ tTable.getComponentMouseButtonListeners().add(new ComponentMouseButtonListener.Adapter(){
+ @Override
+ public boolean mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+ final Map<String, String> row = (Map<String, String>) tTable.getSelectedRow();
+ if (row == null) {
+ System.out.println("No term selected.");
+ return false;
+ }
+ if (button.name().equals(Mouse.Button.RIGHT.name())) {
+ MenuPopup popup = new MenuPopup();
+ Menu menu = new Menu();
+ Menu.Section section1 = new Menu.Section();
+ Menu.Section section2 = new Menu.Section();
+ Menu.Item item1 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu1"));
+ item1.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ // 'Browse term docs' menu selected. switch to Documents tab.
+ Term term = new Term(row.get("field"), new BytesRef(row.get("rawterm")));
+ lukeMediator.getDocumentsTab().showTerm(term);
+ // TODO: index access isn't good...
+ lukeMediator.getTabPane().setSelectedIndex(1);
+ }
+ });
+ Menu.Item item2 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu2"));
+ item2.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ // 'Show all term docs' menu selected. switch to Search tab.
+ // TODO
+ }
+ });
+ Menu.Item item3 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu3"));
+ item3.setAction(new Action() {
+ @Override
+ public void perform(Component component) {
+ // 'Copy to clipboard' menu selected.
+ StringBuilder sb = new StringBuilder();
+ sb.append(row.get("num") + "\t");
+ sb.append(row.get("df") + "\t");
+ sb.append(row.get("field") + "\t");
+ sb.append(row.get("text") + "\t");
+ LocalManifest content = new LocalManifest();
+ content.putText(sb.toString());
+ Clipboard.setContent(content);
+ }
+ });
+ section1.add(item1);
+ section1.add(item2);
+ section2.add(item3);
+ menu.getSections().add(section1);
+ menu.getSections().add(section2);
+ popup.setMenu(menu);
+
+ popup.open(getWindow(), getMouseLocation().x + 20, getMouseLocation().y);
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
private void initFieldList(Object fCombo, Object defFld) {
// removeAll(fieldsTable);
// removeAll(defFld);
@@ -454,11 +528,12 @@
NumberFormat percentFormat = NumberFormat.getNumberInstance();
intCountFormat.setGroupingUsed(true);
percentFormat.setMaximumFractionDigits(2);
+ // sort listener
fieldsTable.getTableViewSortListeners().add(new TableViewSortListener.Adapter() {
@Override
public void sortChanged(TableView tableView) {
@SuppressWarnings("unchecked")
- List<Map<String, String>> tableData = (List<Map<String, String>>) tableView.getTableData();
+ List<FieldsTableRow> tableData = (List<FieldsTableRow>) tableView.getTableData();
tableData.setComparator(new TableComparator(tableView));
}
});
@@ -465,34 +540,39 @@
// default sort : sorted by name in ascending order
fieldsTable.setSort("name", SortDirection.ASCENDING);
- for (String s : indexInfo.getFieldNames()) {
- Map<String,String> row = new HashMap<String,String>();
+ // row editor for decoders
+ List decoders = new ArrayList();
+ for (Decoder dec : Util.loadDecoders()) {
+ decoders.add(dec);
+ }
+ ListButton decodersButton = new ListButton(decoders);
+ decodersButton.setSelectedItemKey("decoder");
+ TableViewRowEditor rowEditor = new TableViewRowEditor();
+ rowEditor.getCellEditors().put("decoder", decodersButton);
+ fieldsTable.setRowEditor(rowEditor);
- row.put("name", s);
- FieldTermCount ftc = termCounts.get(s);
+ for (String fname : indexInfo.getFieldNames()) {
+ FieldsTableRow row = new FieldsTableRow(lukeMediator);
+ row.setName(fname);
+ FieldTermCount ftc = termCounts.get(fname);
if (ftc != null) {
long cnt = ftc.termCount;
-
- row.put("termCount", intCountFormat.format(cnt));
-
+ row.setTermCount(intCountFormat.format(cnt));
float pcent = (float) (cnt * 100) / (float) numTerms;
-
- row.put("percent", percentFormat.format(pcent) + " %");
-
+ row.setPercent(percentFormat.format(pcent) + " %");
} else {
- row.put("termCount", "0");
- row.put("percent", "0.00%");
+ row.setTermCount("0");
+ row.setPercent("0.00%");
}
- //tableData.add(row);
- List<Map<String, String>> tableData = (List<Map<String, String>>)fieldsTable.getTableData();
+ List<FieldsTableRow> tableData = (List<FieldsTableRow>)fieldsTable.getTableData();
tableData.add(row);
- Decoder dec = lukeMediator.getDecoders().get(s);
+ Decoder dec = lukeMediator.getDecoders().get(fname);
if (dec == null)
dec = lukeMediator.getDefDecoder();
- row.put("decoder", dec.toString());
+ row.setDecoder(dec);
// populate combos
// Object choice = create("choice");
@@ -504,9 +584,14 @@
// setString(choice, "text", s);
// putProperty(choice, "fName", s);
}
- //fieldsTable.setTableData(tableData);
+
}
+ private void clearFieldsTableStatus() {
+ // clear the fields table view status
+ fieldsTable.clearSelection();
+ }
+
private int getNTerms() {
final int nTermsInt = nTerms.getSelectedIndex();
return nTermsInt;
Index: src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.bxml (revision 0)
+++ src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.bxml (working copy)
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<luke:PosAndOffsetsWindow bxml:id="posAndOffsets" icon="/img/luke.gif"
+ title="%posAndOffsetsWindow_title" xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:luke="org.apache.lucene.luke.ui" xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <content>
+ <TablePane styles="{verticalSpacing:10}">
+ <columns>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <TablePane styles="{verticalSpacing:1,horizontalSpacing:1}">
+ <columns>
+ <TablePane.Column />
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <Label text="Document #" styles="{font:{bold:true},backgroundColor:'#dce0e7',padding:2}"/>
+ <Label bxml:id="docNum" text="?" styles="{backgroundColor:'#fcfdfd',padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Term positions for term: " styles="{font:{bold:true},backgroundColor:'#f1f1f1',padding:2}"/>
+ <Label bxml:id="term" text="?" styles="{backgroundColor:11,padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Term Frequency: " styles="{font:{bold:true},backgroundColor:'#dce0e7',padding:2}"/>
+ <Label bxml:id="tf" text="?" styles="{backgroundColor:'#fcfdfd',padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Offsets: " styles="{font:{bold:true},backgroundColor:'#f1f1f1',padding:2}"/>
+ <Label bxml:id="offsets" text="?" styles="{backgroundColor:11,padding:2}"/>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Label text="Show payload as: " styles="{font:{bold:true},backgroundColor:'#dce0e7',padding:2}"/>
+ <Spinner bxml:id="pDecoder" />
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <Border styles="{padding:1}">
+ <ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
+ <view>
+ <TableView bxml:id="posTable" selectMode="multi">
+ <columns>
+ <TableView.Column name="pos"
+ headerData="Position" width="50"/>
+ <TableView.Column name="offsets"
+ headerData="Offsets" width="100"/>
+ <TableView.Column name="payloadStr"
+ headerData="Payload" width="300"/>
+ </columns>
+ </TableView>
+ </view>
+ <columnHeader>
+ <TableViewHeader tableView="$posTable" />
+ </columnHeader>
+ </ScrollPane>
+ </Border>
+ </TablePane.Row>
+
+ <TablePane.Row>
+ <BoxPane orientation="horizontal" styles="{horizontalAlignment:'right'}">
+ <PushButton buttonData="%label_ok"
+ ButtonPressListener.buttonPressed="posAndOffsets.close()">
+ </PushButton>
+ <PushButton bxml:id="posCopyButton" buttonData="%label_clipboard"/>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+</luke:PosAndOffsetsWindow>
\ No newline at end of file
Property changes on: src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.bxml
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Index: src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.java (revision 0)
+++ src/org/apache/lucene/luke/ui/PosAndOffsetsWindow.java (working copy)
@@ -0,0 +1,208 @@
+package org.apache.lucene.luke.ui;
+
+import org.apache.lucene.analysis.payloads.PayloadHelper;
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.luke.core.Util;
+import org.apache.lucene.util.BytesRef;
+import org.apache.pivot.beans.BXML;
+import org.apache.pivot.beans.Bindable;
+import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.collections.List;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.util.Resources;
+import org.apache.pivot.wtk.*;
+
+import java.net.URL;
+
+public class PosAndOffsetsWindow extends Dialog implements Bindable {
+
+ @BXML
+ private TableView posTable;
+ @BXML
+ private Label docNum;
+ @BXML
+ private Label term;
+ @BXML
+ private Label tf;
+ @BXML
+ private Label offsets;
+ @BXML
+ private Spinner pDecoder;
+ @BXML
+ private PushButton posCopyButton;
+
+ private Resources resources;
+
+ private List<PositionAndOffset> tableData;
+
+ @Override
+ public void initialize(Map<String, Object> map, URL url, Resources resources) {
+ this.resources = resources;
+ }
+
+ public void initPositionInfo(DocsAndPositionsEnum pe, Term lastTerm) throws Exception {
+ setPayloadDecoders();
+ tableData = new ArrayList<PositionAndOffset>(getTermPositionAndOffsets(pe));
+ docNum.setText(String.valueOf(pe.docID()));
+ term.setText(lastTerm.field() + ":" + lastTerm.text());
+ tf.setText(String.valueOf(pe.freq()));
+ if (!tableData.isEmpty()) {
+ offsets.setText(String.valueOf(tableData.get(0).hasOffsets));
+ }
+ posTable.setTableData(tableData);
+ addPushButtonListener();
+ }
+
+ private void setPayloadDecoders() {
+ ArrayList<Object> decoders = new ArrayList<Object>();
+ decoders.add(PayloadDecoder.ARRAY_OF_FLOAT);
+ decoders.add(PayloadDecoder.ARRAY_OF_INT);
+ decoders.add(PayloadDecoder.HEXDUMP);
+ decoders.add(PayloadDecoder.STRING);
+ decoders.add(PayloadDecoder.STRING_UTF8);
+ pDecoder.setSpinnerData(decoders);
+ pDecoder.setSelectedItem(PayloadDecoder.STRING_UTF8);
+
+ pDecoder.getSpinnerSelectionListeners().add(new SpinnerSelectionListener.Adapter() {
+ @Override
+ public void selectedItemChanged(Spinner spinner, Object o) {
+ try {
+ for (PositionAndOffset row : tableData) {
+ PayloadDecoder dec = (PayloadDecoder) spinner.getSelectedItem();
+ if (dec == null) {
+ dec = PayloadDecoder.defDecoder();
+ }
+ row.payloadStr = dec.decode(row.payload);
+ }
+ posTable.repaint(); // update table data
+ } catch (Exception e) {
+ // TODO:
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ public class PositionAndOffset {
+ public int pos = -1;
+ public boolean hasOffsets = false;
+ public String offsets = "----";
+ public BytesRef payload = null;
+ public String payloadStr = "----";
+ }
+
+ private PositionAndOffset[] getTermPositionAndOffsets(DocsAndPositionsEnum pe) throws Exception {
+ int freq = pe.freq();
+
+ PositionAndOffset[] res = new PositionAndOffset[freq];
+ for (int i = 0; i < freq; i++) {
+ PositionAndOffset po = new PositionAndOffset();
+ po.pos = pe.nextPosition();
+ if (pe.startOffset() >= 0 && pe.endOffset() >= 0) {
+ // retrieve start and end offsets
+ po.hasOffsets = true;
+ po.offsets = String.valueOf(pe.startOffset()) + " - " + String.valueOf(pe.endOffset());
+ }
+ if (pe.getPayload() != null) {
+ po.payload = pe.getPayload();
+ po.payloadStr = ((PayloadDecoder) pDecoder.getSelectedItem()).decode(pe.getPayload());
+ }
+ res[i] = po;
+ }
+ return res;
+ }
+
+ enum PayloadDecoder {
+ STRING_UTF8("String UTF-8"),
+ STRING("String default enc."),
+ HEXDUMP("Hexdump"),
+ ARRAY_OF_INT("Array of int"),
+ ARRAY_OF_FLOAT("Array of float");
+
+ private String strExpr = null;
+ PayloadDecoder(String expr) {
+ this.strExpr = expr;
+ }
+
+ @Override
+ public String toString() {
+ return strExpr;
+ }
+
+ public static PayloadDecoder defDecoder() {
+ return STRING_UTF8;
+ }
+
+ public String decode(BytesRef payload) {
+ String val = "----";
+ StringBuilder sb = null;
+ if (payload == null) {
+ return val;
+ }
+ switch(this) {
+ case STRING_UTF8:
+ try {
+ val = new String(payload.bytes, payload.offset, payload.length, "UTF-8");
+ } catch (Exception e) {
+ e.printStackTrace();
+ val = new String(payload.bytes, payload.offset, payload.length);
+ }
+ break;
+ case STRING:
+ val = new String(payload.bytes, payload.offset, payload.length);
+ break;
+ case HEXDUMP:
+ val = Util.bytesToHex(payload.bytes, payload.offset, payload.length, false);
+ break;
+ case ARRAY_OF_INT:
+ sb = new StringBuilder();
+ for (int k = payload.offset; k < payload.offset + payload.length; k += 4) {
+ if (k > 0) sb.append(',');
+ sb.append(String.valueOf(PayloadHelper.decodeInt(payload.bytes, k)));
+ }
+ val = sb.toString();
+ break;
+ case ARRAY_OF_FLOAT:
+ sb = new StringBuilder();
+ for (int k = payload.offset; k < payload.offset + payload.length; k += 4) {
+ if (k > 0) sb.append(',');
+ sb.append(String.valueOf(PayloadHelper.decodeFloat(payload.bytes, k)));
+ }
+ val = sb.toString();
+ break;
+ }
+ return val;
+ }
+ }
+
+ private void addPushButtonListener() {
+
+ posCopyButton.getButtonPressListeners().add(new ButtonPressListener() {
+ @Override
+ public void buttonPressed(Button button) {
+ // fired when 'Copy to Clipboard' button pressed
+ Sequence<PositionAndOffset> selectedRows = (Sequence<PositionAndOffset>) posTable.getSelectedRows();
+ if (selectedRows == null || selectedRows.getLength() == 0) {
+ Alert.alert(MessageType.INFO, "No rows selected.", getWindow());
+ } else {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < selectedRows.getLength(); i++) {
+ PositionAndOffset row = selectedRows.get(i);
+ sb.append(row.pos + "\t");
+ sb.append(row.offsets + "\t");
+ sb.append(row.payloadStr);
+ if (i < selectedRows.getLength() - 1) {
+ sb.append("\n");
+ }
+ }
+ LocalManifest content = new LocalManifest();
+ content.putText(sb.toString());
+ Clipboard.setContent(content);
+ }
+ }
+ });
+ }
+
+}
Index: src/org/apache/lucene/luke/ui/TermVectorWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/TermVectorWindow.bxml (revision 0)
+++ src/org/apache/lucene/luke/ui/TermVectorWindow.bxml (working copy)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<luke:TermVectorWindow bxml:id="termVector" icon="/img/luke.gif"
+ title="%termVectorWindow_title" xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:luke="org.apache.lucene.luke.ui" xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <content>
+ <TablePane styles="{verticalSpacing:10}">
+ <columns>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row>
+ <BoxPane styles="{fill:true}">
+ <ImageView image="/img/info.gif"/>
+ <Label text="%termVectorWindow_field" />
+ <Label bxml:id="field" text="?" styles="{font:{bold:true}}"/>
+ </BoxPane>
+ </TablePane.Row>
+ <TablePane.Row>
+ <Border styles="{padding:1}">
+ <ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
+ <view>
+ <TableView bxml:id="tvTable" selectMode="multi">
+ <columns>
+ <TableView.Column name="term"
+ headerData="Term" width="100"/>
+ <TableView.Column name="freq"
+ headerData="Freq." width="50"/>
+ <TableView.Column name="pos"
+ headerData="Positions" width="100"/>
+ <TableView.Column name="offsets"
+ headerData="Offsets" width="100" />
+ </columns>
+ </TableView>
+ </view>
+ <columnHeader>
+ <TableViewHeader tableView="$tvTable" sortMode="single_column" />
+ </columnHeader>
+ </ScrollPane>
+ </Border>
+ </TablePane.Row>
+ <TablePane.Row>
+ <BoxPane orientation="horizontal" styles="{horizontalAlignment:'right'}">
+ <PushButton buttonData="%label_ok"
+ ButtonPressListener.buttonPressed="termVector.close()">
+ </PushButton>
+ <PushButton bxml:id="tvCopyButton" buttonData="%label_clipboard"/>
+ </BoxPane>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+</luke:TermVectorWindow>
\ No newline at end of file
Property changes on: src/org/apache/lucene/luke/ui/TermVectorWindow.bxml
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Index: src/org/apache/lucene/luke/ui/TermVectorWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/TermVectorWindow.java (revision 0)
+++ src/org/apache/lucene/luke/ui/TermVectorWindow.java (working copy)
@@ -0,0 +1,143 @@
+package org.apache.lucene.luke.ui;
+
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.luke.ui.util.TermVectorTableComparator;
+import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.BytesRef;
+import org.apache.pivot.beans.BXML;
+import org.apache.pivot.beans.Bindable;
+import org.apache.pivot.collections.*;
+import org.apache.pivot.util.Resources;
+import org.apache.pivot.wtk.*;
+
+import java.io.IOException;
+import java.net.URL;
+
+public class TermVectorWindow extends Dialog implements Bindable{
+
+ @BXML
+ private Label field;
+ @BXML
+ private TableView tvTable;
+ @BXML
+ private PushButton tvCopyButton;
+
+ private Resources resources;
+
+ private List<Map<String, String>> tableData;
+
+ public static String TVROW_KEY_TERM = "term";
+ public static String TVROW_KEY_FREQ = "freq";
+ public static String TVROW_KEY_POSITION = "pos";
+ public static String TVROW_KEY_OFFSETS = "offsets";
+
+ @Override
+ public void initialize(Map<String, Object> map, URL url, Resources resources) {
+ this.resources = resources;
+ }
+
+ public void initTermVector(String fieldName, Terms tv) throws IOException {
+ field.setText(fieldName);
+ tableData = new ArrayList<Map<String, String>>();
+ TermsEnum te = tv.iterator(null);
+ BytesRef term = null;
+
+ // populate table data with term vector info
+ while((term = te.next()) != null) {
+ Map<String, String> row = new HashMap<String, String>();
+ tableData.add(row);
+ row.put(TVROW_KEY_TERM, term.utf8ToString());
+ // try to get DocsAndPositionsEnum
+ DocsEnum de = te.docsAndPositions(null, null);
+ if (de == null) {
+ // if positions are not indexed, get DocsEnum
+ de = te.docs(null, null);
+ }
+ // must have one doc
+ if (de.nextDoc() == DocIdSetIterator.NO_MORE_DOCS) {
+ continue;
+ }
+ row.put(TVROW_KEY_FREQ, String.valueOf(de.freq()));
+ if (de instanceof DocsAndPositionsEnum) {
+ // positions are available
+ DocsAndPositionsEnum dpe = (DocsAndPositionsEnum) de;
+ StringBuilder bufPos = new StringBuilder();
+ StringBuilder bufOff = new StringBuilder();
+ // enumerate all positions info
+ for (int i = 0; i < de.freq(); i++) {
+ int pos = dpe.nextPosition();
+ bufPos.append(String.valueOf(pos));
+ if (i < de.freq() - 1) {
+ bufPos.append((","));
+ }
+ // offsets are indexed?
+ int sOffset = dpe.startOffset();
+ int eOffset = dpe.endOffset();
+ if (sOffset >= 0 && eOffset >= 0) {
+ String offsets = String.valueOf(sOffset) + "-" + String.valueOf(eOffset);
+ bufOff.append(offsets);
+ if (i < de.freq() - 1) {
+ bufOff.append(",");
+ }
+ }
+ }
+ row.put(TVROW_KEY_POSITION, bufPos.toString());
+ row.put(TVROW_KEY_OFFSETS, (bufOff.length() == 0) ? "----" : bufOff.toString());
+ } else {
+ // positions are not available
+ row.put(TVROW_KEY_POSITION, "----");
+ row.put(TVROW_KEY_OFFSETS, "----");
+ }
+ }
+ // register sort listener
+ tvTable.getTableViewSortListeners().add(new TableViewSortListener.Adapter() {
+ @Override
+ public void sortChanged(TableView tableView) {
+ List<Map<String, String>> tableData = (List<Map<String, String>>) tableView.getTableData();
+ tableData.setComparator(new TermVectorTableComparator(tableView));
+ }
+ });
+ // default sort : by ascending order of term
+ Sequence<Dictionary.Pair<String, SortDirection>> sort = new ArrayList<Dictionary.Pair<String, SortDirection>>();
+ sort.add(new Dictionary.Pair<String, SortDirection>(TVROW_KEY_TERM, SortDirection.ASCENDING));
+ sort.add(new Dictionary.Pair<String, SortDirection>(TVROW_KEY_FREQ, SortDirection.DESCENDING));
+ tvTable.setSort(sort);
+
+ tvTable.setTableData(tableData);
+ addPushButtonListener();
+ }
+
+ private void addPushButtonListener() {
+
+ tvCopyButton.getButtonPressListeners().add(new ButtonPressListener() {
+ @Override
+ public void buttonPressed(Button button) {
+ // fired when 'Copy to Clipboard' button pressed
+ Sequence<Map<String, String>> selectedRows = (Sequence<Map<String, String>>) tvTable.getSelectedRows();
+ if (selectedRows == null || selectedRows.getLength() == 0) {
+ Alert.alert(MessageType.INFO, "No rows selected.", getWindow());
+ } else {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < selectedRows.getLength(); i++) {
+ Map<String, String> row = selectedRows.get(i);
+ sb.append(row.get(TVROW_KEY_TERM) + "\t");
+ sb.append(row.get(TVROW_KEY_FREQ) + "\t");
+ sb.append(row.get(TVROW_KEY_POSITION) + "\t");
+ sb.append(row.get(TVROW_KEY_OFFSETS));
+ if (i < selectedRows.getLength() - 1) {
+ sb.append("\n");
+ }
+ }
+ LocalManifest content = new LocalManifest();
+ content.putText(sb.toString());
+ Clipboard.setContent(content);
+ }
+ }
+ });
+ }
+
+}
Index: src/org/apache/lucene/luke/ui/util/FieldsTableRow.java
===================================================================
--- src/org/apache/lucene/luke/ui/util/FieldsTableRow.java (revision 0)
+++ src/org/apache/lucene/luke/ui/util/FieldsTableRow.java (working copy)
@@ -0,0 +1,61 @@
+package org.apache.lucene.luke.ui.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.
+ */
+
+import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.ui.LukeWindow;
+
+public class FieldsTableRow {
+ private String name;
+ private String termCount;
+ private String percent;
+ private Decoder decoder;
+
+ private LukeWindow.LukeMediator lukeMediator;
+
+ public FieldsTableRow(LukeWindow.LukeMediator lukeMediator) {
+ this.lukeMediator = lukeMediator;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getTermCount() {
+ return termCount;
+ }
+ public void setTermCount(String termCount) {
+ this.termCount = termCount;
+ }
+ public String getPercent() {
+ return percent;
+ }
+ public void setPercent(String percent) {
+ this.percent = percent;
+ }
+ public Decoder getDecoder() {
+ return decoder;
+ }
+ public void setDecoder(Decoder decoder) {
+ this.decoder = decoder;
+ this.lukeMediator.getDecoders().put(name, decoder);
+ }
+
+}
Index: src/org/apache/lucene/luke/ui/util/TableComparator.java
===================================================================
--- src/org/apache/lucene/luke/ui/util/TableComparator.java (revision 0)
+++ src/org/apache/lucene/luke/ui/util/TableComparator.java (working copy)
@@ -0,0 +1,102 @@
+package org.apache.lucene.luke.ui.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.
+ */
+
+
+import java.util.Comparator;
+
+import org.apache.pivot.collections.Dictionary;
+import org.apache.pivot.wtk.SortDirection;
+import org.apache.pivot.wtk.TableView;
+
+public class TableComparator implements Comparator<FieldsTableRow> {
+ private TableView tableView;
+
+ public TableComparator(TableView fieldsTable) {
+ if (fieldsTable == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.tableView = fieldsTable;
+ }
+
+ @Override
+ public int compare(FieldsTableRow row1, FieldsTableRow row2) {
+ Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
+
+ int result;
+ if (sort.key.equals("name")) {
+ // sort by name
+ result = row1.getName().compareTo(row2.getName());
+ } else if (sort.key.equals("termCount")) {
+ // sort by termCount
+ Integer c1 = Integer.parseInt(row1.getTermCount());
+ Integer c2 = Integer.parseInt(row2.getTermCount());
+ result = c1.compareTo(c2);
+ } else {
+ // other (ignored)
+ result = 0;
+ }
+ //int result = o1.get("name").compareTo(o2.get("name"));
+ //SortDirection sortDirection = tableView.getSort().get("name");
+ SortDirection sortDirection = sort.value;
+ result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
+
+ return result * -1;
+ }
+}
+
+/*
+public class TableComparator implements Comparator<Map<String,String>> {
+ private TableView tableView;
+
+ public TableComparator(TableView fieldsTable) {
+ if (fieldsTable == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.tableView = fieldsTable;
+ }
+
+ @Override
+ public int compare(Map<String,String> o1, Map<String,String> o2) {
+ Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
+
+ int result;
+ if (sort.key.equals("name")) {
+ // sort by name
+ result = o1.get(sort.key).compareTo(o2.get(sort.key));
+ } else if (sort.key.equals("termCount")) {
+ // sort by termCount
+ Integer c1 = Integer.parseInt(o1.get(sort.key));
+ Integer c2 = Integer.parseInt(o2.get(sort.key));
+ result = c1.compareTo(c2);
+ } else {
+ // other (ignored)
+ result = 0;
+ }
+ //int result = o1.get("name").compareTo(o2.get("name"));
+ //SortDirection sortDirection = tableView.getSort().get("name");
+ SortDirection sortDirection = sort.value;
+ result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
+
+ return result * -1;
+ }
+
+}
+*/
Index: src/org/apache/lucene/luke/ui/util/TermVectorTableComparator.java
===================================================================
--- src/org/apache/lucene/luke/ui/util/TermVectorTableComparator.java (revision 0)
+++ src/org/apache/lucene/luke/ui/util/TermVectorTableComparator.java (working copy)
@@ -0,0 +1,46 @@
+package org.apache.lucene.luke.ui.util;
+
+import org.apache.pivot.collections.Dictionary;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.wtk.SortDirection;
+import org.apache.pivot.wtk.TableView;
+
+import java.util.Comparator;
+
+import static org.apache.lucene.luke.ui.TermVectorWindow.TVROW_KEY_FREQ;
+import static org.apache.lucene.luke.ui.TermVectorWindow.TVROW_KEY_TERM;
+
+
+public class TermVectorTableComparator implements Comparator<Map<String, String>> {
+ private TableView tableView;
+
+ public TermVectorTableComparator(TableView tableView) {
+ if (tableView == null) {
+ throw new IllegalArgumentException();
+ }
+ this.tableView = tableView;
+ }
+
+ @Override
+ public int compare(Map<String, String> row1, Map<String, String> row2) {
+ Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
+
+ int result;
+ if (sort.key.equals(TVROW_KEY_TERM)) {
+ // sort by name
+ result = row1.get(TVROW_KEY_TERM).compareTo(row2.get(TVROW_KEY_TERM));
+ } else if (sort.key.equals(TVROW_KEY_FREQ)) {
+ // sort by termCount
+ Integer f1 = Integer.parseInt(row1.get(TVROW_KEY_FREQ));
+ Integer f2 = Integer.parseInt(row2.get(TVROW_KEY_FREQ));
+ result = f1.compareTo(f2);
+ } else {
+ // other (ignored)
+ result = 0;
+ }
+ SortDirection sortDirection = sort.value;
+ result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
+
+ return result * -1;
+ }
+}