- fix case when terms componenent query returns no results

- implement custom cell renderer with tooltips in query column showing entire query string
This commit is contained in:
adam-m 2012-01-06 10:11:08 -05:00
parent 89bceacdf7
commit 52a0b6cb12
2 changed files with 66 additions and 34 deletions

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.awt.Component;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -27,7 +28,11 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.TopComponent; import org.openide.windows.TopComponent;
@ -50,7 +55,7 @@ persistenceType = TopComponent.PERSISTENCE_NEVER)
preferredID = "KeywordSearchListTopComponent") preferredID = "KeywordSearchListTopComponent")
public final class KeywordSearchListTopComponent extends TopComponent implements KeywordSearchTopComponentInterface { public final class KeywordSearchListTopComponent extends TopComponent implements KeywordSearchTopComponentInterface {
private Logger logger = Logger.getLogger(KeywordSearchListTopComponent.class.getName()); private static Logger logger = Logger.getLogger(KeywordSearchListTopComponent.class.getName());
private KeywordTableModel tableModel; private KeywordTableModel tableModel;
public KeywordSearchListTopComponent() { public KeywordSearchListTopComponent() {
@ -75,10 +80,10 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
keywordTable.setAutoscrolls(true); keywordTable.setAutoscrolls(true);
keywordTable.setTableHeader(null); keywordTable.setTableHeader(null);
keywordTable.setShowHorizontalLines(false); keywordTable.setShowHorizontalLines(true);
keywordTable.setShowVerticalLines(false); keywordTable.setShowVerticalLines(true);
keywordTable.setShowGrid(false); //keywordTable.setShowGrid(false)
//TODO removing dotted line of selected cell might require custom renderer //TODO removing dotted line of selected cell might require code in custom renderer
final int width = keywordTable.getSize().width; final int width = keywordTable.getSize().width;
TableColumn column = null; TableColumn column = null;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -88,21 +93,22 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
//column.setCellEditor(new DefaultCellEditor(new JCheckBox())); //column.setCellEditor(new DefaultCellEditor(new JCheckBox()));
} else { } else {
column.setCellRenderer(new CellTooltipRenderer());
column.setPreferredWidth(((int) (width * 0.7))); column.setPreferredWidth(((int) (width * 0.7)));
} }
} }
keywordTable.setCellSelectionEnabled(false); keywordTable.setCellSelectionEnabled(false);
//keywordTable.setBorder(BorderFactory.createEmptyBorder()); //keywordTable.setBorder(BorderFactory.createEmptyBorder());
//create some empty rows //create some empty rows
tableModel.initEmpty(); tableModel.initEmpty();
//test //test
tableModel.addKeyword("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d"); tableModel.addKeyword("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d");
tableModel.addKeyword("\\d\\d\\.\\d\\d\\d\\.*"); tableModel.addKeyword("\\d\\d\\.\\d\\d\\d\\.*");
tableModel.addKeyword("text"); tableModel.addKeyword("text");
} }
/** This method is called from within the constructor to /** This method is called from within the constructor to
@ -313,7 +319,6 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
private void deleteAllWordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteAllWordsButtonActionPerformed private void deleteAllWordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteAllWordsButtonActionPerformed
tableModel.deleteAll(); tableModel.deleteAll();
}//GEN-LAST:event_deleteAllWordsButtonActionPerformed }//GEN-LAST:event_deleteAllWordsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addWordButton; private javax.swing.JButton addWordButton;
private javax.swing.JTextField addWordField; private javax.swing.JTextField addWordField;
@ -370,18 +375,17 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
} }
@Override @Override
public Map<String,Boolean> getQueryList() { public Map<String, Boolean> getQueryList() {
List<String> selected = getSelectedKeywords(); List<String> selected = getSelectedKeywords();
//filter out blank just in case //filter out blank just in case
Map<String,Boolean> ret = new LinkedHashMap<String,Boolean>(); Map<String, Boolean> ret = new LinkedHashMap<String, Boolean>();
for (String s : selected) { for (String s : selected) {
if (!s.trim().equals("")) if (!s.trim().equals("")) {
ret.put(s, false); ret.put(s, false);
}
} }
return ret; return ret;
} }
@Override @Override
public boolean isLuceneQuerySelected() { public boolean isLuceneQuerySelected() {
@ -416,8 +420,9 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
return tableModel.keywordExists(keyword); return tableModel.keywordExists(keyword);
} }
class KeywordTableModel extends AbstractTableModel { static class KeywordTableModel extends AbstractTableModel {
private static Logger logger = Logger.getLogger(KeywordTableModel.class.getName());
//data //data
private List<TableEntry> keywordData = new ArrayList<TableEntry>(); private List<TableEntry> keywordData = new ArrayList<TableEntry>();
@ -492,28 +497,29 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
keywordData.add(0, new TableEntry(keyword)); keywordData.add(0, new TableEntry(keyword));
this.fireTableRowsInserted(keywordData.size() - 1, keywordData.size()); this.fireTableRowsInserted(keywordData.size() - 1, keywordData.size());
} }
void deleteAll() { void deleteAll() {
keywordData.clear(); keywordData.clear();
initEmpty(); initEmpty();
} }
void deleteSelected() { void deleteSelected() {
List<TableEntry> toDel = new ArrayList<TableEntry>(); List<TableEntry> toDel = new ArrayList<TableEntry>();
int i = 0; int i = 0;
for (TableEntry e: keywordData) { for (TableEntry e : keywordData) {
if (e.isActive && !e.keyword.equals("")) if (e.isActive && !e.keyword.equals("")) {
toDel.add(e); toDel.add(e);
}
} }
for (TableEntry del : toDel) { for (TableEntry del : toDel) {
keywordData.remove(del); keywordData.remove(del);
} }
fireTableDataChanged(); fireTableDataChanged();
} }
void initEmpty() { void initEmpty() {
for (int i = 0; i<20; ++i) { for (int i = 0; i < 20; ++i) {
keywordData.add(0, new TableEntry("", false)); keywordData.add(0, new TableEntry("", false));
} }
fireTableDataChanged(); fireTableDataChanged();
@ -535,4 +541,29 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
} }
} }
} }
/**
* tooltips that show entire query string
*/
public static class CellTooltipRenderer extends JLabel
implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table, Object color,
boolean isSelected, boolean hasFocus,
int row, int column) {
if (column == 0) {
String val = (String)table.getModel().getValueAt(row, column);
setToolTipText(val);
setText(val);
}
return this;
}
}
} }

