| 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; |
| + } |
| +} |