View File

@ -157,10 +157,10 @@ public class TermComponentQuery implements KeywordSearchQuery {
final SolrQuery q = createQuery(); final SolrQuery q = createQuery();
terms = executeQuery(q); terms = executeQuery(q);
//get unique match result files //get unique match result files
//combine the terms into single Solr query to get files //combine the terms into single Solr query to get files
//it's much more efficient and should yield the same file IDs as per match queries //it's much more efficient and should yield the same file IDs as per match queries
//requires http POST query method due to potentially large query size //requires http POST query method due to potentially large query size
@ -172,17 +172,18 @@ public class TermComponentQuery implements KeywordSearchQuery {
filesQueryB.append(" "); filesQueryB.append(" ");
} }
List<FsContent> uniqueMatches = new ArrayList<FsContent>(); List<FsContent> uniqueMatches = new ArrayList<FsContent>();
LuceneQuery filesQuery = new LuceneQuery(filesQueryB.toString()); if (! terms.isEmpty()) {
filesQuery.escape(); //TODO escaping invididual terms above instead could make a difference to Solr LuceneQuery filesQuery = new LuceneQuery(filesQueryB.toString());
try { filesQuery.escape(); //TODO escaping invididual terms above instead could make a difference to Solr
uniqueMatches = filesQuery.performQuery(); try {
} uniqueMatches = filesQuery.performQuery();
catch (RuntimeException e) { } catch (RuntimeException e) {
logger.log(Level.SEVERE, "Error executing Solr query,", e); logger.log(Level.SEVERE, "Error executing Solr query,", e);
}
} }
//filter out non-matching files using the original query (whether literal or not) //filter out non-matching files using the original query (whether literal or not)
//TODO this could be costly, for now just testing how it performs //TODO this could be costly, for now just testing how it performs
for (FsContent f : uniqueMatches) { for (FsContent f : uniqueMatches) {