PageRenderTime 79ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/3.1.0/src/org/getopt/luke/Luke.java

http://luke.googlecode.com/
Java | 4726 lines | 4239 code | 178 blank | 309 comment | 988 complexity | ed6ce736556028291fd87ef78bffcd8e MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.getopt.luke;
  18. import java.awt.Color;
  19. import java.awt.Font;
  20. import java.awt.GraphicsEnvironment;
  21. import java.awt.Toolkit;
  22. import java.awt.datatransfer.Clipboard;
  23. import java.awt.datatransfer.ClipboardOwner;
  24. import java.awt.datatransfer.StringSelection;
  25. import java.awt.datatransfer.Transferable;
  26. import java.io.*;
  27. import java.lang.reflect.Constructor;
  28. import java.lang.reflect.Method;
  29. import java.text.DecimalFormat;
  30. import java.text.NumberFormat;
  31. import java.util.*;
  32. import java.util.Map.Entry;
  33. import java.util.zip.GZIPOutputStream;
  34. import javax.swing.JFileChooser;
  35. import javax.swing.UIManager;
  36. import org.apache.lucene.LucenePackage;
  37. import org.apache.lucene.analysis.*;
  38. import org.apache.lucene.analysis.payloads.PayloadHelper;
  39. import org.apache.lucene.analysis.standard.StandardAnalyzer;
  40. import org.apache.lucene.document.DateTools;
  41. import org.apache.lucene.document.Document;
  42. import org.apache.lucene.document.Field;
  43. import org.apache.lucene.document.NumberTools;
  44. import org.apache.lucene.document.Field.Index;
  45. import org.apache.lucene.document.Field.Store;
  46. import org.apache.lucene.index.*;
  47. import org.apache.lucene.index.IndexReader.FieldOption;
  48. import org.apache.lucene.index.IndexWriter.MaxFieldLength;
  49. import org.apache.lucene.misc.SweetSpotSimilarity;
  50. import org.apache.lucene.queryParser.QueryParser;
  51. import org.apache.lucene.search.*;
  52. import org.apache.lucene.search.BooleanClause.Occur;
  53. import org.apache.lucene.search.payloads.PayloadNearQuery;
  54. import org.apache.lucene.search.payloads.PayloadTermQuery;
  55. import org.apache.lucene.search.similar.MoreLikeThis;
  56. import org.apache.lucene.search.spans.SpanFirstQuery;
  57. import org.apache.lucene.search.spans.SpanNearQuery;
  58. import org.apache.lucene.search.spans.SpanNotQuery;
  59. import org.apache.lucene.search.spans.SpanOrQuery;
  60. import org.apache.lucene.search.spans.SpanQuery;
  61. import org.apache.lucene.search.spans.SpanTermQuery;
  62. import org.apache.lucene.search.spans.Spans;
  63. import org.apache.lucene.store.*;
  64. import org.apache.lucene.util.NumericUtils;
  65. import org.apache.lucene.util.Version;
  66. import org.apache.lucene.xmlparser.CoreParser;
  67. import org.apache.lucene.xmlparser.CorePlusExtensionsParser;
  68. import org.getopt.luke.DocReconstructor.Reconstructed;
  69. import org.getopt.luke.decoders.BinaryDecoder;
  70. import org.getopt.luke.decoders.DateDecoder;
  71. import org.getopt.luke.decoders.Decoder;
  72. import org.getopt.luke.decoders.NumDoubleDecoder;
  73. import org.getopt.luke.decoders.NumFloatDecoder;
  74. import org.getopt.luke.decoders.NumIntDecoder;
  75. import org.getopt.luke.decoders.NumLongDecoder;
  76. import org.getopt.luke.decoders.OldDateFieldDecoder;
  77. import org.getopt.luke.decoders.OldNumberToolsDecoder;
  78. import org.getopt.luke.decoders.StringDecoder;
  79. import org.getopt.luke.plugins.ScriptingPlugin;
  80. import org.getopt.luke.xmlQuery.XmlQueryParserFactory;
  81. import org.getopt.luke.xmlQuery.CorePlusExtensionsParserFactory;
  82. import thinlet.FrameLauncher;
  83. import thinlet.Thinlet;
  84. /**
  85. * This class allows you to browse a <a href="jakarta.apache.org/lucene">Lucene
  86. * </a> index in several ways - by document, by term, by query, and by most
  87. * frequent terms.
  88. *
  89. * @author Andrzej Bialecki
  90. *
  91. */
  92. public class Luke extends Thinlet implements ClipboardOwner {
  93. private Directory dir = null;
  94. String pName = null;
  95. private IndexReader ir = null;
  96. private IndexSearcher is = null;
  97. private boolean slowAccess = false;
  98. private Collection<String> fn = null;
  99. private String[] idxFields = null;
  100. private HashMap<String, FieldTermCount> termCounts = new HashMap<String, FieldTermCount>();
  101. private List<LukePlugin> plugins = new ArrayList<LukePlugin>();
  102. private Object errorDlg = null;
  103. private Object infoDlg = null;
  104. private Object statmsg = null;
  105. private Object slowstatus = null;
  106. private Object slowmsg = null;
  107. private Analyzer stdAnalyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);
  108. private Analyzer analyzer = null;
  109. //private QueryParser qp = null;
  110. private boolean readOnly = false;
  111. private boolean ram = false;
  112. private boolean keepCommits = false;
  113. private boolean multi = false;
  114. private int tiiDiv = 1;
  115. private IndexCommit currentCommit = null;
  116. private Similarity similarity = null;
  117. private Object lastST;
  118. private HashMap<String, Decoder> decoders = new HashMap<String, Decoder>();
  119. private Decoder defDecoder = new StringDecoder();
  120. /** Default salmon theme. */
  121. public static final int THEME_DEFAULT = 0;
  122. /** Gray theme. */
  123. public static final int THEME_GRAY = 1;
  124. /** Sandstone theme. */
  125. public static final int THEME_SANDSTONE = 2;
  126. /** Sky blue theme. */
  127. public static final int THEME_SKY = 3;
  128. /** Navy blue reverse theme. */
  129. public static final int THEME_NAVY = 4;
  130. /** Theme color contants. */
  131. public int[][] themes = {
  132. {0xece9d0, 0x000000, 0xf5f4f0, 0x919b9a, 0xb0b0b0, 0xeeeeee, 0xb9b9b9, 0xff8080, 0xc5c5dd}, // default
  133. {0xe6e6e6, 0x000000, 0xffffff, 0x909090, 0xb0b0b0, 0xededed, 0xb9b9b9, 0x89899a, 0xc5c5dd}, // gray
  134. {0xeeeecc, 0x000000, 0xffffff, 0x999966, 0xb0b096, 0xededcb, 0xcccc99, 0xcc6600, 0xffcc66}, // sandstone
  135. {0xf0f0ff, 0x0000a0, 0xffffff, 0x8080ff, 0xb0b0b0, 0xededed, 0xb0b0ff, 0xff0000, 0xfde0e0}, // sky
  136. {0x6375d6, 0xffffff, 0x7f8fdd, 0xd6dff5, 0x9caae5, 0x666666, 0x003399, 0xff3333, 0x666666} // navy
  137. };
  138. private int numTerms = 0;
  139. private static boolean exitOnDestroy = false;
  140. private Class[] analyzers = null;
  141. private String baseDir = null;
  142. private Class[] defaultAnalyzers = { SimpleAnalyzer.class, StandardAnalyzer.class, StopAnalyzer.class,
  143. WhitespaceAnalyzer.class };
  144. private static final String MSG_NOINDEX = "FAILED: No index, or index is closed. Reopen it.";
  145. private static final String MSG_READONLY = "FAILED: Read-Only index.";
  146. private static final String MSG_CONV_ERROR = "Some values could not be properly represented in this format. " +
  147. "They are marked in grey and presented as a hex dump.";
  148. /** Default constructor, loads preferences, initializes plugins and GUI. */
  149. public Luke() {
  150. super();
  151. Prefs.load();
  152. try {
  153. UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  154. } catch (Exception e) {}
  155. setTheme(Prefs.getInteger(Prefs.P_THEME, THEME_DEFAULT));
  156. String fontName = Prefs.getProperty(Prefs.P_FONT_NAME, "SansSerif");
  157. String fontSize = Prefs.getProperty(Prefs.P_FONT_SIZE, "12.0");
  158. float fsize = 12.0f;
  159. try {
  160. fsize = Float.parseFloat(fontSize);
  161. } catch (Exception e) {};
  162. Font f = new Font(fontName, Font.PLAIN, (int)fsize);
  163. setFont(f);
  164. addComponent(this, "/xml/luke.xml", null, null);
  165. errorDlg = addComponent(null, "/xml/error.xml", null, null);
  166. infoDlg = addComponent(null, "/xml/info.xml", null, null);
  167. statmsg = find("statmsg");
  168. slowstatus = find("slowstat");
  169. slowmsg = find(slowstatus, "slowmsg");
  170. // populate analyzers
  171. try {
  172. Class[] an = ClassFinder.getInstantiableSubclasses(Analyzer.class);
  173. if (an == null || an.length == 0) {
  174. analyzers = defaultAnalyzers;
  175. } else {
  176. HashSet<Class> uniq = new HashSet<Class>(Arrays.asList(an));
  177. analyzers = (Class[])uniq.toArray(new Class[uniq.size()]);
  178. }
  179. Object cbType = find("cbType");
  180. populateAnalyzers(cbType);
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. }
  184. loadPlugins();
  185. }
  186. /**
  187. * Set color theme for the UI.
  188. * @param which one of the predefined themes. For custom themes use {@link Thinlet#setColors(int, int, int, int, int, int, int, int, int)}.
  189. */
  190. public void setTheme(int which) {
  191. if (which < 0 || which >= themes.length) which = THEME_DEFAULT;
  192. int[] t = themes[which];
  193. setColors(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]);
  194. Prefs.setProperty(Prefs.P_THEME, which + "");
  195. }
  196. /**
  197. * Action handler to select color theme.
  198. * @param menu
  199. */
  200. public void actionTheme(Object menu) {
  201. String which = (String)getProperty(menu, "t");
  202. int t = THEME_DEFAULT;
  203. try {
  204. t = Integer.parseInt(which);
  205. } catch (Exception e) {};
  206. setTheme(t);
  207. }
  208. /**
  209. * Populate a combobox with the current list of analyzers.
  210. * @param combo
  211. */
  212. public void populateAnalyzers(Object combo) {
  213. removeAll(combo);
  214. String[] aNames = new String[analyzers.length];
  215. for (int i = 0; i < analyzers.length; i++) {
  216. aNames[i] = analyzers[i].getName();
  217. }
  218. Arrays.sort(aNames);
  219. for (int i = 0; i < aNames.length; i++) {
  220. Object choice = create("choice");
  221. setString(choice, "text", aNames[i]);
  222. add(combo, choice);
  223. if (i == 0) {
  224. setString(combo, "text", aNames[i]);
  225. }
  226. }
  227. int lastAnalyzerIdx = 0;
  228. String lastAnalyzer = Prefs.getProperty(Prefs.P_ANALYZER);
  229. if (lastAnalyzer != null) lastAnalyzerIdx = getIndex(combo, lastAnalyzer);
  230. if (lastAnalyzerIdx < 0) lastAnalyzerIdx = 0;
  231. setInteger(combo, "selected", lastAnalyzerIdx);
  232. }
  233. /**
  234. * Return an array of available Analyzer implementations.
  235. * @return
  236. */
  237. public Class[] getAnalyzers() {
  238. return analyzers;
  239. }
  240. /**
  241. * Loads plugins. Plugins are first searched from the CLASSPATH, and then from a
  242. * plugin list contained in a resource file "/.plugins". The "/.plugins" resource file
  243. * has a simple format - one fully qualified class name per line. Blank lines and
  244. * lines starting with '#' are ignored.
  245. */
  246. private void loadPlugins() {
  247. List pluginClasses = new ArrayList();
  248. // try to find all plugins
  249. try {
  250. Class classes[] = ClassFinder.getInstantiableSubclasses(LukePlugin.class);
  251. if (classes != null && classes.length > 0) {
  252. pluginClasses.addAll(Arrays.asList(classes));
  253. }
  254. } catch (Exception e) {
  255. e.printStackTrace();
  256. }
  257. // load plugins declared in the ".plugins" file
  258. try {
  259. InputStream is = getClass().getResourceAsStream("/.plugins");
  260. if (is != null) {
  261. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  262. String line = null;
  263. while ((line = br.readLine()) != null) {
  264. if (line.startsWith("#")) continue;
  265. if (line.trim().equals("")) continue;
  266. try {
  267. Class clazz = Class.forName(line.trim());
  268. if (clazz.getSuperclass().equals(LukePlugin.class) && !pluginClasses.contains(clazz)) {
  269. pluginClasses.add(clazz);
  270. }
  271. } catch (Throwable x) {
  272. //
  273. }
  274. }
  275. }
  276. } catch (Exception e) {
  277. e.printStackTrace();
  278. }
  279. try {
  280. StringBuffer errors = new StringBuffer("Unable to load some plugins:");
  281. boolean failures = false;
  282. for (int i = 0; i < pluginClasses.size(); i++) {
  283. try {
  284. LukePlugin plugin = (LukePlugin) ((Class) pluginClasses.get(i)).getConstructor(new Class[0]).newInstance(
  285. new Object[0]);
  286. String xul = plugin.getXULName();
  287. if (xul == null) continue;
  288. Object ui = parse(xul, plugin);
  289. plugin.setApplication(this);
  290. plugin.setMyUi(ui);
  291. plugins.add(plugin);
  292. } catch (Exception e) {
  293. failures = true;
  294. e.printStackTrace();
  295. errors.append("\n" + pluginClasses.get(i).toString());
  296. }
  297. }
  298. if (failures) {
  299. errorMsg(errors.toString());
  300. }
  301. } catch (Exception e) {
  302. e.printStackTrace();
  303. errorMsg(e.toString());
  304. }
  305. if (plugins.size() == 0) return;
  306. initPlugins();
  307. }
  308. /**
  309. * Create UI for a single plugin.
  310. * @param tabs parent tabbedpane
  311. * @param plugin plugin instance
  312. */
  313. private void addPluginTab(Object tabs, LukePlugin plugin) {
  314. Object tab = create("tab");
  315. setColor(tab, "foreground", new Color(0x006000));
  316. setString(tab, "text", plugin.getPluginName());
  317. setFont(tab, getFont().deriveFont(Font.BOLD));
  318. add(tabs, tab);
  319. Object panel = create("panel");
  320. setInteger(panel, "gap", 2);
  321. setInteger(panel, "weightx", 1);
  322. setInteger(panel, "weighty", 1);
  323. setChoice(panel, "halign", "fill");
  324. setChoice(panel, "valign", "fill");
  325. setInteger(panel, "columns", 1);
  326. add(tab, panel);
  327. Object infobar = create("panel");
  328. setInteger(infobar, "gap", 8);
  329. setInteger(infobar, "top", 2);
  330. setInteger(infobar, "bottom", 2);
  331. setInteger(infobar, "weightx", 1);
  332. setChoice(infobar, "halign", "fill");
  333. setColor(infobar, "background", new Color(0xc0f0c0));
  334. add(panel, infobar);
  335. Object label = create("label");
  336. setString(label, "text", plugin.getPluginInfo());
  337. add(infobar, label);
  338. Object link = create("button");
  339. setChoice(link, "type", "link");
  340. setString(link, "text", plugin.getPluginHome());
  341. putProperty(link, "url", plugin.getPluginHome());
  342. setMethod(link, "action", "goUrl(this)", infobar, this);
  343. add(infobar, link);
  344. add(panel, create("separator"));
  345. add(panel, plugin.getMyUi());
  346. }
  347. /**
  348. * Return the list of active plugin instances.
  349. * @return
  350. */
  351. public List getPlugins() {
  352. return Collections.unmodifiableList(plugins);
  353. }
  354. /**
  355. * Get an already instantiated plugin, or null if such plugin was
  356. * not loaded on startup.
  357. * @param className fully qualified plugin classname
  358. * @return
  359. */
  360. public LukePlugin getPlugin(String className) {
  361. for (int i = 0; i < plugins.size(); i++) {
  362. Object plugin = plugins.get(i);
  363. if (plugin.getClass().getName().equals(className))
  364. return (LukePlugin)plugin;
  365. }
  366. return null;
  367. }
  368. Thread statusThread = null;
  369. long lastUpdate = 0;
  370. long statusSleep = 0;
  371. /**
  372. * Display a message on the status bar for 5 seconds.
  373. * @param msg message to display. Too long messages will be truncated by the UI.
  374. */
  375. public void showStatus(final String msg) {
  376. if (statusThread != null && statusThread.isAlive()) {
  377. setString(statmsg, "text", msg);
  378. statusSleep = 5000;
  379. } else {
  380. statusThread = new Thread() {
  381. public void run() {
  382. statusSleep = 5000;
  383. setString(statmsg, "text", msg);
  384. while (statusSleep > 0) {
  385. try {
  386. sleep(500);
  387. } catch (Exception e) {};
  388. statusSleep -= 500;
  389. }
  390. setString(statmsg, "text", "");
  391. }
  392. };
  393. statusThread.start();
  394. }
  395. }
  396. /**
  397. * As {@link #showStatus(String)} but also sets the "Last search time" label.
  398. * @param msg
  399. */
  400. public void showSearchStatus(String msg) {
  401. setString(lastST, "text", msg);
  402. showStatus(msg);
  403. }
  404. long lastSlowUpdate = 0L;
  405. long lastSlowCounter = 0L;
  406. Thread slowThread = null;
  407. long slowSleep = 0;
  408. public void showSlowStatus(final String msg, final long counter) {
  409. if (slowThread != null && slowThread.isAlive()) {
  410. lastSlowCounter += counter;
  411. setString(slowmsg, "text", msg + " " + lastSlowCounter);
  412. slowSleep = 5000;
  413. } else {
  414. slowThread = new Thread() {
  415. public void run() {
  416. slowSleep = 5000;
  417. lastSlowCounter = counter;
  418. setBoolean(slowstatus, "visible", true);
  419. setString(slowmsg, "text", msg + " " + lastSlowCounter);
  420. while (slowSleep > 0) {
  421. try {
  422. sleep(500);
  423. } catch (Exception e) {};
  424. slowSleep -= 500;
  425. }
  426. setString(slowmsg, "text", "");
  427. setBoolean(slowstatus, "visible", false);
  428. }
  429. };
  430. slowThread.start();
  431. }
  432. }
  433. /**
  434. * Add a Thinlet component from XUL file.
  435. * @param parent add the new component to this parent
  436. * @param compView path to the XUL resource
  437. * @param handlerStr fully qualified classname of the handler to instantiate,
  438. * or null if the current class will become the handler
  439. * @param argv if not null, these arguments will be passed to the
  440. * appropriate constructor.
  441. * @return
  442. */
  443. public Object addComponent(Object parent, String compView, String handlerStr, Object[] argv) {
  444. Object res = null;
  445. Object handler = null;
  446. try {
  447. if (handlerStr != null) {
  448. if (argv == null) {
  449. handler = Class.forName(handlerStr).getConstructor(new Class[] { Thinlet.class }).newInstance(
  450. new Object[] { this });
  451. } else {
  452. handler = Class.forName(handlerStr).getConstructor(new Class[] { Thinlet.class, Object[].class })
  453. .newInstance(new Object[] { this, argv });
  454. }
  455. }
  456. if (handler != null) {
  457. res = parse(compView, handler);
  458. } else res = parse(compView);
  459. if (parent != null) {
  460. if (parent instanceof Thinlet)
  461. add(res);
  462. else add(parent, res);
  463. }
  464. return res;
  465. } catch (Exception exc) {
  466. exc.printStackTrace();
  467. errorMsg(exc.getMessage());
  468. return null;
  469. }
  470. }
  471. /**
  472. * Show a modal error dialog with OK button.
  473. * @param msg error message
  474. */
  475. public void errorMsg(String msg) {
  476. Object fMsg = find(errorDlg, "msg");
  477. setString(fMsg, "text", msg);
  478. add(errorDlg);
  479. }
  480. /**
  481. * Show a modal info dialog with OK button.
  482. * @param msg info message
  483. */
  484. public void infoMsg(String msg) {
  485. Object fMsg = find(infoDlg, "msg");
  486. setString(fMsg, "text", msg);
  487. add(infoDlg);
  488. }
  489. /**
  490. * Show an "Open Index" dialog.
  491. *
  492. */
  493. public void actionOpen() {
  494. Object dialog = addComponent(this, "/xml/lukeinit.xml", null, null);
  495. Object path = find(dialog, "path");
  496. if (this.baseDir != null)
  497. setString(path, "text", this.baseDir);
  498. else setString(path, "text", System.getProperty("user.dir"));
  499. }
  500. /**
  501. * Browse for a directory, and put the selection result in the
  502. * indicated widget.
  503. * @param path Thinlet widget to put the result
  504. */
  505. public void openBrowse(Object path) {
  506. JFileChooser fd = new JFileChooser();
  507. fd.setDialogType(JFileChooser.OPEN_DIALOG);
  508. fd.setDialogTitle("Select Index directory");
  509. fd.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
  510. fd.setFileHidingEnabled(false);
  511. String strPath = getString(path, "text");
  512. if (strPath != null) strPath.trim();
  513. if (strPath != null && strPath.length() > 0)
  514. fd.setCurrentDirectory(new File(strPath));
  515. else if (this.baseDir != null)
  516. fd.setCurrentDirectory(new File(this.baseDir));
  517. else fd.setCurrentDirectory(new File(System.getProperty("user.dir")));
  518. int res = fd.showOpenDialog(this);
  519. File iDir = null;
  520. if (res == JFileChooser.APPROVE_OPTION) iDir = fd.getSelectedFile();
  521. if (iDir != null && iDir.exists()) {
  522. if (!iDir.isDirectory()) iDir = iDir.getParentFile();
  523. setString(path, "text", iDir.toString());
  524. }
  525. }
  526. /**
  527. * Select an output file name, and put the selection result in the
  528. * indicated widget.
  529. * @param path Thinlet widget to put the result
  530. */
  531. public void saveBrowse(Object path, Object startButton) {
  532. JFileChooser fd = new JFileChooser();
  533. fd.setDialogType(JFileChooser.SAVE_DIALOG);
  534. fd.setDialogTitle("Select Output File");
  535. fd.setFileSelectionMode(JFileChooser.FILES_ONLY);
  536. fd.setFileHidingEnabled(false);
  537. String strPath = getString(path, "text");
  538. if (strPath != null) strPath.trim();
  539. if (strPath != null && strPath.length() > 0)
  540. fd.setCurrentDirectory(new File(strPath));
  541. else if (this.baseDir != null)
  542. fd.setCurrentDirectory(new File(this.baseDir));
  543. else fd.setCurrentDirectory(new File(System.getProperty("user.dir")));
  544. int res = fd.showSaveDialog(this);
  545. setBoolean(startButton, "enabled", false);
  546. File iFile = null;
  547. if (res == JFileChooser.APPROVE_OPTION) iFile = fd.getSelectedFile();
  548. if (iFile != null) {
  549. setString(path, "text", iFile.toString());
  550. setBoolean(startButton, "enabled", true);
  551. }
  552. }
  553. /**
  554. * Initialize MRU list of indexes in the open index dialog.
  555. * @param dialog
  556. */
  557. public void setupInit(Object dialog) {
  558. Object path = find(dialog, "path");
  559. syncMRU(path);
  560. }
  561. /**
  562. * Attempt to load the index with parameters specified in the dialog.
  563. * <p>NOTE: this method is invoked from the UI. If you need to open an index
  564. * programmatically, you should use {@link #openIndex(String, boolean, boolean, boolean)} instead.</p>
  565. * @param dialog UI dialog with parameters
  566. */
  567. public void openOk(Object dialog) {
  568. Object path = find(dialog, "path");
  569. pName = getString(path, "text").trim();
  570. boolean force = getBoolean(find(dialog, "force"), "selected");
  571. boolean noReader = getBoolean(find(dialog, "cbNoReader"), "selected");
  572. tiiDiv = 1;
  573. try {
  574. tiiDiv = Integer.parseInt(getString(find(dialog, "tiiDiv"), "text"));
  575. } catch (Exception e) {
  576. e.printStackTrace();
  577. }
  578. Object dirImpl = getSelectedItem(find(dialog, "dirImpl"));
  579. String dirClass = null;
  580. if (dirImpl == null) {
  581. dirClass = FSDirectory.class.getName();
  582. } else {
  583. String name = getString(dirImpl, "name");
  584. if (name == null) {
  585. dirClass = getString(dirImpl, "text");
  586. } else {
  587. if (name.equals("fs")) {
  588. dirClass = FSDirectory.class.getName();
  589. } else if (name.equals("mmap")) {
  590. dirClass = MMapDirectory.class.getName();
  591. } else if (name.equals("niofs")) {
  592. dirClass = NIOFSDirectory.class.getName();
  593. }
  594. }
  595. }
  596. if (pName == null || pName.trim().equals("")) {
  597. errorMsg("Invalid path.");
  598. return;
  599. }
  600. readOnly = getBoolean(find(dialog, "ro"), "selected");
  601. ram = getBoolean(find(dialog, "ram"), "selected");
  602. keepCommits = getBoolean(find(dialog, "cbKeepCommits"), "selected");
  603. slowAccess = getBoolean(find(dialog, "cbSlowIO"), "selected");
  604. decoders.clear();
  605. currentCommit = null;
  606. Prefs.addToMruList(pName);
  607. syncMRU(path);
  608. remove(dialog);
  609. if (noReader) {
  610. removeAll();
  611. addComponent(this, "/xml/luke.xml", null, null);
  612. try {
  613. Directory d = openDirectory(dirClass, pName, false);
  614. if (IndexReader.indexExists(d)) {
  615. throw new Exception("there is no valid Lucene index in this directory.");
  616. }
  617. dir = d;
  618. initOverview();
  619. infoMsg("There is no IndexReader - most actions are disabled. " +
  620. "You can open IndexReader from current Directory using 'Re-Open'");
  621. } catch (Exception e) {
  622. errorMsg("ERROR: " + e.toString());
  623. }
  624. } else {
  625. openIndex(pName, force, dirClass, readOnly, ram, keepCommits, null, tiiDiv);
  626. }
  627. }
  628. public void actionClose() {
  629. if (ir != null) {
  630. try {
  631. if (is != null) is.close();
  632. ir.close();
  633. if (dir != null) dir.close();
  634. } catch (Exception e) {
  635. e.printStackTrace();
  636. errorMsg("Close failed: " + e.getMessage());
  637. }
  638. }
  639. ir = null;
  640. dir = null;
  641. is = null;
  642. removeAll();
  643. addComponent(this, "/xml/luke.xml", null, null);
  644. initPlugins();
  645. }
  646. public void actionCommit() {
  647. if (ir == null) {
  648. showStatus(MSG_NOINDEX);
  649. return;
  650. }
  651. if (readOnly) {
  652. showStatus(MSG_READONLY);
  653. return;
  654. }
  655. if (!IndexGate.hasChanges(ir)) {
  656. showStatus("No changes - commit ignored.");
  657. return;
  658. }
  659. Object dialog = addComponent(this, "/xml/commit.xml", null, null);
  660. Map userData = ir.getCommitUserData();
  661. TreeMap ud = new TreeMap(userData);
  662. putProperty(dialog, "userData", ud);
  663. _showUserData(dialog);
  664. }
  665. private void _showUserData(Object dialog) {
  666. Object table = find(dialog, "data");
  667. removeAll(table);
  668. Map<Object,Object> ud = (Map)getProperty(dialog, "userData");
  669. for (Entry e : ud.entrySet()) {
  670. Object row = create("row");
  671. putProperty(row, "key", e.getKey());
  672. add(table, row);
  673. Object cell = create("cell");
  674. setString(cell, "text", e.getKey().toString());
  675. add(row, cell);
  676. cell = create("cell");
  677. setString(cell, "text", e.getValue().toString());
  678. add(row, cell);
  679. }
  680. }
  681. public void putUserData(Object dialog) {
  682. Object key = find(dialog, "key");
  683. Object value = find(dialog, "value");
  684. String k = getString(key, "text");
  685. String v = getString(value, "text");
  686. if (k.equals("")) {
  687. showStatus("Cannot add empty key.");
  688. return;
  689. }
  690. Map<Object,Object> ud = (Map)getProperty(dialog, "userData");
  691. ud.put(k, v);
  692. _showUserData(dialog);
  693. }
  694. public void deleteUserData(Object dialog) {
  695. Object table = find(dialog, "data");
  696. Map ud = (Map)getProperty(dialog, "userData");
  697. Object[] rows = getSelectedItems(table);
  698. if (rows == null || rows.length == 0) {
  699. return;
  700. }
  701. for (Object row : rows) {
  702. Object key = getProperty(row, "key");
  703. ud.remove(key);
  704. }
  705. _showUserData(dialog);
  706. }
  707. public void commitUserData(Object dialog) {
  708. Map userData = (Map)getProperty(dialog, "userData");
  709. remove(dialog);
  710. try {
  711. ir.flush(userData);
  712. initOverview();
  713. showFiles(dir, Collections.EMPTY_LIST);
  714. } catch (Exception e) {
  715. errorMsg("Error: " + e.toString());
  716. }
  717. }
  718. public void actionReopen() {
  719. if (dir == null) {
  720. return;
  721. }
  722. openIndex(pName, false, dir.getClass().getName(), readOnly, ram,
  723. keepCommits, currentCommit, tiiDiv);
  724. }
  725. /**
  726. * Open indicated index and re-initialize all GUI and plugins.
  727. * @param pName path to index
  728. * @param force if true, and the index is locked, unlock it first. If false, and
  729. * the index is locked, an error will be reported.
  730. * @param readOnly open in read-only mode, and disallow modifications.
  731. */
  732. public void openIndex(String name, boolean force, String dirImpl, boolean ro,
  733. boolean ramdir, boolean keepCommits, IndexCommit point, int tiiDivisor) {
  734. pName = name;
  735. readOnly = ro;
  736. removeAll();
  737. File baseFileDir = new File(name);
  738. this.baseDir = baseFileDir.toString();
  739. addComponent(this, "/xml/luke.xml", null, null);
  740. statmsg = find("statmsg");
  741. if (dir != null) {
  742. try {
  743. if (ir != null) ir.close();
  744. } catch (Exception e) {}
  745. ;
  746. try {
  747. if (dir != null) dir.close();
  748. } catch (Exception e) {}
  749. ;
  750. }
  751. ArrayList<Directory> dirs = new ArrayList<Directory>();
  752. try {
  753. Directory d = openDirectory(dirImpl, pName, false);
  754. if (IndexWriter.isLocked(d)) {
  755. if (ro) {
  756. errorMsg("Index is locked and Read-Only. Open for read-write and 'Force unlock'.");
  757. d.close();
  758. d = null;
  759. return;
  760. }
  761. if (force) {
  762. IndexWriter.unlock(d);
  763. } else {
  764. errorMsg("Index is locked. Try 'Force unlock' when opening.");
  765. d.close();
  766. d = null;
  767. return;
  768. }
  769. }
  770. boolean existsSingle = false;
  771. try {
  772. existsSingle = IndexReader.indexExists(d);
  773. } catch (Exception e) {
  774. //
  775. }
  776. if (!existsSingle) { // try multi
  777. File[] files = baseFileDir.listFiles();
  778. for (File f : files) {
  779. if (f.isFile()) {
  780. continue;
  781. }
  782. Directory d1 = openDirectory(dirImpl, f.toString(), false);
  783. if (IndexWriter.isLocked(d1)) {
  784. if (ro) {
  785. errorMsg("Index is locked and Read-Only. Open for read-write and 'Force unlock'.");
  786. d1.close();
  787. d1 = null;
  788. return;
  789. }
  790. if (force) {
  791. IndexWriter.unlock(d1);
  792. } else {
  793. errorMsg("Index is locked. Try 'Force unlock' when opening.");
  794. d1.close();
  795. d1 = null;
  796. return;
  797. }
  798. }
  799. existsSingle = false;
  800. try {
  801. existsSingle = IndexReader.indexExists(d1);
  802. } catch (Exception e) {};
  803. if (!existsSingle) {
  804. d1.close();
  805. continue;
  806. }
  807. dirs.add(d1);
  808. }
  809. } else {
  810. dirs.add(d);
  811. }
  812. if (dirs.size() == 0) {
  813. errorMsg("No valid directory at the location, try another location.");
  814. return;
  815. }
  816. if (ramdir) {
  817. showStatus("Loading index into RAMDirectory ...");
  818. Directory dir1 = new RAMDirectory();
  819. IndexWriter iw1 = new IndexWriter(dir1, new SimpleAnalyzer(), MaxFieldLength.UNLIMITED);
  820. iw1.addIndexesNoOptimize((Directory[])dirs.toArray(new Directory[dirs.size()]));
  821. iw1.close();
  822. showStatus("RAMDirectory loading done!");
  823. dir.close();
  824. dir = dir1;
  825. }
  826. IndexDeletionPolicy policy;
  827. if (keepCommits) {
  828. policy = new KeepAllIndexDeletionPolicy();
  829. } else {
  830. policy = new KeepLastIndexDeletionPolicy();
  831. }
  832. ArrayList<IndexReader> readers = new ArrayList<IndexReader>();
  833. for (Directory dd : dirs) {
  834. IndexReader reader;
  835. if (tiiDivisor > 1) {
  836. reader = IndexReader.open(dd, policy, ro, tiiDivisor);
  837. } else {
  838. reader = IndexReader.open(dd, policy, ro);
  839. }
  840. readers.add(reader);
  841. }
  842. if (readers.size() == 1) {
  843. ir = readers.get(0);
  844. dir = ir.directory();
  845. } else {
  846. ir = new MultiReader((IndexReader[])readers.toArray(new IndexReader[readers.size()]));
  847. }
  848. is = new IndexSearcher(ir);
  849. // XXX
  850. slowAccess = false;
  851. initOverview();
  852. initPlugins();
  853. showStatus("Index successfully open.");
  854. } catch (Exception e) {
  855. e.printStackTrace();
  856. errorMsg(e.getMessage());
  857. return;
  858. }
  859. }
  860. /**
  861. * Open a single directory.
  862. * @param dirImpl fully-qualified class name of Directory implementation,
  863. * or "FSDirectory" for {@link FSDirectory}
  864. * @param file index directory
  865. * @param create if true, create a new directory
  866. * @return directory implementation
  867. */
  868. Class defaultDirImpl = null;
  869. public Directory openDirectory(String dirImpl, String file, boolean create) throws Exception {
  870. File f = new File(file);
  871. if (!f.exists()) {
  872. throw new Exception("Index directory doesn't exist.");
  873. }
  874. Directory res = null;
  875. if (dirImpl == null || dirImpl.equals(FSDirectory.class.getName())) {
  876. return FSDirectory.open(f);
  877. }
  878. try {
  879. Class implClass = Class.forName(dirImpl);
  880. Constructor<Directory> constr = implClass.getConstructor(File.class);
  881. res = constr.newInstance(f);
  882. } catch (Throwable e) {
  883. errorMsg("Invalid directory implementation class: " + dirImpl + " " + e);
  884. return null;
  885. }
  886. if (res != null) return res;
  887. // fall-back to FSDirectory.
  888. if (res == null) return FSDirectory.open(f);
  889. return null;
  890. }
  891. /**
  892. * Indicates whether I/O access should be optimized because
  893. * the index is on a slow medium (e.g. remote).
  894. * @return true if I/O access is costly and should be minimized
  895. */
  896. public boolean isSlowAccess() {
  897. return slowAccess;
  898. }
  899. /**
  900. * Set whether the I/O access to this index is costly and
  901. * should be minimized.
  902. */
  903. public void setSlowAccess(boolean slowAccess) {
  904. this.slowAccess = slowAccess;
  905. if (slowAccess) {
  906. }
  907. }
  908. /**
  909. * Initialize plugins. This method should always be called when a new index is open.
  910. *
  911. */
  912. public void initPlugins() {
  913. Object pluginsTabs = find("pluginsTabs");
  914. removeAll(pluginsTabs);
  915. for (int i = 0; i < plugins.size(); i++) {
  916. LukePlugin plugin = (LukePlugin) plugins.get(i);
  917. addPluginTab(pluginsTabs, plugin);
  918. plugin.setDirectory(dir);
  919. plugin.setIndexReader(ir);
  920. try {
  921. plugin.init();
  922. } catch (Exception e) {
  923. e.printStackTrace();
  924. showStatus("PLUGIN ERROR: " + e.getMessage());
  925. }
  926. }
  927. }
  928. /**
  929. * Initialize index overview and other GUI elements. This method is called always
  930. * when a new index is open.
  931. *
  932. */
  933. private void initOverview() {
  934. try {
  935. courier = new Font("Courier", getFont().getStyle(), getFont().getSize());
  936. lastST = find("lastST");
  937. setBoolean(find("bReload"), "enabled", true);
  938. setBoolean(find("bClose"), "enabled", true);
  939. setBoolean(find("bCommit"), "enabled", true);
  940. Object cbType = find("cbType");
  941. populateAnalyzers(cbType);
  942. Object pOver = find("pOver");
  943. Object iName = find("idx");
  944. String idxName;
  945. if (pName.length() > 40) {
  946. idxName = pName.substring(0, 10) + "..." + pName.substring(pName.length() - 27);
  947. } else {
  948. idxName = pName;
  949. }
  950. setString(iName, "text", idxName + (readOnly ? " (R)" : ""));
  951. iName = find(pOver, "iName");
  952. setString(iName, "text", pName + (readOnly ? " (Read-Only)" : ""));
  953. Object dirImpl = find("dirImpl");
  954. String implName = "N/A";
  955. if (dir == null) {
  956. if (ir != null) {
  957. implName = "N/A (reader is " + ir.getClass().getName() + ")";
  958. }
  959. } else {
  960. implName = dir.getClass().getName();
  961. }
  962. setString(dirImpl, "text", implName);
  963. Object fileSize = find("iFileSize");
  964. long totalFileSize = Util.calcTotalFileSize(pName, dir);
  965. setString(fileSize, "text", Util.normalizeSize(totalFileSize) + Util.normalizeUnit(totalFileSize));
  966. if (ir == null) {
  967. return;
  968. }
  969. // we need IndexReader from now on
  970. Object iMod = find(pOver, "iMod");
  971. String modText = "N/A";
  972. if (dir != null) {
  973. modText = new Date(IndexReader.lastModified(dir)).toString();
  974. }
  975. setString(iMod, "text", modText);
  976. Object iDocs = find(pOver, "iDocs");
  977. String numdocs = String.valueOf(ir.numDocs());
  978. setString(iDocs, "text", numdocs);
  979. iDocs = find("iDocs1");
  980. setString(iDocs, "text", String.valueOf(ir.maxDoc() - 1));
  981. Object iFields = find(pOver, "iFields");
  982. fn = ir.getFieldNames(IndexReader.FieldOption.ALL);
  983. if (fn.size() == 0) {
  984. showStatus("Empty index.");
  985. }
  986. showFiles(dir, null);
  987. showCommits();
  988. final Object fList = find(pOver, "fList");
  989. final Object defFld = find("defFld");
  990. final Object fCombo = find("fCombo");
  991. TreeSet<String> fields = new TreeSet<String>(fn);
  992. idxFields = (String[])fields.toArray(new String[fields.size()]);
  993. setString(iFields, "text", String.valueOf(idxFields.length));
  994. final Object iTerms = find(pOver, "iTerms");
  995. if (!slowAccess) {
  996. Thread t = new Thread() {
  997. public void run() {
  998. Object r = create("row");
  999. Object cell = create("cell");
  1000. add(r, cell);
  1001. add(fList, r);
  1002. setBoolean(cell, "enabled", false);
  1003. setString(cell, "text", "..wait..");
  1004. termCounts.clear();
  1005. FieldTermCount ftc = null;
  1006. try {
  1007. TermEnum te = ir.terms();
  1008. numTerms = 0;
  1009. while (te.next()) {
  1010. Term currTerm = te.term();
  1011. if (ftc == null) {
  1012. // initialize
  1013. ftc = new FieldTermCount();
  1014. ftc.fieldname = currTerm.field();
  1015. termCounts.put(ftc.fieldname, ftc);
  1016. }
  1017. if (ftc.fieldname == currTerm.field()) {
  1018. ftc.termCount++;
  1019. } else {
  1020. ftc = new FieldTermCount();
  1021. ftc.fieldname = currTerm.field();
  1022. ftc.termCount++;
  1023. termCounts.put(ftc.fieldname, ftc);
  1024. }
  1025. numTerms++;
  1026. }
  1027. te.close();
  1028. setString(iTerms, "text", String.valueOf(numTerms));
  1029. initFieldList(fList, fCombo, defFld);
  1030. } catch (Exception e) {
  1031. showStatus("ERROR: can't count terms per field");
  1032. }
  1033. }
  1034. };
  1035. t.start();
  1036. } else {
  1037. setString(iTerms, "text", "N/A");
  1038. initFieldList(fList, fCombo, defFld);
  1039. }
  1040. Object iDel = find(pOver, "iDelOpt");
  1041. String sDel = ir.hasDeletions() ? "Yes (" + ir.numDeletedDocs() + ")" : "No";
  1042. String sDelOpt = sDel + " / " +
  1043. (ir.isOptimized() ? "Yes" : "No");
  1044. setString(iDel, "text", sDelOpt);
  1045. Object iVer = find(pOver, "iVer");
  1046. String verText = "N/A";
  1047. if (dir != null) {
  1048. verText = Long.toHexString(IndexReader.getCurrentVersion(dir));
  1049. }
  1050. setString(iVer, "text", verText);
  1051. Object iFormat = find(pOver, "iFormat");
  1052. Object iCaps = find(pOver, "iCaps");
  1053. String formatText = "N/A";
  1054. String formatCaps = "N/A";
  1055. if (dir != null) {
  1056. int format = IndexGate.getIndexFormat(dir);
  1057. IndexGate.FormatDetails formatDetails = IndexGate.getFormatDetails(format);
  1058. formatText = format + " (" + formatDetails.genericName + ")";
  1059. formatCaps = formatDetails.capabilities;
  1060. }
  1061. setString(iFormat, "text", formatText);
  1062. setString(iCaps, "text", formatCaps);
  1063. Object iTiiDiv = find(pOver, "iTiiDiv");
  1064. String divText = "N/A";
  1065. // not available in Lucene 3.0
  1066. // try {
  1067. // divText = String.valueOf(ir.getTermInfosIndexDivisor());
  1068. // } catch (UnsupportedOperationException uoe) {
  1069. // }
  1070. setString(iTiiDiv, "text", divText);
  1071. Object iCommit = find(pOver, "iCommit");
  1072. String commitText = "N/A";
  1073. try {
  1074. IndexCommit commit = ir.getIndexCommit();
  1075. commitText = commit.getSegmentsFileName() + " (" +
  1076. new Date(commit.getTimestamp()).toString() + ")";
  1077. } catch (UnsupportedOperationException uoe) {
  1078. }
  1079. setString(iCommit, "text", commitText);
  1080. Object iUser = find(pOver, "iUser");
  1081. String userData = null;
  1082. try {
  1083. Map userDataMap = ir.getCommitUserData();
  1084. if (userDataMap != null && !userDataMap.isEmpty()) {
  1085. userData = ir.getCommitUserData().toString();
  1086. } else {
  1087. userData = "--";
  1088. }
  1089. } catch (UnsupportedOperationException uoe) {
  1090. userData = "(not supported)";
  1091. }
  1092. setString(iUser, "text", userData);
  1093. final Object nTerms = find("nTerms");
  1094. if (!slowAccess) {
  1095. Thread t = new Thread() {
  1096. public void run() {
  1097. actionTopTerms(nTerms);
  1098. }
  1099. };
  1100. t.start();
  1101. }
  1102. } catch (Exception e) {
  1103. e.printStackTrace();
  1104. errorMsg(e.getMessage());
  1105. }
  1106. }
  1107. private void initFieldList(Object fList, Object fCombo, Object defFld) {
  1108. removeAll(fList);
  1109. removeAll(fCombo);
  1110. removeAll(defFld);
  1111. setString(fCombo, "text", idxFields[0]);
  1112. setString(defFld, "text", idxFields[0]);
  1113. NumberFormat intCountFormat = NumberFormat.getIntegerInstance();
  1114. NumberFormat percentFormat = NumberFormat.getNumberInstance();
  1115. intCountFormat.setGroupingUsed(true);
  1116. percentFormat.setMaximumFractionDigits(2);
  1117. // sort by names now
  1118. for (String s : idxFields) {
  1119. Object row = create("row");
  1120. putProperty(row, "fName", s);
  1121. add(fList, row);
  1122. Object cell = create("cell");
  1123. setString(cell, "text", s);
  1124. add(row, cell);
  1125. cell = create("cell");
  1126. FieldTermCount ftc = termCounts.get(s);
  1127. if (ftc != null) {
  1128. long cnt = ftc.termCount;
  1129. setString(cell, "text", intCountFormat.format(cnt));
  1130. setChoice(cell, "alignment", "right");
  1131. add(row, cell);
  1132. float pcent = (float)(cnt * 100) / (float)numTerms;
  1133. cell = create("cell");
  1134. setString(cell, "text", percentFormat.format(pcent) + " %");
  1135. setChoice(cell, "alignment", "right");
  1136. add(row, cell);
  1137. } else {
  1138. setString(cell, "text", "0");
  1139. setChoice(cell, "alignment", "right");
  1140. add(row, cell);
  1141. cell = create("cell");
  1142. setString(cell, "text", "0.00 %");
  1143. setChoice(cell, "alignment", "right");
  1144. add(row, cell);
  1145. }
  1146. cell = create("cell");
  1147. setChoice(cell, "alignment", "right");
  1148. Decoder dec = decoders.get(s);
  1149. if (dec == null) dec = defDecoder;
  1150. setString(cell, "text", dec.toString());
  1151. add(row, cell);
  1152. // populate combos
  1153. Object choice = create("choice");
  1154. add(fCombo, choice);
  1155. setString(choice, "text", s);
  1156. putProperty(choice, "fName", s);
  1157. choice = create("choice");
  1158. add(defFld, choice);
  1159. setString(choice, "text", s);
  1160. putProperty(choice, "fName", s);
  1161. }
  1162. setString(find("defFld"), "text", idxFields[0]);
  1163. // Remove columns
  1164. Object header = get(find("sTable"), "header");
  1165. removeAll(header);
  1166. Object c = create("column");
  1167. setString(c, "text", "#");
  1168. setInteger(c, "width", 40);
  1169. add(header, c);
  1170. c = create("column");
  1171. setString(c, "text", "Score");
  1172. setInteger(c, "width", 50);
  1173. add(header, c);
  1174. c = create("column");
  1175. setString(c, "text", "Doc. Id");
  1176. setInteger(c, "width", 60);
  1177. add(header, c);
  1178. for (int j = 0; j < idxFields.length; j++) {
  1179. c = create("column");
  1180. setString(c, "text", idxFields[j]);
  1181. add(header, c);
  1182. }
  1183. }
  1184. private void showCommits() throws Exception {
  1185. Object commitsTable = find("commitsTable");
  1186. removeAll(commitsTable);
  1187. if (dir == null) {
  1188. Object row = create("row");
  1189. Object cell = create("cell");
  1190. setString(cell, "text", "<not available>");
  1191. setBoolean(cell, "enabled", false);
  1192. add(row, cell);
  1193. add(commitsTable, row);
  1194. return;
  1195. }
  1196. Collection commits = IndexReader.listCommits(dir);
  1197. // commits are ordered from oldest to newest ?
  1198. Iterator it = commits.iterator();
  1199. int rowNum = 0;
  1200. while (it.hasNext()) {
  1201. IndexCommit commit = (IndexCommit)it.next();
  1202. // figure out the name of the segment files
  1203. Collection files = commit.getFileNames();
  1204. Iterator itf = files.iterator();
  1205. Object row = create("row");
  1206. boolean enabled = rowNum < commits.size() - 1;
  1207. Color color = null;
  1208. rowNum++;
  1209. add(commitsTable, row);
  1210. putProperty(row, "commit", commit);
  1211. if (enabled) {
  1212. putProperty(row, "commitDeletable", Boolean.TRUE);
  1213. }
  1214. Object cell = create("cell");
  1215. setString(cell, "text", String.valueOf(commit.getGeneration()));
  1216. add(row, cell);
  1217. cell = create("cell");
  1218. char[] flags = new char[]{'-', '-'};
  1219. if (commit.isDeleted()) flags[0] = 'D';
  1220. if (commit.isOptimized()) flags[1] = 'O';
  1221. setString(cell, "text", new String(flags));
  1222. setFont(cell, "font", courier);
  1223. setChoice(cell, "alignment", "center");
  1224. add(row, cell);
  1225. cell = create("cell");
  1226. setString(cell, "text", Long.toHexString(commit.getVersion()));
  1227. add(row, cell);
  1228. cell = create("cell");
  1229. setString(cell, "text", new Date(commit.getTimestamp()).toString());
  1230. add(row, cell);
  1231. cell = create("cell");
  1232. Map userData = commit.getUserData();
  1233. if (userData != null && !userData.isEmpty()) {
  1234. setString(cell, "text", userData.toString());
  1235. } else {
  1236. setString(cell, "text", "--");
  1237. }
  1238. add(row, cell);
  1239. }
  1240. }
  1241. public void showCommitFiles(Object commitTable) throws Exception {
  1242. List commits = new ArrayList();
  1243. Object[] rows = getSelectedItems(commitTable);
  1244. if (rows == null || rows.length == 0) {
  1245. showFiles(dir, commits);
  1246. return;
  1247. }
  1248. for (int i = 0; i < rows.length; i++) {
  1249. IndexCommit commit = (IndexCommit)getProperty(rows[i], "commit");
  1250. if (commit != null) {
  1251. commits.add(commit);
  1252. }
  1253. }
  1254. showFiles(dir, commits);
  1255. }
  1256. private void showFiles(Directory dir, List commits) throws Exception {
  1257. Object filesTable = find("filesTable");
  1258. if (dir == null) {
  1259. removeAll(filesTable);
  1260. Object row = create("row");
  1261. Object cell = create("cell");
  1262. setString(cell, "text", "<not available>");
  1263. setBoolean(cell, "enabled", false);
  1264. add(row, cell);
  1265. add(filesTable, row);
  1266. return;
  1267. }
  1268. String[] physFiles = dir.listAll();
  1269. List<String> files = new ArrayList();
  1270. if (commits != null && commits.size() > 0) {
  1271. for (int i = 0; i < commits.size(); i++) {
  1272. IndexCommit commit = (IndexCommit)commits.get(i);
  1273. files.addAll(commit.getFileNames());
  1274. }
  1275. } else {
  1276. files.addAll(Arrays.asList(physFiles));
  1277. }
  1278. Collections.sort(files);
  1279. List segs = getIndexFileNames(dir);
  1280. List dels = getIndexDeletableNames(dir);
  1281. removeAll(filesTable);
  1282. for (int i = 0; i < files.size(); i++) {
  1283. String fileName = files.get(i);
  1284. String pathName;
  1285. if (pName.endsWith(File.separator)) {
  1286. pathName = pName;
  1287. } else {
  1288. pathName = pName + File.separator;
  1289. }
  1290. File file = new File(pathName + fileName);
  1291. Object row = create("row");
  1292. Object nameCell = create("cell");
  1293. setString(nameCell, "text", fileName);
  1294. add(row, nameCell);
  1295. Object sizeCell = create("cell");
  1296. setString(sizeCell, "text", Util.normalizeSize(file.length()));
  1297. setChoice(sizeCell, "alignment", "right");
  1298. add(row, sizeCell);
  1299. Object unitCell = create("cell");
  1300. setString(unitCell, "text", Util.normalizeUnit(file.length()));
  1301. add(row, unitCell);
  1302. boolean deletable = dels.contains(fileName.intern());
  1303. String inuse = getFileFunction(fileName);
  1304. Object delCell = create("cell");
  1305. setString(delCell, "text", deletable ? "YES" : "-");
  1306. add(row, delCell);
  1307. Object inuseCell = create("cell");
  1308. setString(inuseCell, "text", inuse);
  1309. add(row, inuseCell);
  1310. add(filesTable, row);
  1311. }
  1312. }
  1313. private String getFileFunction(String file) {
  1314. String res = IndexGate.getFileFunction(file);
  1315. if (res == null) {
  1316. res = "YES";
  1317. }
  1318. return res;
  1319. }
  1320. private void syncMRU(Object path) {
  1321. removeAll(path);
  1322. for (Iterator iter = Prefs.getMruList().iterator(); iter.hasNext();) {
  1323. String element = (String) iter.next();
  1324. Object choice = create("choice");
  1325. setString(choice, "text", element);
  1326. add(path, choice);
  1327. }
  1328. }
  1329. /**
  1330. * Update the list of top terms.
  1331. * @param nTerms Thinlet widget containing the number of top terms to show
  1332. */
  1333. public void actionTopTerms(Object nTerms) {
  1334. if (ir == null) {
  1335. showStatus(MSG_NOINDEX);
  1336. return;
  1337. }
  1338. String sndoc = getString(nTerms, "text");
  1339. int nd = 50;
  1340. try {
  1341. nd = Integer.parseInt(sndoc);
  1342. } catch (Exception e) {}
  1343. final int ndoc = nd;
  1344. Object[] fields = getSelectedItems(find("fList"));
  1345. String[] flds = null;
  1346. if (fields == null || fields.length == 0) {
  1347. flds = idxFields;
  1348. } else {
  1349. flds = new String[fields.length];
  1350. for (int i = 0; i < fields.length; i++) {
  1351. flds[i] = (String) getProperty(fields[i], "fName");
  1352. }
  1353. }
  1354. final String[] fflds = flds;
  1355. SlowThread st = new SlowThread(this) {
  1356. public void execute() {
  1357. try {
  1358. TermInfo[] tis = HighFreqTerms.getHighFreqTerms(ir, null, ndoc + 1, fflds);
  1359. Object table = find("tTable");
  1360. removeAll(table);
  1361. if (tis == null || tis.length == 0) {
  1362. Object row = create("row");
  1363. Object cell = create("cell");
  1364. add(row, cell);
  1365. cell = create("cell");
  1366. add(row, cell);
  1367. cell = create("cell");
  1368. add(row, cell);
  1369. cell = create("cell");
  1370. setBoolean(cell, "enabled", false);
  1371. setString(cell, "text", "No Results");
  1372. add(row, cell);
  1373. add(table, row);
  1374. return;
  1375. }
  1376. for (int i = 0; i < tis.length; i++) {
  1377. Object row = create("row");
  1378. add(table, row);
  1379. putProperty(row, "term", tis[i].term);
  1380. putProperty(row, "ti", tis[i]);
  1381. Object cell = create("cell");
  1382. setChoice(cell, "alignment", "right");
  1383. setString(cell, "text", String.valueOf(i + 1));
  1384. add(row, cell);
  1385. cell = create("cell");
  1386. setChoice(cell, "alignment", "right");
  1387. setString(cell, "text", String.valueOf(tis[i].docFreq) + " ");
  1388. add(row, cell);
  1389. cell = create("cell");
  1390. setString(cell, "text", tis[i].term.field());
  1391. add(row, cell);
  1392. cell = create("cell");
  1393. Decoder dec = decoders.get(tis[i].term.field());
  1394. if (dec == null) dec = defDecoder;
  1395. String s;
  1396. try {
  1397. s = dec.decodeTerm(tis[i].term.field(), tis[i].term.text());
  1398. } catch (Throwable e) {
  1399. s = tis[i].term.text();
  1400. setColor(cell, "foreground", Color.RED);
  1401. }
  1402. setString(cell, "text", " " + s);
  1403. add(row, cell);
  1404. }
  1405. } catch (Exception e) {
  1406. e.printStackTrace();
  1407. errorMsg(e.getMessage());
  1408. }
  1409. }
  1410. };
  1411. if (slowAccess) {
  1412. st.start();
  1413. } else {
  1414. st.execute();
  1415. }
  1416. }
  1417. public void clipTopTerms(Object tTable) {
  1418. Object[] rows = getItems(tTable);
  1419. StringBuffer sb = new StringBuffer();
  1420. for (int i = 0; i < rows.length; i++) {
  1421. TermInfo ti = (TermInfo)getProperty(rows[i], "ti");
  1422. if (ti == null) continue;
  1423. sb.append(ti.docFreq + "\t" + ti.term.field() + "\t" + ti.term.text() + "\n");
  1424. }
  1425. StringSelection sel = new StringSelection(sb.toString());
  1426. Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, this);
  1427. }
  1428. /**
  1429. * Switch to a view that shows all documents containing selected term.
  1430. * @param tTable Thinlet table widget, where selected row contains a property named "term",
  1431. * which is the selected {@link Term} instance
  1432. */
  1433. public void browseTermDocs(Object tTable) {
  1434. Object row = getSelectedItem(tTable);
  1435. if (row == null) return;
  1436. Term t = (Term) getProperty(row, "term");
  1437. if (t == null) return;
  1438. Object tabpane = find("maintpane");
  1439. setInteger(tabpane, "selected", 1);
  1440. _showTerm(find("fCombo"), find("fText"), t);
  1441. repaint();
  1442. }
  1443. public void showTermDocs(Object tTable) {
  1444. Object row = getSelectedItem(tTable);
  1445. if (row == null) return;
  1446. Term t = (Term) getProperty(row, "term");
  1447. if (t == null) return;
  1448. Object tabpane = find("maintpane");
  1449. setInteger(tabpane, "selected", 2);
  1450. Object qField = find("qField");
  1451. setString(qField, "text", t.field() + ":" + t.text());
  1452. search(qField);
  1453. repaint();
  1454. }
  1455. /**
  1456. * Undelete all deleted documents in the current index. This method also
  1457. * updates the overview.
  1458. */
  1459. public void actionUndelete() {
  1460. if (ir == null) {
  1461. showStatus(MSG_NOINDEX);
  1462. return;
  1463. }
  1464. if (readOnly) {
  1465. showStatus(MSG_READONLY);
  1466. return;
  1467. }
  1468. try {
  1469. ir.undeleteAll();
  1470. initOverview();
  1471. } catch (Exception e) {
  1472. e.printStackTrace();
  1473. errorMsg(e.getMessage());
  1474. }
  1475. }
  1476. /** Not implemented yet... */
  1477. public void actionConvert(Object method) {
  1478. }
  1479. public List<String> getIndexDeletableNames(Directory d) {
  1480. if (d == null) return null;
  1481. List<String> deletable = null;
  1482. try {
  1483. deletable = IndexGate.getDeletableFiles(d);
  1484. } catch (Exception e) {
  1485. e.printStackTrace();
  1486. }
  1487. //for (int i = 0; i < deletable.size(); i++) {
  1488. // System.out.println(" -del " + deletable.get(i));
  1489. //}
  1490. if (deletable == null) deletable = Collections.EMPTY_LIST;
  1491. return deletable;
  1492. }
  1493. public Directory getDirectory() {
  1494. return dir;
  1495. }
  1496. public IndexReader getIndexReader() {
  1497. return ir;
  1498. }
  1499. public void setIndexReader(IndexReader reader, String indexName) {
  1500. if (reader == null) {
  1501. return;
  1502. }
  1503. try {
  1504. if (is != null) {
  1505. is.close();
  1506. is = null;
  1507. }
  1508. if (ir != null) {
  1509. ir.close();
  1510. ir = null;
  1511. }
  1512. if (dir != null) {
  1513. dir.close();
  1514. dir = null;
  1515. }
  1516. try {
  1517. dir = reader.directory();
  1518. } catch (UnsupportedOperationException uoe) {
  1519. dir = null;
  1520. }
  1521. ir = reader;
  1522. is = new IndexSearcher(ir);
  1523. pName = indexName;
  1524. initOverview();
  1525. initPlugins();
  1526. } catch (Exception e) {
  1527. e.printStackTrace();
  1528. errorMsg("Setting new IndexReader failed: " + e.toString());
  1529. }
  1530. }
  1531. public List<String> getIndexFileNames(Directory d) {
  1532. if (d == null) return null;
  1533. List<String> names = null;
  1534. try {
  1535. names = IndexGate.getIndexFiles(d);
  1536. } catch (Exception e) {
  1537. e.printStackTrace();
  1538. }
  1539. //for (int i = 0; i < names.size(); i++) {
  1540. // System.out.println(" -seg " + names.get(i));
  1541. //}
  1542. return names;
  1543. }
  1544. public void actionCheckIndex() {
  1545. if (dir == null) {
  1546. errorMsg("No directory - open index directory first (you may use the 'no IndexReader' option).");
  1547. return;
  1548. }
  1549. Object dialog = addComponent(null, "/xml/checkindex.xml", null, null);
  1550. Object dirName = find(dialog, "dirName");
  1551. setString(dirName, "text", pName);
  1552. add(dialog);
  1553. }
  1554. public void checkIndex(final Object dialog) {
  1555. Thread t = new Thread() {
  1556. public void run() {
  1557. Object panel = find(dialog, "msg");
  1558. Object fixPanel = find(dialog, "fixPanel");
  1559. PanelPrintWriter ppw = new PanelPrintWriter(Luke.this, panel);
  1560. Object ckRes = find(dialog, "ckRes");
  1561. CheckIndex.Status status = null;
  1562. CheckIndex ci = new CheckIndex(dir);
  1563. ci.setInfoStream(ppw);
  1564. putProperty(dialog, "checkIndex", ci);
  1565. putProperty(dialog, "ppw", ppw);
  1566. try {
  1567. status = ci.checkIndex();
  1568. } catch (Exception e) {
  1569. ppw.println("ERROR: caught exception, giving up.\n\n");
  1570. e.printStackTrace();
  1571. e.printStackTrace(ppw);
  1572. }
  1573. if (status != null) {
  1574. Luke.this.putProperty(dialog, "checkStatus", status);
  1575. String statMsg;
  1576. if (status.clean) {
  1577. statMsg = "OK";
  1578. } else if (status.toolOutOfDate) {
  1579. statMsg = "ERROR: Can't check - tool out-of-date";
  1580. } else {
  1581. // show fixPanel
  1582. setBoolean(fixPanel, "visible", true);
  1583. repaint(dialog);
  1584. statMsg = "BAD: ";
  1585. if (status.cantOpenSegments) {
  1586. statMsg += "cantOpenSegments ";
  1587. }
  1588. if (status.missingSegments) {
  1589. statMsg += "missingSegments ";
  1590. }
  1591. if (status.missingSegmentVersion) {
  1592. statMsg += "missingSegVersion ";
  1593. }
  1594. if (status.numBadSegments > 0) {
  1595. statMsg += "numBadSegments=" + status.numBadSegments + " ";
  1596. }
  1597. if (status.totLoseDocCount > 0) {
  1598. statMsg += "lostDocCount=" + status.totLoseDocCount + " ";
  1599. }
  1600. }
  1601. setString(ckRes, "text", statMsg);
  1602. }
  1603. }
  1604. };
  1605. t.start();
  1606. }
  1607. public void fixIndex(final Object dialog) {
  1608. Thread t = new Thread() {
  1609. public void run(){
  1610. CheckIndex ci = (CheckIndex)getProperty(dialog, "checkIndex");
  1611. if (ci == null) {
  1612. errorMsg("You need to run 'Check Index' first.");
  1613. return;
  1614. }
  1615. CheckIndex.Status status = (CheckIndex.Status)getProperty(dialog, "checkStatus");
  1616. if (status == null) {
  1617. errorMsg("You need to run 'Check Index' first.");
  1618. return;
  1619. }
  1620. Object fixRes = find(dialog, "fixRes");
  1621. PanelPrintWriter ppw = (PanelPrintWriter)getProperty(dialog, "ppw");
  1622. try {
  1623. ci.fixIndex(status);
  1624. setString(fixRes, "text", "DONE. Review the output above.");
  1625. } catch (Exception e) {
  1626. ppw.println("\nERROR during Fix Index:");
  1627. e.printStackTrace(ppw);
  1628. setString(fixRes, "text", "FAILED. Review the output above.");
  1629. }
  1630. }
  1631. };
  1632. t.start();
  1633. }
  1634. public boolean isFSBased(Directory dir) {
  1635. if (dir == null) {
  1636. return false;
  1637. }
  1638. if (dir instanceof MMapDirectory ||
  1639. dir instanceof NIOFSDirectory ||
  1640. dir instanceof FSDirectory) {
  1641. return true;
  1642. }
  1643. return false;
  1644. }
  1645. /**
  1646. * This method will cleanup the current Directory of any content
  1647. * that is not the part of the index.
  1648. */
  1649. public void actionCleanup() {
  1650. if (dir == null) {
  1651. showStatus(MSG_NOINDEX);
  1652. return;
  1653. }
  1654. try {
  1655. List allFiles;
  1656. boolean phys = false;
  1657. if (isFSBased(dir)) {
  1658. File phyDir = new File(pName);
  1659. phys = true;
  1660. allFiles = new ArrayList(Arrays.asList(phyDir.list()));
  1661. } else {
  1662. allFiles = new ArrayList(Arrays.asList(dir.listAll()));
  1663. }
  1664. List indexFiles = getIndexFileNames(dir);
  1665. allFiles.removeAll(indexFiles);
  1666. if (allFiles.size() == 0) {
  1667. infoMsg("There are no files to be cleaned - target directory contains only index-related files.");
  1668. return;
  1669. }
  1670. Object dialog = addComponent(null, "/xml/cleanup.xml", null, null);
  1671. Object filesTable = find(dialog, "filesTable");
  1672. for (int i = 0; i < allFiles.size(); i++) {
  1673. String fileName = (String)allFiles.get(i);
  1674. Object row = create("row");
  1675. add(filesTable, row);
  1676. putProperty(row, "fileName", fileName);
  1677. long size = dir.fileLength(fileName);
  1678. Object cell;
  1679. cell = create("cell");
  1680. setString(cell, "text", Util.normalizeSize(size));
  1681. add(row, cell);
  1682. cell = create("cell");
  1683. setString(cell, "text", Util.normalizeUnit(size));
  1684. add(row, cell);
  1685. cell = create("cell");
  1686. setString(cell, "text", fileName);
  1687. add(row, cell);
  1688. }
  1689. add(dialog);
  1690. } catch (Exception e) {
  1691. errorMsg("Error: " + e.toString());
  1692. }
  1693. }
  1694. public void toggleKeep(Object filesTable) {
  1695. Object[] rows = getSelectedItems(filesTable);
  1696. if (rows == null || rows.length == 0) return;
  1697. for (int i = 0; i < rows.length; i++) {
  1698. Boolean Deletable = (Boolean)getProperty(rows[i], "deletable");
  1699. boolean deletable = Deletable != null ? Deletable.booleanValue() : true;
  1700. deletable = !deletable;
  1701. putProperty(rows[i], "deletable", Boolean.valueOf(deletable));
  1702. Object[] cells = getItems(rows[i]);
  1703. for (int k = 0; k < cells.length; k++) {
  1704. if (!deletable) {
  1705. setBoolean(cells[k], "enabled", false);
  1706. } else {
  1707. setBoolean(cells[k], "enabled", true);
  1708. }
  1709. }
  1710. }
  1711. repaint(filesTable);
  1712. }
  1713. public void _actionCleanup(Object filesTable) {
  1714. try {
  1715. ir.close();
  1716. } catch (Exception e) {
  1717. e.printStackTrace();
  1718. }
  1719. ArrayList noDel = new ArrayList();
  1720. String errMsg = null;
  1721. boolean phys = isFSBased(dir);
  1722. int deleted = 0;
  1723. try {
  1724. Object[] rows = getItems(filesTable);
  1725. for (int i = 0; i < rows.length; i++) {
  1726. String name = (String)getProperty(rows[i], "fileName");
  1727. Boolean Deletable = (Boolean)getProperty(rows[i], "deletable");
  1728. boolean deletable = Deletable != null ? Deletable.booleanValue() : true;
  1729. if (!deletable) {
  1730. continue;
  1731. }
  1732. if (phys) {
  1733. File f = new File(pName, name);
  1734. if (!removeFile(f)) {
  1735. noDel.add(name);
  1736. }
  1737. deleted++;
  1738. continue;
  1739. } else {
  1740. dir.deleteFile(name);
  1741. deleted++;
  1742. }
  1743. }
  1744. if (noDel.size() > 0) {
  1745. StringBuffer msg = new StringBuffer("Some files could not be deleted:");
  1746. for (int i = 0; i < noDel.size(); i++) msg.append("\n" + noDel.get(i));
  1747. errMsg = msg.toString();
  1748. }
  1749. } catch (Exception e) {
  1750. e.printStackTrace();
  1751. errMsg = "FAILED: " + e.getMessage();
  1752. } finally {
  1753. try {
  1754. actionReopen();
  1755. } catch (Exception e) {
  1756. e.printStackTrace();
  1757. errMsg = "FAILED: " + e.getMessage();
  1758. }
  1759. }
  1760. if (errMsg != null) {
  1761. errorMsg(errMsg);
  1762. } else if (deleted == 0) {
  1763. infoMsg("No files were deleted.");
  1764. }
  1765. }
  1766. /** Recursively remove files and directories including the indicated
  1767. * root file.
  1768. * @param f root file name
  1769. * @return true if successful, false otherwise. Note that if the result
  1770. * is false the tree may have been partially removed.
  1771. */
  1772. public boolean removeFile(File f) {
  1773. System.out.println("remove " + f);
  1774. if (!f.isDirectory()) return f.delete();
  1775. File[] files = f.listFiles();
  1776. boolean res = true;
  1777. if (files != null) {
  1778. for (int i = 0; i < files.length; i++) {
  1779. res = res && removeFile(files[i]);
  1780. }
  1781. }
  1782. res = res && f.delete();
  1783. return res;
  1784. }
  1785. public void actionExport() {
  1786. if (ir == null) {
  1787. showStatus(MSG_NOINDEX);
  1788. return;
  1789. }
  1790. Object dialog = addComponent(this, "/xml/export.xml", null, null);
  1791. }
  1792. public void export(final Object dialog) {
  1793. Object ckOver = find(dialog, "ckOver");
  1794. Object ckGzip = find(dialog, "ckGzip");
  1795. Object path = find(dialog, "path");
  1796. Object ckRanges = find(dialog, "ckRanges");
  1797. Object list = find(dialog, "ranges");
  1798. String fileName = getString(path, "text");
  1799. fileName = fileName.trim();
  1800. if (fileName.length() == 0) {
  1801. errorMsg("No output file set.");
  1802. return;
  1803. }
  1804. boolean over = getBoolean(ckOver, "selected");
  1805. boolean gzip = getBoolean(ckGzip, "selected");
  1806. if (gzip && !fileName.endsWith(".gz")) {
  1807. fileName = fileName + ".gz";
  1808. setString(path, "text", fileName);
  1809. }
  1810. File out = new File(fileName);
  1811. if (out.exists()) {
  1812. if (out.isDirectory()) {
  1813. errorMsg("Output already exists and is a directory.");
  1814. return;
  1815. }
  1816. if (!over) {
  1817. errorMsg("Output already exists.");
  1818. return;
  1819. }
  1820. }
  1821. Ranges ranges = null;
  1822. if (getBoolean(ckRanges, "selected")) {
  1823. String rs = getString(list, "text");
  1824. if (rs.trim().length() > 0) {
  1825. try {
  1826. ranges = Ranges.parse(rs);
  1827. } catch (Exception e) {
  1828. errorMsg(e.toString());
  1829. return;
  1830. }
  1831. }
  1832. }
  1833. final Object progressBar = find(dialog, "bar");
  1834. final Object counter = find(dialog, "counter");
  1835. final Object msg = find(dialog, "msg");
  1836. Observer obs = new Observer() {
  1837. public void update(Observable o, Object arg) {
  1838. ProgressNotification pn = (ProgressNotification)arg;
  1839. setInteger(progressBar, "minimum", pn.minValue);
  1840. setInteger(progressBar, "maximum", pn.maxValue);
  1841. setInteger(progressBar, "value", pn.curValue);
  1842. setString(msg, "text", pn.message);
  1843. if (!pn.aborted) {
  1844. setString(counter, "text", pn.curValue + " of " + pn.maxValue + " done.");
  1845. } else {
  1846. setString(counter, "text", "ABORTED at " + pn.curValue + " of " + pn.maxValue);
  1847. }
  1848. }
  1849. };
  1850. // toggle buttons
  1851. setBoolean(find(dialog, "startButton"), "visible", false);
  1852. setBoolean(find(dialog, "abortButton"), "visible", true);
  1853. setBoolean(find(dialog, "closeButton"), "enabled", false);
  1854. _runExport(out, gzip, obs, dialog, ranges);
  1855. }
  1856. XMLExporter exporter = null;
  1857. public void _runExport(final File out, final boolean gzip, Observer obs,
  1858. final Object dialog, final Ranges ranges) {
  1859. exporter = new XMLExporter(ir, pName);
  1860. exporter.addObserver(obs);
  1861. Thread t = new Thread() {
  1862. public void run() {
  1863. OutputStream os = null;
  1864. try {
  1865. os = new FileOutputStream(out);
  1866. if (gzip) {
  1867. os = new GZIPOutputStream(os);
  1868. }
  1869. exporter.export(os, true, true, "index", ranges);
  1870. exporter = null;
  1871. } catch (Exception e) {
  1872. e.printStackTrace();
  1873. errorMsg("ERROR occurred, file may be incomplete: " + e.toString());
  1874. } finally {
  1875. setBoolean(find(dialog, "startButton"), "visible", true);
  1876. setBoolean(find(dialog, "abortButton"), "visible", false);
  1877. setBoolean(find(dialog, "closeButton"), "enabled", true);
  1878. if (os != null) {
  1879. try {
  1880. os.flush();
  1881. os.close();
  1882. } catch (Exception e) {
  1883. errorMsg("ERROR closing output, file may be incomplete: " + e.toString());
  1884. }
  1885. }
  1886. }
  1887. }
  1888. };
  1889. t.start();
  1890. }
  1891. public void abortExport(Object dialog) {
  1892. if (exporter != null && exporter.isRunning()) {
  1893. exporter.abort();
  1894. }
  1895. }
  1896. /**
  1897. * Optimize the current index
  1898. * @param method Thinlet menuitem widget containing the choice of index format.
  1899. * If the widget name is "optCompound" then the index will be optimized into compound
  1900. * format; otherwise a plain multi-file format will be used.
  1901. * <p>NOTE: this method is usually invoked from the GUI, and it also re-initializes GUI
  1902. * and plugins.</p>
  1903. */
  1904. public void actionOptimize() {
  1905. if (dir == null) {
  1906. showStatus(MSG_NOINDEX);
  1907. return;
  1908. }
  1909. if (readOnly) {
  1910. showStatus(MSG_READONLY);
  1911. return;
  1912. }
  1913. Object dialog = addComponent(null, "/xml/optimize.xml", null, null);
  1914. setString(find(dialog, "dirName"), "text", pName);
  1915. add(dialog);
  1916. }
  1917. /**
  1918. * Optimize the index.
  1919. */
  1920. public void optimize(final Object dialog) {
  1921. Thread t = new Thread() {
  1922. public void run() {
  1923. IndexWriter iw = null;
  1924. Object optimizeButton = find(dialog, "optimizeButton");
  1925. setBoolean(optimizeButton, "enabled", false);
  1926. Object closeButton = find(dialog, "closeButton");
  1927. setBoolean(closeButton, "enabled", false);
  1928. Object msg = find(dialog, "msg");
  1929. Object stat = find(dialog, "stat");
  1930. setString(stat, "text", "Running ...");
  1931. PanelPrintWriter ppw = new PanelPrintWriter(Luke.this, msg);
  1932. boolean useCompound = getBoolean(find(dialog, "optCompound"), "selected");
  1933. boolean expunge = getBoolean(find(dialog, "optExpunge"), "selected");
  1934. Object tiiSpin = find(dialog, "tii");
  1935. Object segnumSpin = find(dialog, "segnum");
  1936. int tii = Integer.parseInt(getString(tiiSpin, "text"));
  1937. int segnum = Integer.parseInt(getString(segnumSpin, "text"));
  1938. try {
  1939. if (is != null) is.close();
  1940. if (ir != null) ir.close();
  1941. IndexDeletionPolicy policy;
  1942. if (keepCommits) {
  1943. policy = new KeepAllIndexDeletionPolicy();
  1944. } else {
  1945. policy = new KeepLastIndexDeletionPolicy();
  1946. }
  1947. iw = new IndexWriter(dir, new org.apache.lucene.analysis.WhitespaceAnalyzer(),
  1948. false, policy, MaxFieldLength.UNLIMITED);
  1949. iw.setUseCompoundFile(useCompound);
  1950. iw.setTermIndexInterval(tii);
  1951. iw.setInfoStream(ppw);
  1952. long startSize = Util.calcTotalFileSize(pName, dir);
  1953. long startTime = System.currentTimeMillis();
  1954. if (expunge) {
  1955. iw.expungeDeletes();
  1956. } else {
  1957. if (segnum > 1) {
  1958. iw.optimize(segnum);
  1959. } else {
  1960. iw.optimize();
  1961. }
  1962. }
  1963. long endTime = System.currentTimeMillis();
  1964. long endSize = Util.calcTotalFileSize(pName, dir);
  1965. long deltaSize = startSize - endSize;
  1966. String sign = deltaSize > 0 ? " Increased " : " Reduced ";
  1967. String sizeMsg = sign + Util.normalizeSize(Math.abs(deltaSize)) + Util.normalizeUnit(Math.abs(deltaSize));
  1968. String timeMsg = String.valueOf(endTime - startTime) + " ms";
  1969. showStatus(sizeMsg + " in " + timeMsg);
  1970. iw.close();
  1971. setString(stat, "text", "Finished OK.");
  1972. } catch (Exception e) {
  1973. e.printStackTrace(ppw);
  1974. setString(stat, "text", "ERROR - aborted.");
  1975. errorMsg("ERROR optimizing: " + e.toString());
  1976. if (iw != null) try {
  1977. iw.close();
  1978. } catch (Exception e1) {}
  1979. } finally {
  1980. setBoolean(closeButton, "enabled", true);
  1981. }
  1982. try {
  1983. actionReopen();
  1984. is = new IndexSearcher(ir);
  1985. // add dialog again
  1986. add(dialog);
  1987. } catch (Exception e) {
  1988. e.printStackTrace(ppw);
  1989. errorMsg("ERROR reopening after optimize:\n" + e.getMessage());
  1990. }
  1991. }
  1992. };
  1993. t.start();
  1994. }
  1995. public void showPrevDoc(Object docNum) {
  1996. _showDoc(docNum, -1);
  1997. }
  1998. public void showNextDoc(Object docNum) {
  1999. _showDoc(docNum, +1);
  2000. }
  2001. public void showDoc(Object docNum) {
  2002. _showDoc(docNum, 0);
  2003. }
  2004. Document doc = null;
  2005. int iNum;
  2006. private void _showDoc(Object docNum, int incr) {
  2007. if (ir == null) {
  2008. showStatus(MSG_NOINDEX);
  2009. return;
  2010. }
  2011. String num = getString(docNum, "text");
  2012. if (num.trim().equals("")) num = String.valueOf(-incr);
  2013. try {
  2014. iNum = Integer.parseInt(num);
  2015. iNum += incr;
  2016. if (iNum < 0 || iNum >= ir.maxDoc()) {
  2017. showStatus("Document number outside valid range.");
  2018. return;
  2019. }
  2020. setString(docNum, "text", String.valueOf(iNum));
  2021. if (!ir.isDeleted(iNum)) {
  2022. SlowThread st = new SlowThread(this) {
  2023. public void execute() {
  2024. try {
  2025. doc = ir.document(iNum);
  2026. _showDocFields(iNum, doc);
  2027. } catch (Exception e) {
  2028. e.printStackTrace();
  2029. showStatus(e.getMessage());
  2030. }
  2031. }
  2032. };
  2033. if (slowAccess) {
  2034. st.start();
  2035. } else {
  2036. st.execute();
  2037. }
  2038. } else {
  2039. showStatus("Deleted document - not available.");
  2040. _showDocFields(iNum, null);
  2041. }
  2042. } catch (Exception e) {
  2043. e.printStackTrace();
  2044. showStatus(e.getMessage());
  2045. }
  2046. }
  2047. public void actionAddDocument(Object docTable) {
  2048. if (ir == null) {
  2049. errorMsg(MSG_NOINDEX);
  2050. return;
  2051. }
  2052. Object dialog = addComponent(null, "/xml/editdoc.xml", null, null);
  2053. remove(find(dialog, "bDelAdd"));
  2054. Object cbAnalyzers = find(dialog, "cbAnalyzers");
  2055. populateAnalyzers(cbAnalyzers);
  2056. setInteger(cbAnalyzers, "selected", 0);
  2057. add(dialog);
  2058. }
  2059. public void actionReconstruct(Object docNumText) {
  2060. final int[] nums = new int[1];
  2061. try {
  2062. String numString = getString(docNumText, "text");
  2063. nums[0] = Integer.parseInt(numString);
  2064. } catch (Exception e) {
  2065. showStatus("ERROR: no valid document selected");
  2066. return;
  2067. }
  2068. final Progress progress = new Progress(this);
  2069. progress.setMessage("Reconstructing ...");
  2070. progress.show();
  2071. Thread thr = new Thread() {
  2072. public void run() {
  2073. try {
  2074. int docNum = nums[0];
  2075. DocReconstructor recon = new DocReconstructor(ir, idxFields, numTerms);
  2076. recon.addObserver(progress);
  2077. Reconstructed doc = recon.reconstruct(docNum);
  2078. Object dialog = addComponent(null, "/xml/editdoc.xml", null, null);
  2079. putProperty(dialog, "docNum", new Integer(docNum));
  2080. Object cbAnalyzers = find(dialog, "cbAnalyzers");
  2081. populateAnalyzers(cbAnalyzers);
  2082. setInteger(cbAnalyzers, "selected", 0);
  2083. Object editTabs = find(dialog, "editTabs");
  2084. setString(find(dialog, "docNum"), "text", "Fields of Doc #: " + docNum);
  2085. for (int p = 0; p < idxFields.length; p++) {
  2086. String key = idxFields[p];
  2087. if (!doc.hasField(key)) continue;
  2088. Field[] fields = doc.getStoredFields().get(key);
  2089. GrowableStringArray recField = doc.getReconstructedFields().get(key);
  2090. int count = 0;
  2091. if (recField != null) count = 1;
  2092. if (fields != null && fields.length > count) count = fields.length;
  2093. for (int i = 0; i < count; i++) {
  2094. if (i > 0) recField = null; // show it only for the first field
  2095. Object tab = create("tab");
  2096. setString(tab, "text", key);
  2097. setFont(tab, getFont().deriveFont(Font.BOLD));
  2098. add(editTabs, tab);
  2099. Object editfield = addComponent(tab, "/xml/editfield.xml", null, null);
  2100. Object fType = find(editfield, "fType");
  2101. Object sText = find(editfield, "sText");
  2102. Object rText = find(editfield, "rText");
  2103. Object fBoost = find(editfield, "fBoost");
  2104. Object cbStored = find(editfield, "cbStored");
  2105. //Object cbCmp = find(editfield, "cbCmp");
  2106. Object cbBin = find(editfield, "cbBin");
  2107. Object cbIndexed = find(editfield, "cbIndexed");
  2108. Object cbTokenized = find(editfield, "cbTokenized");
  2109. Object cbTVF = find(editfield, "cbTVF");
  2110. Object cbTVFp = find(editfield, "cbTVFp");
  2111. Object cbTVFo = find(editfield, "cbTVFo");
  2112. Object cbONorms = find(editfield, "cbONorms");
  2113. Object cbOTF = find(editfield, "cbOTF");
  2114. Object stored = find(editfield, "stored");
  2115. Object restored = find(editfield, "restored");
  2116. setBoolean(cbONorms, "selected", !ir.hasNorms(key));
  2117. Field f = null;
  2118. if (fields != null && fields.length > i) {
  2119. f = (Field) fields[i];
  2120. setString(fType, "text", "Original stored field content");
  2121. String text;
  2122. if (f.isBinary()) {
  2123. text = Util.bytesToHex(f.getBinaryValue(),
  2124. f.getBinaryOffset(), f.getBinaryLength(), true);
  2125. setBoolean(cbBin, "selected", true);
  2126. } else {
  2127. text = f.stringValue();
  2128. }
  2129. setString(sText, "text", text);
  2130. setString(fBoost, "text", String.valueOf(f.getBoost()));
  2131. setBoolean(cbStored, "selected", f.isStored());
  2132. // Lucene 3.0 doesn't support compressed fields
  2133. //setBoolean(cbCmp, "selected", false);
  2134. setBoolean(cbIndexed, "selected", f.isIndexed());
  2135. setBoolean(cbTokenized, "selected", f.isTokenized());
  2136. setBoolean(cbTVF, "selected", f.isTermVectorStored());
  2137. setBoolean(cbTVFp, "selected", f.isStorePositionWithTermVector());
  2138. setBoolean(cbTVFo, "selected", f.isStoreOffsetWithTermVector());
  2139. setBoolean(cbOTF, "selected", f.getOmitTermFreqAndPositions());
  2140. } else {
  2141. remove(stored);
  2142. }
  2143. if (recField != null) {
  2144. String sep = " ";
  2145. if (f == null) {
  2146. setString(fType, "text", "RESTORED content ONLY - check for errors!");
  2147. setColor(fType, "foreground", Color.red);
  2148. } else {
  2149. setBoolean(rText, "editable", false);
  2150. setBoolean(rText, "border", false);
  2151. setString(restored, "text", "Tokenized (from all '" + key + "' fields)");
  2152. sep = ", ";
  2153. }
  2154. setBoolean(cbIndexed, "selected", true);
  2155. setString(fBoost, "text", String.valueOf(1.0f));
  2156. setString(rText, "text", recField.toString(sep));
  2157. } else {
  2158. remove(restored);
  2159. }
  2160. }
  2161. }
  2162. add(dialog);
  2163. getPreferredSize(editTabs);
  2164. } catch (Exception e) {
  2165. e.printStackTrace();
  2166. showStatus(e.getMessage());
  2167. }
  2168. progress.hide();
  2169. }
  2170. };
  2171. thr.start();
  2172. }
  2173. public boolean actionEditAdd(Object editdoc) {
  2174. Document doc = new Document();
  2175. Object cbAnalyzers = find(editdoc, "cbAnalyzers");
  2176. // reuse the logic in createAnalyzer - needs a prepared srchOptTabs
  2177. Object srchTabs = find("srchOptTabs");
  2178. Object cbType = find(srchTabs, "cbType");
  2179. String clazz = getString(cbAnalyzers, "text");
  2180. setString(cbType, "text", clazz);
  2181. Analyzer a = createAnalyzer(srchTabs);
  2182. Object editTabs = find(editdoc, "editTabs");
  2183. Object[] tabs = getItems(editTabs);
  2184. for (int i = 0; i < tabs.length; i++) {
  2185. String name = getString(tabs[i], "text");
  2186. if (name.trim().equals("")) continue;
  2187. Object fBoost = find(tabs[i], "fBoost");
  2188. Object fText = find(tabs[i], "sText");
  2189. if (fText == null) fText = find(tabs[i], "rText");
  2190. Object cbStored = find(tabs[i], "cbStored");
  2191. Object cbIndexed = find(tabs[i], "cbIndexed");
  2192. Object cbTokenized = find(tabs[i], "cbTokenized");
  2193. Object cbTVF = find(tabs[i], "cbTVF");
  2194. Object cbTVFo = find(tabs[i], "cbTVFo");
  2195. Object cbTVFp = find(tabs[i], "cbTVFp");
  2196. Object cbCmp = find(tabs[i], "cbCmp");
  2197. Object cbBin = find(tabs[i], "cbBin");
  2198. Object cbONorms = find(tabs[i], "cbONorms");
  2199. Object cbOTF = find(tabs[i], "cbOTF");
  2200. String text = getString(fText, "text");
  2201. byte[] binValue;
  2202. boolean binary = getBoolean(cbBin, "selected");
  2203. Field.TermVector tv;
  2204. if (getBoolean(cbTVF, "selected")) {
  2205. if (getBoolean(cbTVFo, "selected")) {
  2206. if (getBoolean(cbTVFp, "selected")) {
  2207. tv = Field.TermVector.WITH_POSITIONS_OFFSETS;
  2208. } else {
  2209. tv = Field.TermVector.WITH_OFFSETS;
  2210. }
  2211. } else {
  2212. if (getBoolean(cbTVFp, "selected")) {
  2213. tv = Field.TermVector.WITH_POSITIONS;
  2214. } else {
  2215. tv = Field.TermVector.YES;
  2216. }
  2217. }
  2218. } else {
  2219. tv = Field.TermVector.NO;
  2220. }
  2221. Field f;
  2222. Store stored = getBoolean(cbStored, "selected") ? Field.Store.YES :
  2223. Field.Store.NO;
  2224. Index indexed = getBoolean(cbIndexed, "selected") ?
  2225. (getBoolean(cbTokenized, "selected") ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED) :
  2226. Field.Index.NO;
  2227. if (stored.equals(Store.NO) && indexed.equals(Index.NO)) {
  2228. errorMsg("Field '" + name + "' is neither stored nor indexed.");
  2229. return false;
  2230. }
  2231. if (binary) {
  2232. try {
  2233. binValue = Util.hexToBytes(text);
  2234. } catch (Throwable e) {
  2235. errorMsg("Field '" + name + "': " + e.getMessage());
  2236. return false;
  2237. }
  2238. f = new Field(name, binValue, stored);
  2239. } else {
  2240. f = new Field(name, text, stored, indexed, tv);
  2241. }
  2242. f.setOmitNorms(getBoolean(cbONorms, "selected"));
  2243. f.setOmitTermFreqAndPositions(getBoolean(cbOTF, "selected"));
  2244. String boostS = getString(fBoost, "text").trim();
  2245. if (!boostS.equals("") && !boostS.equals("1.0")) {
  2246. float boost = 1.0f;
  2247. try {
  2248. boost = Float.parseFloat(boostS);
  2249. } catch (Exception e) {
  2250. e.printStackTrace();
  2251. }
  2252. f.setBoost(boost);
  2253. }
  2254. doc.add(f);
  2255. }
  2256. IndexWriter writer = null;
  2257. boolean res = false;
  2258. String msg = null;
  2259. try {
  2260. ir.close();
  2261. IndexDeletionPolicy policy;
  2262. if (keepCommits) {
  2263. policy = new KeepAllIndexDeletionPolicy();
  2264. } else {
  2265. policy = new KeepLastIndexDeletionPolicy();
  2266. }
  2267. writer = new IndexWriter(dir, a, false, policy, MaxFieldLength.UNLIMITED);
  2268. writer.setUseCompoundFile(IndexGate.preferCompoundFormat(dir));
  2269. writer.addDocument(doc);
  2270. res = true;
  2271. } catch (Exception e) {
  2272. e.printStackTrace();
  2273. msg = "FAILED: " + e.getMessage();
  2274. res = false;
  2275. } finally {
  2276. try {
  2277. if (writer != null) writer.close();
  2278. } catch (Exception e) {
  2279. e.printStackTrace();
  2280. res = false;
  2281. msg = "FAILED: " + e.getMessage();
  2282. }
  2283. remove(editdoc);
  2284. try {
  2285. actionReopen();
  2286. // show Documents tab
  2287. Object tabpane = find("maintpane");
  2288. setInteger(tabpane, "selected", 1);
  2289. } catch (Exception e) {
  2290. e.printStackTrace();
  2291. res = false;
  2292. msg = "FAILED: " + e.getMessage();
  2293. }
  2294. }
  2295. if (!res) {
  2296. errorMsg(msg);
  2297. }
  2298. return res;
  2299. }
  2300. public void actionEditReplace(Object editdoc) {
  2301. if (!actionEditAdd(editdoc)) return;
  2302. Integer DocNum = (Integer) getProperty(editdoc, "docNum");
  2303. if (DocNum == null) return;
  2304. try {
  2305. ir.deleteDocument(DocNum.intValue());
  2306. } catch (Exception e) {
  2307. e.printStackTrace();
  2308. errorMsg("ERROR deleting: " + e.getMessage());
  2309. return;
  2310. }
  2311. }
  2312. public void actionEditAddField(Object editdoc) {
  2313. String name = getString(find(editdoc, "fNewName"), "text");
  2314. if (name.trim().equals("")) {
  2315. showStatus("FAILED: Field name is required.");
  2316. return;
  2317. }
  2318. name = name.trim();
  2319. Object editTabs = find(editdoc, "editTabs");
  2320. Object tab = create("tab");
  2321. setString(tab, "text", name);
  2322. setFont(tab, getFont().deriveFont(Font.BOLD));
  2323. add(editTabs, tab);
  2324. addComponent(tab, "/xml/editfield.xml", null, null);
  2325. repaint(editTabs);
  2326. }
  2327. public void actionEditDeleteField(Object editfield) {
  2328. Object tab = getParent(editfield);
  2329. remove(tab);
  2330. }
  2331. /** More Like this query from the current doc (or selected fields) */
  2332. public void actionMLT(Object docNum, Object docTable) {
  2333. if (ir == null) {
  2334. errorMsg(MSG_NOINDEX);
  2335. return;
  2336. }
  2337. int id = 0;
  2338. try {
  2339. id = Integer.parseInt(getString(docNum, "text"));
  2340. } catch (NumberFormatException nfe) {
  2341. errorMsg("Invalid document number");
  2342. return;
  2343. }
  2344. MoreLikeThis mlt = new MoreLikeThis(ir, similarity != null ? similarity : new DefaultSimilarity());
  2345. mlt.setFieldNames((String[])ir.getFieldNames(FieldOption.INDEXED).toArray(new String[0]));
  2346. mlt.setMinTermFreq(1);
  2347. mlt.setMaxQueryTerms(50);
  2348. mlt.setAnalyzer(createAnalyzer(find("srchOptTabs")));
  2349. Object[] rows = getSelectedItems(docTable);
  2350. BooleanQuery similar = null;
  2351. if (rows != null && rows.length > 0) {
  2352. // collect text from fields
  2353. StringBuilder sb = new StringBuilder();
  2354. for (int i = 0; i < rows.length; i++) {
  2355. Field f = (Field)getProperty(rows[i], "field");
  2356. if (f == null) {
  2357. continue;
  2358. }
  2359. String s = f.stringValue();
  2360. if (s == null || s.trim().length() == 0) {
  2361. continue;
  2362. }
  2363. if (sb.length() > 0) sb.append(" ");
  2364. sb.append(s);
  2365. }
  2366. try {
  2367. similar = (BooleanQuery)mlt.like(new StringReader(sb.toString()));
  2368. } catch (Exception e) {
  2369. e.printStackTrace();
  2370. errorMsg("FAILED: " + e.getMessage());
  2371. return;
  2372. }
  2373. } else {
  2374. try {
  2375. similar = (BooleanQuery)mlt.like(id);
  2376. } catch (Exception e) {
  2377. e.printStackTrace();
  2378. errorMsg("FAILED: " + e.getMessage());
  2379. return;
  2380. }
  2381. }
  2382. if (similar.clauses() != null && similar.clauses().size() > 0) {
  2383. //System.err.println("SIMILAR: " + similar);
  2384. Object tabpane = find("maintpane");
  2385. setInteger(tabpane, "selected", 2);
  2386. Object qField = find("qField");
  2387. setString(qField, "text", similar.toString());
  2388. } else {
  2389. showStatus("WARN: empty query - check Analyzer settings");
  2390. }
  2391. }
  2392. private void _showDocFields(int docid, Document doc) {
  2393. Object table = find("docTable");
  2394. setString(find("docNum"), "text", String.valueOf(docid));
  2395. removeAll(table);
  2396. putProperty(table, "doc", doc);
  2397. putProperty(table, "docNum", new Integer(docid));
  2398. if (doc == null) {
  2399. setString(find("docNum1"), "text", String.valueOf(docid) + " DELETED");
  2400. return;
  2401. }
  2402. setString(find("docNum1"), "text", String.valueOf(docid));
  2403. for (int i = 0; i < idxFields.length; i++) {
  2404. Field[] fields = doc.getFields(idxFields[i]);
  2405. if (fields == null) {
  2406. addFieldRow(table, idxFields[i], null, docid);
  2407. continue;
  2408. }
  2409. for (int j = 0; j < fields.length; j++) {
  2410. // if (fields[j].isBinary()) {
  2411. // System.out.println("f.len=" + fields[j].getBinaryLength() + ", doc.len=" + doc.getBinaryValue(idxFields[i]).length);
  2412. // }
  2413. addFieldRow(table, idxFields[i], fields[j], docid);
  2414. }
  2415. }
  2416. doLayout(table);
  2417. }
  2418. Font courier = null;
  2419. private void addFieldRow(Object table, String fName, Field f, int docid) {
  2420. Object row = create("row");
  2421. add(table, row);
  2422. putProperty(row, "field", f);
  2423. putProperty(row, "fName", fName);
  2424. Object cell = create("cell");
  2425. setString(cell, "text", fName );
  2426. add(row, cell);
  2427. cell = create("cell");
  2428. setString(cell, "text", Util.fieldFlags(f));
  2429. if (f == null) {
  2430. setBoolean(cell, "enabled", false);
  2431. }
  2432. setFont(cell, "font", courier);
  2433. setChoice(cell, "alignment", "center");
  2434. add(row, cell);
  2435. cell = create("cell");
  2436. if (f != null) {
  2437. try {
  2438. if (ir.hasNorms(fName)) {
  2439. setString(cell, "text", String.valueOf(Similarity.decodeNorm(ir.norms(fName)[docid])));
  2440. } else {
  2441. setString(cell, "text", "---");
  2442. }
  2443. } catch (IOException ioe) {
  2444. ioe.printStackTrace();
  2445. setString(cell, "text", "!?!");
  2446. }
  2447. } else {
  2448. setString(cell, "text", "---");
  2449. setBoolean(cell, "enabled", false);
  2450. }
  2451. add(row, cell);
  2452. cell = create("cell");
  2453. if (f != null) {
  2454. String text = f.stringValue();
  2455. if (text == null && f.isBinary()) {
  2456. text = Util.bytesToHex(f.getBinaryValue(), f.getBinaryOffset(),
  2457. f.getBinaryLength(), false);
  2458. }
  2459. Decoder dec = decoders.get(f.name());
  2460. if (dec == null) dec = defDecoder;
  2461. try {
  2462. if (f.isStored()) {
  2463. text = dec.decodeStored(f.name(), text);
  2464. } else {
  2465. text = dec.decodeTerm(f.name(), text);
  2466. }
  2467. } catch (Throwable e) {
  2468. setColor(cell, "foreground", Color.RED);
  2469. }
  2470. setString(cell, "text", Util.escape(text));
  2471. } else {
  2472. setString(cell, "text", "<not present or not stored>");
  2473. setBoolean(cell, "enabled", false);
  2474. }
  2475. add(row, cell);
  2476. }
  2477. public void showTV(Object table) {
  2478. final Object row = getSelectedItem(table);
  2479. if (row == null) return;
  2480. if (ir == null) {
  2481. showStatus(MSG_NOINDEX);
  2482. return;
  2483. }
  2484. final Integer DocId = (Integer) getProperty(table, "docNum");
  2485. if (DocId == null) {
  2486. showStatus("Missing Doc. Id.");
  2487. return;
  2488. }
  2489. SlowThread st = new SlowThread(this) {
  2490. public void execute() {
  2491. try {
  2492. String fName = (String) getProperty(row, "fName");
  2493. TermFreqVector tfv = ir.getTermFreqVector(DocId.intValue(), fName);
  2494. if (tfv == null) {
  2495. showStatus("Term Vector not available.");
  2496. return;
  2497. }
  2498. Object dialog = addComponent(null, "/xml/vector.xml", null, null);
  2499. setString(find(dialog, "fld"), "text", fName);
  2500. Object vTable = find(dialog, "vTable");
  2501. IntPair[] tvs = new IntPair[tfv.size()];
  2502. String[] terms = tfv.getTerms();
  2503. int[] freqs = tfv.getTermFrequencies();
  2504. TermPositionVector tpv = null;
  2505. Decoder dec = decoders.get(fName);
  2506. if (dec == null) dec = defDecoder;
  2507. if (tfv instanceof TermPositionVector) tpv = (TermPositionVector)tfv;
  2508. for (int i = 0; i < terms.length; i++) {
  2509. IntPair ip = new IntPair(freqs[i], terms[i]);
  2510. if (tpv != null) {
  2511. ip.offsets = tpv.getOffsets(i);
  2512. ip.positions = tpv.getTermPositions(i);
  2513. }
  2514. tvs[i] = ip;
  2515. }
  2516. Arrays.sort(tvs, new IntPair.PairComparator(false, true));
  2517. for (int i = 0; i < tvs.length; i++) {
  2518. Object r = create("row");
  2519. add(vTable, r);
  2520. putProperty(r, "tf", tvs[i]);
  2521. Object cell = create("cell");
  2522. String s;
  2523. try {
  2524. s = dec.decodeTerm(fName, tvs[i].text);
  2525. } catch (Throwable e) {
  2526. s = tvs[i].text;
  2527. setColor(cell, "foreground", Color.RED);
  2528. }
  2529. setString(cell, "text", Util.escape(s));
  2530. add(r, cell);
  2531. cell = create("cell");
  2532. setString(cell, "text", String.valueOf(tvs[i].cnt));
  2533. add(r, cell);
  2534. cell = create("cell");
  2535. if (tvs[i].positions != null) {
  2536. StringBuilder sb = new StringBuilder();
  2537. for (int k = 0; k < tvs[i].positions.length; k++) {
  2538. if (k > 0) sb.append(',');
  2539. sb.append(String.valueOf(tvs[i].positions[k]));
  2540. }
  2541. setString(cell, "text", sb.toString());
  2542. }
  2543. add(r, cell);
  2544. cell = create("cell");
  2545. if (tvs[i].offsets != null) {
  2546. StringBuilder sb = new StringBuilder();
  2547. for (int k = 0; k < tvs[i].offsets.length; k++) {
  2548. if (k > 0) sb.append(',');
  2549. TermVectorOffsetInfo tvfi = tvs[i].offsets[k];
  2550. sb.append(tvfi.getStartOffset() + "-" + tvfi.getEndOffset());
  2551. }
  2552. setString(cell, "text", sb.toString());
  2553. }
  2554. add(r, cell);
  2555. }
  2556. add(dialog);
  2557. } catch (Exception e) {
  2558. e.printStackTrace();
  2559. showStatus(e.getMessage());
  2560. }
  2561. }
  2562. };
  2563. if (slowAccess) {
  2564. st.start();
  2565. } else {
  2566. st.execute();
  2567. }
  2568. }
  2569. public void clipTV(Object vTable) {
  2570. Object[] rows = getItems(vTable);
  2571. StringBuilder sb = new StringBuilder();
  2572. for (int i = 0; i < rows.length; i++) {
  2573. IntPair tf = (IntPair)getProperty(rows[i], "tf");
  2574. sb.append(tf.cnt + "\t" + tf.text);
  2575. if (tf.positions != null) {
  2576. sb.append("\t");
  2577. for (int k = 0; k < tf.positions.length; k++) {
  2578. if (k > 0) sb.append(',');
  2579. sb.append(String.valueOf(tf.positions[k]));
  2580. }
  2581. }
  2582. if (tf.offsets != null) {
  2583. if (tf.positions == null) sb.append("\t");
  2584. sb.append("\t");
  2585. for (int k = 0; k < tf.offsets.length; k++) {
  2586. if (k > 0) sb.append(',');
  2587. TermVectorOffsetInfo tvfi = tf.offsets[k];
  2588. sb.append(tvfi.getStartOffset() + "-" + tvfi.getEndOffset());
  2589. }
  2590. }
  2591. sb.append("\n");
  2592. }
  2593. StringSelection sel = new StringSelection(sb.toString());
  2594. Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, this);
  2595. }
  2596. public void actionSetNorm(Object table) throws Exception {
  2597. Object row = getSelectedItem(table);
  2598. if (row == null) return;
  2599. if (ir == null) {
  2600. showStatus(MSG_NOINDEX);
  2601. return;
  2602. }
  2603. Field f = (Field) getProperty(row, "field");
  2604. if (f == null) {
  2605. showStatus("No data available for this field");
  2606. return;
  2607. }
  2608. if (!f.isIndexed()) {
  2609. showStatus("Cannot set norm value - this field is not indexed.");
  2610. return;
  2611. }
  2612. Object dialog = addComponent(null, "/xml/fnorm.xml", null, null);
  2613. Integer docNum = (Integer)getProperty(table, "docNum");
  2614. putProperty(dialog, "docNum", getProperty(table, "docNum"));
  2615. putProperty(dialog, "field", f);
  2616. Object curNorm = find(dialog, "curNorm");
  2617. Object newNorm = find(dialog, "newNorm");
  2618. Object encNorm = find(dialog, "encNorm");
  2619. Object doc = find(dialog, "docNum");
  2620. Object fld = find(dialog, "fld");
  2621. setString(doc, "text", String.valueOf(docNum.intValue()));
  2622. setString(fld, "text", f.name());
  2623. try {
  2624. byte curBVal = ir.norms(f.name())[docNum.intValue()];
  2625. float curFVal = Similarity.decodeNorm(curBVal);
  2626. setString(curNorm, "text", String.valueOf(curFVal));
  2627. setString(newNorm, "text", String.valueOf(curFVal));
  2628. setString(encNorm, "text", String.valueOf(curFVal) +
  2629. " (0x" + Util.byteToHex(curBVal) + ")");
  2630. } catch (Exception e) {
  2631. errorMsg("Error reading norm: " + e.toString());
  2632. return;
  2633. }
  2634. add(dialog);
  2635. displayNewNorm(dialog);
  2636. }
  2637. public void displayNewNorm(Object dialog) {
  2638. Object newNorm = find(dialog, "newNorm");
  2639. Object encNorm = find(dialog, "encNorm");
  2640. try {
  2641. float newFVal = Float.parseFloat(getString(newNorm, "text"));
  2642. byte newBVal = Similarity.encodeNorm(newFVal);
  2643. float encFVal = Similarity.decodeNorm(newBVal);
  2644. setString(encNorm, "text", String.valueOf(encFVal) +
  2645. " (0x" + Util.byteToHex(newBVal) + ")");
  2646. putProperty(dialog, "newNorm", new Float(newFVal));
  2647. doLayout(dialog);
  2648. } catch (Exception e) {
  2649. // XXX eat silently
  2650. }
  2651. }
  2652. public void setNorm(Object dialog) {
  2653. boolean singleDoc = getBoolean(find(dialog, "fDoc"), "selected");
  2654. boolean allDoc = getBoolean(find(dialog, "fAll"), "selected");
  2655. boolean ranges = getBoolean(find(dialog, "fList"), "selected");
  2656. Float newFVal = (Float)getProperty(dialog, "newNorm");
  2657. Integer docNum = (Integer)getProperty(dialog, "docNum");
  2658. Field f = (Field)getProperty(dialog, "field");
  2659. try {
  2660. if (singleDoc) {
  2661. ir.setNorm(docNum.intValue(), f.name(), newFVal.floatValue());
  2662. } else if (allDoc) {
  2663. for (int i = 0; i < ir.maxDoc(); i++) {
  2664. if (ir.isDeleted(i)) continue;
  2665. ir.setNorm(i, f.name(), newFVal.floatValue());
  2666. }
  2667. } else if (ranges) {
  2668. String expr = getString(find(dialog, "frange"), "text");
  2669. Ranges r = Ranges.parse(expr);
  2670. if (r.cardinality() == 0) {
  2671. infoMsg("Empty list - no documents selected, no modifications.");
  2672. } else {
  2673. DocIdSetIterator it = r.iterator();
  2674. int docId;
  2675. while ((docId = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
  2676. if (ir.isDeleted(docId)) continue;
  2677. ir.setNorm(docId, f.name(), newFVal.floatValue());
  2678. }
  2679. }
  2680. }
  2681. } catch (Exception e) {
  2682. e.printStackTrace();
  2683. errorMsg("Set norms failed: " + e.toString());
  2684. }
  2685. remove(dialog);
  2686. Object table = find("docTable");
  2687. Document doc = (Document)getProperty(table, "doc");
  2688. _showDocFields(docNum.intValue(), doc);
  2689. }
  2690. public void showTField(Object table) {
  2691. Object row = getSelectedItem(table);
  2692. if (row == null) return;
  2693. if (ir == null) {
  2694. showStatus(MSG_NOINDEX);
  2695. return;
  2696. }
  2697. Field f = (Field) getProperty(row, "field");
  2698. if (f == null) {
  2699. showStatus("No data available for this field");
  2700. return;
  2701. }
  2702. Object dialog = addComponent(null, "/xml/field.xml", null, null);
  2703. Object fName = find(dialog, "fld");
  2704. putProperty(dialog, "f", f);
  2705. setString(fName, "text", f.name());
  2706. add(dialog);
  2707. _showData(dialog);
  2708. }
  2709. public void _showData(Object dialog) {
  2710. Object fDataText = find(dialog, "fDataText");
  2711. Field f = (Field)getProperty(dialog, "f");
  2712. String value = null;
  2713. String enc = "cbUtf";
  2714. Object choice = getSelectedItem(find(dialog, "cbData"));
  2715. String selEnc = getString(choice, "name");
  2716. boolean warn = false;
  2717. if (selEnc != null) enc = selEnc;
  2718. int len = 0;
  2719. byte[] data = null;
  2720. if (f.isBinary()) {
  2721. data = new byte[f.getBinaryLength()];
  2722. System.arraycopy(f.getBinaryValue(), f.getBinaryOffset(), data, 0,
  2723. f.getBinaryLength());
  2724. }
  2725. else {
  2726. try {
  2727. data = f.stringValue().getBytes("UTF-8");
  2728. } catch (UnsupportedEncodingException uee) {
  2729. warn = true;
  2730. uee.printStackTrace();
  2731. data = f.stringValue().getBytes();
  2732. }
  2733. }
  2734. if (data == null) data = new byte[0];
  2735. if (enc.equals("cbHex")) {
  2736. setString(find(dialog, "unit"), "text", " bytes");
  2737. value = Util.bytesToHex(data, 0, data.length, true);
  2738. len = data.length;
  2739. } else if (enc.equals("cbUtf")) {
  2740. setString(find(dialog, "unit"), "text", " UTF-8 characters");
  2741. value = f.stringValue();
  2742. if (value != null) len = value.length();
  2743. } else if (enc.equals("cbDef")) {
  2744. setString(find(dialog, "unit"), "text", " characters");
  2745. value = new String(data);
  2746. len = value.length();
  2747. } else if (enc.equals("cbDate")) {
  2748. try {
  2749. Date d = DateTools.stringToDate(f.stringValue());
  2750. value = d.toString();
  2751. len = 1;
  2752. } catch (Exception e) {
  2753. warn = true;
  2754. value = Util.bytesToHex(data, 0, data.length, true);
  2755. }
  2756. } else if (enc.equals("cbNum")) {
  2757. try {
  2758. long num = NumericUtils.prefixCodedToLong(f.stringValue());
  2759. value = String.valueOf(num);
  2760. len = 1;
  2761. } catch (Exception e) {
  2762. warn = true;
  2763. value = Util.bytesToHex(data, 0, data.length, true);
  2764. }
  2765. } else if (enc.equals("cbInt")) {
  2766. if (data.length % 4 == 0) {
  2767. setString(find(dialog, "unit"), "text", " int values");
  2768. len = data.length / 4;
  2769. StringBuilder sb = new StringBuilder();
  2770. for (int k = 0; k < data.length; k += 4) {
  2771. if (k > 0) sb.append(',');
  2772. sb.append(String.valueOf(PayloadHelper.decodeInt(data, k)));
  2773. }
  2774. value = sb.toString();
  2775. } else {
  2776. warn = true;
  2777. value = Util.bytesToHex(data, 0, data.length, true);
  2778. }
  2779. } else if (enc.equals("cbFloat")) {
  2780. if (data.length % 4 == 0) {
  2781. setString(find(dialog, "unit"), "text", " float values");
  2782. len = data.length / 4;
  2783. StringBuilder sb = new StringBuilder();
  2784. for (int k = 0; k < data.length; k += 4) {
  2785. if (k > 0) sb.append(',');
  2786. sb.append(String.valueOf(PayloadHelper.decodeFloat(data, k)));
  2787. }
  2788. value = sb.toString();
  2789. } else {
  2790. warn = true;
  2791. value = Util.bytesToHex(data, 0, data.length, true);
  2792. }
  2793. }
  2794. setString(fDataText, "text", value);
  2795. setString(find(dialog, "len"), "text", String.valueOf(len));
  2796. if (warn) {
  2797. setBoolean(fDataText, "enabled", false);
  2798. errorMsg(MSG_CONV_ERROR);
  2799. } else {
  2800. setBoolean(fDataText, "enabled", true);
  2801. }
  2802. }
  2803. public void saveField(Object table) {
  2804. Object row = getSelectedItem(table);
  2805. if (row == null) return;
  2806. if (ir == null) {
  2807. showStatus(MSG_NOINDEX);
  2808. return;
  2809. }
  2810. Field f = (Field) getProperty(row, "field");
  2811. if (f == null) {
  2812. showStatus("No data available for this field");
  2813. return;
  2814. }
  2815. JFileChooser fd = new JFileChooser();
  2816. fd.setDialogType(JFileChooser.SAVE_DIALOG);
  2817. fd.setDialogTitle("Save field content to a file");
  2818. fd.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
  2819. fd.setFileHidingEnabled(false);
  2820. if (this.baseDir != null)
  2821. fd.setCurrentDirectory(new File(this.baseDir));
  2822. else fd.setCurrentDirectory(new File(System.getProperty("user.dir")));
  2823. int res = fd.showSaveDialog(this);
  2824. File iFile = null;
  2825. if (res == JFileChooser.APPROVE_OPTION) iFile = fd.getSelectedFile();
  2826. if (iFile == null) return;
  2827. if (iFile.exists() && iFile.isDirectory()) {
  2828. errorMsg("Can't overwrite a directory.");
  2829. return;
  2830. }
  2831. Object progress = null;
  2832. try {
  2833. byte[] data = null;
  2834. if (f.isBinary()) data = f.getBinaryValue();
  2835. else {
  2836. try {
  2837. data = f.stringValue().getBytes("UTF-8");
  2838. } catch (UnsupportedEncodingException uee) {
  2839. uee.printStackTrace();
  2840. errorMsg(uee.toString());
  2841. data = f.stringValue().getBytes();
  2842. }
  2843. }
  2844. if (data == null || data.length == 0) {
  2845. showStatus("No data available");
  2846. return;
  2847. }
  2848. progress = addComponent(null, "/xml/progress.xml", null, null);
  2849. setString(find(progress, "msg"), "text", "Saving...");
  2850. Object bar = find(progress, "bar");
  2851. setInteger(bar, "maximum", 100);
  2852. OutputStream os = new FileOutputStream(iFile);
  2853. int delta = data.length / 100;
  2854. if (delta == 0) delta = 1;
  2855. add(progress);
  2856. for (int i = 0; i < data.length; i++) {
  2857. os.write(data[i]);
  2858. if (i % delta == 0) {
  2859. setInteger(bar, "value", i / delta);
  2860. }
  2861. }
  2862. os.flush();
  2863. os.close();
  2864. setString(find(progress, "msg"), "text", "Done!");
  2865. try { Thread.sleep(1000); } catch (Exception e) {};
  2866. } catch (IOException ioe) {
  2867. ioe.printStackTrace();
  2868. errorMsg("Can't save: " + ioe);
  2869. return;
  2870. } finally {
  2871. if (progress != null) remove(progress);
  2872. }
  2873. }
  2874. public void clipCopyFields(Object table) {
  2875. Object[] rows = getSelectedItems(table);
  2876. if (rows == null || rows.length == 0) return;
  2877. Document doc = (Document) getProperty(table, "doc");
  2878. if (doc == null) return;
  2879. StringBuffer sb = new StringBuffer();
  2880. for (int i = 0; i < rows.length; i++) {
  2881. Field f = (Field) getProperty(rows[i], "field");
  2882. if (f == null) continue;
  2883. if (i > 0) sb.append('\n');
  2884. sb.append(f.toString());
  2885. }
  2886. StringSelection sel = new StringSelection(sb.toString());
  2887. Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, this);
  2888. }
  2889. public void clipCopyDoc(Object table) {
  2890. Document doc = (Document) getProperty(table, "doc");
  2891. if (doc == null) return;
  2892. StringBuffer sb = new StringBuffer();
  2893. Object[] rows = getItems(table);
  2894. for (int i = 0; i < rows.length; i++) {
  2895. Field f = (Field) getProperty(rows[i], "field");
  2896. if (f == null) continue;
  2897. if (i > 0) sb.append('\n');
  2898. sb.append(f.toString());
  2899. }
  2900. StringSelection sel = new StringSelection(sb.toString());
  2901. Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, this);
  2902. }
  2903. public void showFirstTerm(final Object fCombo, final Object fText) {
  2904. if (ir == null) {
  2905. showStatus(MSG_NOINDEX);
  2906. return;
  2907. }
  2908. SlowThread st = new SlowThread(this) {
  2909. public void execute() {
  2910. try {
  2911. String fld = getString(fCombo, "text");
  2912. TermEnum te = ir.terms(new Term(fld, ""));
  2913. Term t = te.term();
  2914. _showTerm(fCombo, fText, t);
  2915. } catch (Exception e) {
  2916. e.printStackTrace();
  2917. showStatus(e.getMessage());
  2918. }
  2919. }
  2920. };
  2921. if (slowAccess) {
  2922. st.start();
  2923. } else {
  2924. st.execute();
  2925. }
  2926. }
  2927. public void showNextTerm(final Object fCombo, final Object fText) {
  2928. if (ir == null) {
  2929. showStatus(MSG_NOINDEX);
  2930. return;
  2931. }
  2932. SlowThread st = new SlowThread(this) {
  2933. public void execute() {
  2934. try {
  2935. String text;
  2936. Term rawTerm = (Term)getProperty(fText, "term");
  2937. text = getString(fText, "text");
  2938. if (rawTerm != null) {
  2939. String s = (String)getProperty(fText, "decText");
  2940. if (s.equals(text)) {
  2941. text = rawTerm.text();
  2942. }
  2943. }
  2944. String fld = getString(fCombo, "text");
  2945. TermEnum te = null;
  2946. if (text == null || text.trim().equals("")) text = "";
  2947. te = ir.terms(new Term(fld, text));
  2948. te.next();
  2949. Term t = te.term();
  2950. _showTerm(fCombo, fText, t);
  2951. } catch (Exception e) {
  2952. e.printStackTrace();
  2953. showStatus(e.getMessage());
  2954. }
  2955. }
  2956. };
  2957. if (slowAccess) {
  2958. st.start();
  2959. } else {
  2960. st.execute();
  2961. }
  2962. }
  2963. public void showTerm(final Object fCombo, final Object fText) {
  2964. if (ir == null) {
  2965. showStatus(MSG_NOINDEX);
  2966. return;
  2967. }
  2968. SlowThread st = new SlowThread(this) {
  2969. public void execute() {
  2970. try {
  2971. String text;
  2972. Term rawTerm = (Term)getProperty(fText, "term");
  2973. text = getString(fText, "text");
  2974. if (rawTerm != null) {
  2975. String s = (String)getProperty(fText, "decText");
  2976. if (s.equals(text)) {
  2977. text = rawTerm.text();
  2978. }
  2979. }
  2980. String fld = getString(fCombo, "text");
  2981. if (text == null || text.trim().equals("")) return;
  2982. Term t = new Term(fld, text);
  2983. if (ir.docFreq(t) == 0) { // missing term
  2984. TermEnum te = ir.terms(t);
  2985. t = te.term();
  2986. }
  2987. _showTerm(fCombo, fText, t);
  2988. } catch (Exception e) {
  2989. e.printStackTrace();
  2990. showStatus(e.getMessage());
  2991. }
  2992. }
  2993. };
  2994. if (slowAccess) {
  2995. st.start();
  2996. } else {
  2997. st.execute();
  2998. }
  2999. }
  3000. private void _showTerm(Object fCombo, Object fText, final Term t) {
  3001. if (t == null) {
  3002. showStatus("No terms?!");
  3003. return;
  3004. }
  3005. if (ir == null) {
  3006. showStatus(MSG_NOINDEX);
  3007. return;
  3008. }
  3009. Object[] choices = getItems(fCombo);
  3010. for (int i = 0; i < choices.length; i++) {
  3011. if (t.field().equals(getString(choices[i], "text"))) {
  3012. setInteger(fCombo, "selected", i);
  3013. break;
  3014. }
  3015. }
  3016. Decoder dec = decoders.get(t.field());
  3017. if (dec == null) dec = defDecoder;
  3018. String s = null;
  3019. boolean decodeErr = false;
  3020. try {
  3021. s = dec.decodeTerm(t.field(), t.text());
  3022. } catch (Throwable e) {
  3023. s = e.getMessage();
  3024. decodeErr = true;
  3025. }
  3026. setString(fText, "text", t.text());
  3027. Object rawText = find("decText");
  3028. if (!s.equals(t.text())) {
  3029. setString(rawText, "text", s);
  3030. if (decodeErr) {
  3031. setColor(rawText, "foreground", Color.RED);
  3032. } else {
  3033. setColor(rawText, "foreground", Color.BLUE);
  3034. }
  3035. } else {
  3036. setString(rawText, "text", "");
  3037. setColor(rawText, "foreground", Color.BLACK);
  3038. }
  3039. putProperty(fText, "term", t);
  3040. putProperty(fText, "decText", s);
  3041. putProperty(fText, "td", null);
  3042. setString(find("tdNum"), "text", "?");
  3043. setString(find("tFreq"), "text", "?");
  3044. SlowThread st = new SlowThread(this) {
  3045. public void execute() {
  3046. Object dFreq = find("dFreq");
  3047. try {
  3048. int freq = ir.docFreq(t);
  3049. setString(dFreq, "text", String.valueOf(freq));
  3050. dFreq = find("tdMax");
  3051. setString(dFreq, "text", String.valueOf(freq));
  3052. } catch (Exception e) {
  3053. e.printStackTrace();
  3054. showStatus(e.getMessage());
  3055. setString(dFreq, "text", "?");
  3056. }
  3057. }
  3058. };
  3059. if (slowAccess) {
  3060. st.start();
  3061. } else {
  3062. st.execute();
  3063. }
  3064. }
  3065. public void showFirstTermDoc(final Object fText) {
  3066. final Term t = (Term) getProperty(fText, "term");
  3067. if (t == null) return;
  3068. if (ir == null) {
  3069. showStatus(MSG_NOINDEX);
  3070. return;
  3071. }
  3072. SlowThread st = new SlowThread(this) {
  3073. public void execute() {
  3074. try {
  3075. TermPositions td = ir.termPositions(t);
  3076. td.next();
  3077. setString(find("tdNum"), "text", "1");
  3078. putProperty(fText, "td", td);
  3079. _showTermDoc(fText, td);
  3080. } catch (Exception e) {
  3081. e.printStackTrace();
  3082. showStatus(e.getMessage());
  3083. }
  3084. }
  3085. };
  3086. if (slowAccess) {
  3087. st.start();
  3088. } else {
  3089. st.execute();
  3090. }
  3091. }
  3092. public void showNextTermDoc(final Object fText) {
  3093. final Term t = (Term) getProperty(fText, "term");
  3094. if (t == null) return;
  3095. if (ir == null) {
  3096. showStatus(MSG_NOINDEX);
  3097. return;
  3098. }
  3099. SlowThread st = new SlowThread(this) {
  3100. public void execute() {
  3101. try {
  3102. TermPositions td = (TermPositions) getProperty(fText, "td");
  3103. if (td == null) {
  3104. showFirstTermDoc(fText);
  3105. return;
  3106. }
  3107. if (!td.next()) return;
  3108. Object tdNum = find("tdNum");
  3109. String sCnt = getString(tdNum, "text");
  3110. int cnt = 1;
  3111. try {
  3112. cnt = Integer.parseInt(sCnt);
  3113. } catch (Exception e) {}
  3114. ;
  3115. setString(tdNum, "text", String.valueOf(cnt + 1));
  3116. _showTermDoc(fText, td);
  3117. } catch (Exception e) {
  3118. e.printStackTrace();
  3119. showStatus(e.getMessage());
  3120. }
  3121. }
  3122. };
  3123. if (slowAccess) {
  3124. st.start();
  3125. } else {
  3126. st.execute();
  3127. }
  3128. }
  3129. public void showPositions(final Object fText) {
  3130. final Term t = (Term) getProperty(fText, "term");
  3131. if (t == null) return;
  3132. if (ir == null) {
  3133. showStatus(MSG_NOINDEX);
  3134. return;
  3135. }
  3136. SlowThread st = new SlowThread(this) {
  3137. public void execute() {
  3138. try {
  3139. TermPositions td = (TermPositions) getProperty(fText, "td");
  3140. if (td == null) {
  3141. return;
  3142. }
  3143. Object dialog = addComponent(null, "/xml/positions.xml", null, null);
  3144. setString(find(dialog, "term"), "text", t.toString());
  3145. String docNum = getString(find("docNum"), "text");
  3146. setString(find(dialog, "docNum"), "text", docNum);
  3147. setString(find(dialog, "freq"), "text", String.valueOf(td.freq()));
  3148. putProperty(dialog, "td", td);
  3149. Object pTable = find(dialog, "pTable");
  3150. removeAll(pTable);
  3151. int freq = td.freq();
  3152. // need to rewind this enum :(
  3153. td.seek(t);
  3154. td.skipTo(Integer.parseInt(docNum));
  3155. for (int i = 0; i < freq; i++) {
  3156. try {
  3157. int pos = td.nextPosition();
  3158. Object r = create("row");
  3159. Object cell = create("cell");
  3160. setString(cell, "text", String.valueOf(pos));
  3161. add(r, cell);
  3162. cell = create("cell");
  3163. add(r, cell);
  3164. if (td.isPayloadAvailable()) {
  3165. byte[] payload = new byte[td.getPayloadLength()];
  3166. td.getPayload(payload, 0);
  3167. putProperty(r, "payload", payload);
  3168. }
  3169. add(pTable, r);
  3170. } catch (IOException ioe) {
  3171. errorMsg("Error: " + ioe.toString());
  3172. return;
  3173. }
  3174. }
  3175. _showPayloads(dialog);
  3176. add(dialog);
  3177. } catch (Exception e) {
  3178. e.printStackTrace();
  3179. showStatus(e.getMessage());
  3180. }
  3181. }
  3182. };
  3183. if (slowAccess) {
  3184. st.start();
  3185. } else {
  3186. st.execute();
  3187. }
  3188. }
  3189. public void _showPayloads(Object dialog) {
  3190. Object cbPay = find(dialog, "cbPay");
  3191. Object choice = getSelectedItem(cbPay);
  3192. String enc = "cbUtf";
  3193. if (choice != null) enc = getString(choice, "name");
  3194. Object pTable = find(dialog, "pTable");
  3195. Object[] rows = getItems(pTable);
  3196. boolean warn = false;
  3197. for (int i = 0; i < rows.length; i++) {
  3198. byte[] payload = (byte[])getProperty(rows[i], "payload");
  3199. if (payload == null) continue;
  3200. Object cell = getItem(rows[i], 1);
  3201. String curEnc = enc;
  3202. if (enc.equals("cbInt") || enc.equals("cbFloat")) {
  3203. if (payload.length % 4 != 0)
  3204. curEnc = "cbHex";
  3205. }
  3206. String val = "?";
  3207. if (curEnc.equals("cbUtf")) {
  3208. try {
  3209. val = new String(payload, "UTF-8");
  3210. } catch (Exception e) {
  3211. e.printStackTrace();
  3212. val = new String(payload);
  3213. curEnc = "cbDef";
  3214. }
  3215. } else if (curEnc.equals("cbHex")) {
  3216. val = Util.bytesToHex(payload, 0, payload.length, false);
  3217. } else if (curEnc.equals("cbDef")) {
  3218. val = new String(payload);
  3219. } else if (curEnc.equals("cbInt")) {
  3220. StringBuilder sb = new StringBuilder();
  3221. for (int k = 0; k < payload.length; k += 4) {
  3222. if (k > 0) sb.append(',');
  3223. sb.append(String.valueOf(PayloadHelper.decodeInt(payload, k)));
  3224. }
  3225. val = sb.toString();
  3226. } else if (curEnc.equals("cbFloat")) {
  3227. StringBuilder sb = new StringBuilder();
  3228. for (int k = 0; k < payload.length; k += 4) {
  3229. if (k > 0) sb.append(',');
  3230. sb.append(String.valueOf(PayloadHelper.decodeFloat(payload, k)));
  3231. }
  3232. val = sb.toString();
  3233. }
  3234. setString(cell, "text", val);
  3235. if (!curEnc.equals(enc)) {
  3236. setBoolean(cell, "enabled", false);
  3237. warn = true;
  3238. } else {
  3239. setBoolean(cell, "enabled", true);
  3240. }
  3241. }
  3242. if (warn) {
  3243. errorMsg(MSG_CONV_ERROR);
  3244. }
  3245. }
  3246. public void clipPositions(Object pTable) {
  3247. Object[] rows = getItems(pTable);
  3248. StringBuilder sb = new StringBuilder();
  3249. for (int i = 0; i < rows.length; i++) {
  3250. if (i > 0) sb.append('\n');
  3251. Object[] cells = getItems(rows[i]);
  3252. for (int k = 0; k < cells.length; k++) {
  3253. if (k > 0) sb.append('\t');
  3254. sb.append(getString(cells[k], "text"));
  3255. }
  3256. }
  3257. StringSelection sel = new StringSelection(sb.toString());
  3258. Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, this);
  3259. }
  3260. public void showAllTermDoc(Object fText) {
  3261. Term t = (Term) getProperty(fText, "term");
  3262. if (t == null) return;
  3263. if (ir == null) {
  3264. showStatus("MSG_NOINDEX");
  3265. return;
  3266. }
  3267. Object tabpane = find("maintpane");
  3268. setInteger(tabpane, "selected", 2);
  3269. Object qField = find("qField");
  3270. setString(qField, "text", t.field() + ":" + t.text());
  3271. Object qFieldParsed = find("qFieldParsed");
  3272. Object ckScoreRes = find("ckScoreRes");
  3273. Object ckOrderRes = find("ckOrderRes");
  3274. Object cntRepeat = find("cntRepeat");
  3275. final boolean scoreRes = getBoolean(ckScoreRes, "selected");
  3276. final boolean orderRes = getBoolean(ckOrderRes, "selected");
  3277. final int repeat = Integer.parseInt(getString(cntRepeat, "text"));
  3278. final Query q = new TermQuery(t);
  3279. setString(qFieldParsed, "text", q.toString());
  3280. SlowThread st = new SlowThread(this) {
  3281. public void execute() {
  3282. IndexSearcher is = null;
  3283. try {
  3284. is = new IndexSearcher(ir);
  3285. Object sTable = find("sTable");
  3286. removeAll(sTable);
  3287. AllHitsCollector ahc = new AllHitsCollector(orderRes, scoreRes);
  3288. _search(q, is, ahc, sTable, repeat);
  3289. } catch (Exception e) {
  3290. e.printStackTrace();
  3291. errorMsg(e.getMessage());
  3292. } finally {
  3293. if (is != null) try {
  3294. is.close();
  3295. } catch (Exception e1) {}
  3296. ;
  3297. }
  3298. }
  3299. };
  3300. if (slowAccess) {
  3301. st.start();
  3302. } else {
  3303. st.execute();
  3304. }
  3305. }
  3306. public Analyzer createAnalyzer(Object srchOpts) {
  3307. Analyzer res = null;
  3308. String sAType = getString(find(srchOpts, "cbType"), "text");
  3309. if (sAType.trim().equals("")) {
  3310. sAType = "org.apache.lucene.analysis.standard.StandardAnalyzer";
  3311. setString(find("cbType"), "text", sAType);
  3312. }
  3313. String arg = getString(find(srchOpts, "snoName"), "text");
  3314. if (arg == null) arg = "";
  3315. try {
  3316. Constructor zeroArg = null, zeroArgV = null, oneArg = null, oneArgV = null;
  3317. try {
  3318. zeroArgV = Class.forName(sAType).getConstructor(new Class[]{Version.class});
  3319. } catch (NoSuchMethodException e) {
  3320. zeroArgV = null;
  3321. try {
  3322. zeroArg = Class.forName(sAType).getConstructor(new Class[0]);
  3323. } catch (NoSuchMethodException e1) {
  3324. zeroArg = null;
  3325. }
  3326. }
  3327. try {
  3328. oneArgV = Class.forName(sAType).getConstructor(new Class[]{Version.class, String.class});
  3329. } catch (NoSuchMethodException e) {
  3330. oneArgV = null;
  3331. try {
  3332. oneArg = Class.forName(sAType).getConstructor(new Class[]{String.class});
  3333. } catch (NoSuchMethodException e1) {
  3334. oneArg = null;
  3335. }
  3336. }
  3337. if (arg.length() == 0) {
  3338. if (zeroArgV != null) {
  3339. res = (Analyzer)zeroArgV.newInstance(Version.LUCENE_CURRENT);
  3340. } else if (zeroArg != null) {
  3341. res = (Analyzer)zeroArg.newInstance();
  3342. } else if (oneArgV != null) {
  3343. res = (Analyzer)oneArgV.newInstance(new Object[]{Version.LUCENE_CURRENT, arg});
  3344. } else if (oneArg != null) {
  3345. res = (Analyzer)oneArg.newInstance(new Object[]{arg});
  3346. } else {
  3347. throw new Exception("Must have a zero-arg or (Version) or (Version, String) constructor");
  3348. }
  3349. } else {
  3350. if (oneArgV != null) {
  3351. res = (Analyzer)oneArgV.newInstance(new Object[]{Version.LUCENE_CURRENT, arg});
  3352. } else if (oneArg != null) {
  3353. res = (Analyzer)oneArg.newInstance(new Object[]{arg});
  3354. } else if (zeroArgV != null) {
  3355. res = (Analyzer)zeroArgV.newInstance(new Object[]{Version.LUCENE_CURRENT});
  3356. } else if (zeroArg != null) {
  3357. res = (Analyzer)zeroArg.newInstance(new Object[0]);
  3358. } else {
  3359. throw new Exception("Must have a zero-arg or (String) constructor");
  3360. }
  3361. }
  3362. } catch (Exception e) {
  3363. e.printStackTrace();
  3364. errorMsg("Analyzer '" + sAType + "' error: " + e.getMessage() + ". Using StandardAnalyzer.");
  3365. res = stdAnalyzer;
  3366. }
  3367. Prefs.setProperty(Prefs.P_ANALYZER, res.getClass().getName());
  3368. return res;
  3369. }
  3370. protected String getDefaultField(Object srchOptTabs) {
  3371. String defField = getString(find(srchOptTabs, "defFld"), "text");
  3372. if (defField == null || defField.trim().equals("")) {
  3373. if (ir != null) {
  3374. defField = idxFields[0];
  3375. setString(find(srchOptTabs, "defFld"), "text", defField);
  3376. } else {
  3377. defField = "DEFAULT";
  3378. }
  3379. }
  3380. return defField;
  3381. }
  3382. /**
  3383. * Create a Query instance that corresponds to values selected in the UI,
  3384. * such as analyzer class name and arguments, and default field.
  3385. * @return
  3386. */
  3387. public Query createQuery(String queryString) throws Exception {
  3388. Object srchOpts = find("srchOptTabs");
  3389. analyzer = createAnalyzer(srchOpts);
  3390. String defField = getDefaultField(srchOpts);
  3391. QueryParser qp = new QueryParser(Version.LUCENE_CURRENT, defField, analyzer);
  3392. Object ckXmlParser = find(srchOpts, "ckXmlParser");
  3393. Object ckWild = find(srchOpts, "ckWild");
  3394. Object ckPosIncr = find(srchOpts, "ckPosIncr");
  3395. Object ckLoExp = find(srchOpts, "ckLoExp");
  3396. Object cbDateRes = find(srchOpts, "cbDateRes");
  3397. DateTools.Resolution resolution = Util.getResolution(getString(cbDateRes, "text"));
  3398. Object cbOp = find(srchOpts, "cbOp");
  3399. Object bqMaxCount = find(srchOpts, "bqMaxCount");
  3400. int maxCount = 1024;
  3401. try {
  3402. maxCount = Integer.parseInt(getString(bqMaxCount, "text"));
  3403. } catch (Exception e) {
  3404. e.printStackTrace();
  3405. showStatus("Invalid BooleanQuery max clause count, using default 1024");
  3406. }
  3407. QueryParser.Operator op;
  3408. BooleanQuery.setMaxClauseCount(maxCount);
  3409. String opString = getString(cbOp, "text");
  3410. if (opString.equalsIgnoreCase("OR")) {
  3411. op = QueryParser.OR_OPERATOR;
  3412. } else {
  3413. op = QueryParser.AND_OPERATOR;
  3414. }
  3415. qp.setAllowLeadingWildcard(getBoolean(ckWild, "selected"));
  3416. qp.setEnablePositionIncrements(getBoolean(ckPosIncr, "selected"));
  3417. qp.setLowercaseExpandedTerms(getBoolean(ckLoExp, "selected"));
  3418. qp.setDateResolution(resolution);
  3419. qp.setDefaultOperator(op);
  3420. if (getBoolean(ckXmlParser, "selected")) {
  3421. CoreParser cp = createParser(defField,analyzer);
  3422. Query q = cp.parse(new ByteArrayInputStream(queryString.getBytes("UTF-8")));
  3423. return q;
  3424. } else {
  3425. return qp.parse(queryString);
  3426. }
  3427. }
  3428. private CoreParser createParser(String defaultField, Analyzer analyzer ) throws Exception
  3429. {
  3430. if(xmlQueryParserFactoryClassName==null)
  3431. {
  3432. //Use the default
  3433. return new CorePlusExtensionsParser(defaultField,analyzer);
  3434. }
  3435. //Use a user-defined parser (classname passed in -xmlQueryParserFactory command-line parameter
  3436. XmlQueryParserFactory parserFactory=(XmlQueryParserFactory) Class.forName(xmlQueryParserFactoryClassName).newInstance();
  3437. return parserFactory.createParser(defaultField,analyzer);
  3438. }
  3439. public Similarity createSimilarity(Object srchOpts) {
  3440. Object ckSimDef = find(srchOpts, "ckSimDef");
  3441. Object ckSimSweet = find(srchOpts, "ckSimSweet");
  3442. Object ckSimOther = find(srchOpts, "ckSimOther");
  3443. Object simClass = find(srchOpts, "simClass");
  3444. Object ckSimCust = find(srchOpts, "ckSimCust");
  3445. if (getBoolean(ckSimDef, "selected")) {
  3446. return new DefaultSimilarity();
  3447. } else if (getBoolean(ckSimSweet, "selected")) {
  3448. return new SweetSpotSimilarity();
  3449. } else if (getBoolean(ckSimOther, "selected")) {
  3450. try {
  3451. Class clazz = Class.forName(getString(simClass, "text"));
  3452. if (Similarity.class.isAssignableFrom(clazz)) {
  3453. Similarity sim = (Similarity)clazz.newInstance();
  3454. return sim;
  3455. } else {
  3456. throw new Exception("Not a subclass of Similarity: " + clazz.getName());
  3457. }
  3458. } catch (Exception e) {
  3459. e.printStackTrace();
  3460. showStatus("ERROR: invalid Similarity, using default");
  3461. setBoolean(ckSimDef, "selected", true);
  3462. setBoolean(ckSimOther, "selected", false);
  3463. return new DefaultSimilarity();
  3464. }
  3465. } else if (getBoolean(ckSimCust, "selected")) {
  3466. return similarity;
  3467. } else {
  3468. return new DefaultSimilarity();
  3469. }
  3470. }
  3471. public AccessibleHitCollector createCollector(Object srchOpts) throws Exception {
  3472. Object ckNormRes = find(srchOpts, "ckNormRes");
  3473. Object ckAllRes = find(srchOpts, "ckAllRes");
  3474. Object ckLimRes = find(srchOpts, "ckLimRes");
  3475. Object ckLimTime = find(srchOpts, "ckLimTime");
  3476. Object limTime = find(srchOpts, "limTime");
  3477. Object ckLimCount = find(srchOpts, "ckLimCount");
  3478. Object limCount = find(srchOpts, "limCount");
  3479. Object ckScoreRes = find(srchOpts, "ckScoreRes");
  3480. Object ckOrderRes = find(srchOpts, "ckOrderRes");
  3481. boolean scoreRes = getBoolean(ckScoreRes, "selected");
  3482. boolean orderRes = getBoolean(ckOrderRes, "selected");
  3483. Collector hc = null;
  3484. if (getBoolean(ckNormRes, "selected")) {
  3485. return new AccessibleTopHitCollector(1000, orderRes, scoreRes);
  3486. } else if (getBoolean(ckAllRes, "selected")) {
  3487. return new AllHitsCollector(orderRes, scoreRes);
  3488. } else if (getBoolean(ckLimRes, "selected")) {
  3489. // figure out the type
  3490. if (getBoolean(ckLimCount, "selected")) {
  3491. int lim = Integer.parseInt(getString(limCount, "text"));
  3492. return new CountLimitedHitCollector(lim, orderRes, scoreRes);
  3493. } else if (getBoolean(ckLimTime, "selected")) {
  3494. int lim = Integer.parseInt(getString(limTime, "text"));
  3495. return new IntervalLimitedCollector(lim, orderRes, scoreRes);
  3496. } else {
  3497. throw new Exception("Unknown LimitedHitCollector type");
  3498. }
  3499. } else {
  3500. throw new Exception("Unknown HitCollector type");
  3501. }
  3502. }
  3503. public void explainStructure(Object qTabs) {
  3504. Object qField = find("qField");
  3505. String queryS = getString(qField, "text");
  3506. if (queryS.trim().equals("")) {
  3507. showStatus("Empty query");
  3508. return;
  3509. }
  3510. showParsed();
  3511. int idx = getSelectedIndex(qTabs);
  3512. Query q = null;
  3513. if (idx == 0) {
  3514. q = (Query)getProperty(qField, "qParsed");
  3515. } else {
  3516. q = (Query)getProperty(qField, "qRewritten");
  3517. }
  3518. Object dialog = addComponent(this, "/xml/qexplain.xml", null, null);
  3519. Object tree = find(dialog, "qTree");
  3520. _explainStructure(tree, q);
  3521. }
  3522. private void _explainStructure(Object parent, Query q) {
  3523. String clazz = q.getClass().getSimpleName();
  3524. float boost = q.getBoost();
  3525. Object n = create("node");
  3526. add(parent, n);
  3527. String msg = clazz;
  3528. if (boost != 1.0f) {
  3529. msg += ": boost=" + df.format(boost);
  3530. }
  3531. setFont(n, getFont().deriveFont(Font.BOLD));
  3532. setString(n, "text", msg);
  3533. if (clazz.equals("TermQuery")) {
  3534. Object n1 = create("node");
  3535. Term t = ((TermQuery)q).getTerm();
  3536. setString(n1, "text", "Term: field='" + t.field() + "' text='" + t.text() + "'");
  3537. add(n, n1);
  3538. } else if (clazz.equals("BooleanQuery")) {
  3539. BooleanQuery bq = (BooleanQuery)q;
  3540. BooleanClause[] clauses = bq.getClauses();
  3541. int max = bq.getMaxClauseCount();
  3542. Object n1 = create("node");
  3543. String descr = "clauses=" + clauses.length +
  3544. ", maxClauses=" + max;
  3545. if (bq.isCoordDisabled()) {
  3546. descr += ", coord=false";
  3547. }
  3548. if (bq.getMinimumNumberShouldMatch() > 0) {
  3549. descr += ", minShouldMatch=" + bq.getMinimumNumberShouldMatch();
  3550. }
  3551. setString(n1, "text", descr);
  3552. add(n, n1);
  3553. for (int i = 0; i < clauses.length; i++) {
  3554. n1 = create("node");
  3555. String occur;
  3556. Occur occ = clauses[i].getOccur();
  3557. if (occ.equals(Occur.MUST)) {
  3558. occur = "MUST";
  3559. } else if (occ.equals(Occur.MUST_NOT)) {
  3560. occur = "MUST_NOT";
  3561. } else if (occ.equals(Occur.SHOULD)) {
  3562. occur = "SHOULD";
  3563. } else {
  3564. occur = occ.toString();
  3565. }
  3566. setString(n1, "text", "Clause " + i + ": " + occur);
  3567. add(n, n1);
  3568. _explainStructure(n1, clauses[i].getQuery());
  3569. }
  3570. } else if (clazz.equals("PrefixQuery")) {
  3571. Object n1 = create("node");
  3572. Term t = ((PrefixQuery)q).getPrefix();
  3573. setString(n1, "text", "Prefix: field='" + t.field() + "' text='" + t.text() + "'");
  3574. add(n, n1);
  3575. } else if (clazz.equals("PhraseQuery")) {
  3576. PhraseQuery pq = (PhraseQuery)q;
  3577. setString(n, "text", getString(n, "text") + ", slop=" + pq.getSlop());
  3578. int[] pos = pq.getPositions();
  3579. Term[] terms = pq.getTerms();
  3580. Object n1 = create("node");
  3581. StringBuffer sb = new StringBuffer("pos: [");
  3582. for (int i = 0; i < pos.length; i++) {
  3583. if (i > 0) sb.append(',');
  3584. sb.append("" + pos[i]);
  3585. }
  3586. sb.append("]");
  3587. setString(n1, "text", sb.toString());
  3588. add(n, n1);
  3589. for (int i = 0; i < terms.length; i++) {
  3590. n1 = create("node");
  3591. setString(n1, "text", "Term " + i + ": field='" + terms[i].field() +
  3592. "' text='" + terms[i].text() + "'");
  3593. add(n, n1);
  3594. }
  3595. } else if (clazz.equals("MultiPhraseQuery")) {
  3596. MultiPhraseQuery pq = (MultiPhraseQuery)q;
  3597. setString(n, "text", getString(n, "text") + ", slop=" + pq.getSlop());
  3598. int[] pos = pq.getPositions();
  3599. Object n1 = create("node");
  3600. StringBuffer sb = new StringBuffer("pos: [");
  3601. for (int i = 0; i < pos.length; i++) {
  3602. if (i > 0) sb.append(',');
  3603. sb.append("" + pos[i]);
  3604. }
  3605. sb.append("]");
  3606. setString(n1, "text", sb.toString());
  3607. add(n, n1);
  3608. n1 = create("node");
  3609. System.err.println("MultiPhraseQuery is missing the public getTermArrays() :-(");
  3610. setString(n1, "text", "toString: " + pq.toString());
  3611. add(n, n1);
  3612. } else if (clazz.equals("FuzzyQuery")) {
  3613. FuzzyQuery fq = (FuzzyQuery)q;
  3614. Object n1 = create("node");
  3615. setString(n1, "text", "prefixLen=" + fq.getPrefixLength() +
  3616. ", minSimilarity=" + df.format(fq.getMinSimilarity()));
  3617. add(n, n1);
  3618. // do some tricks with reflection...
  3619. try {
  3620. Method m = FuzzyQuery.class.getDeclaredMethod("getEnum", new Class[]{IndexReader.class});
  3621. m.setAccessible(true);
  3622. FilteredTermEnum fte = (FilteredTermEnum)m.invoke(fq, new Object[]{ir});
  3623. n1 = create("node");
  3624. String clz = fte.getClass().getName();
  3625. setString(n1, "text", clz + ": diff=" + df.format(fte.difference()));
  3626. add(n, n1);
  3627. do {
  3628. n1 = create("node");
  3629. Term t = fte.term();
  3630. setString(n1, "text", "Term: field='" + t.field() +
  3631. "' text='" + t.text() + "', docFreq=" + fte.docFreq());
  3632. add(n, n1);
  3633. } while (fte.next());
  3634. } catch (Exception e) {
  3635. n1 = create("node");
  3636. setString(n1, "text", "FilteredTermEnum: Exception " + e.getMessage());
  3637. add(n, n1);
  3638. }
  3639. } else if (clazz.equals("WildcardQuery")) {
  3640. WildcardQuery wq = (WildcardQuery)q;
  3641. Term t = wq.getTerm();
  3642. setString(n, "text", getString(n, "text") + ", term=" + t);
  3643. // do some tricks with reflection...
  3644. try {
  3645. Method m = WildcardQuery.class.getDeclaredMethod("getEnum", new Class[]{IndexReader.class});
  3646. m.setAccessible(true);
  3647. FilteredTermEnum fte = (FilteredTermEnum)m.invoke(wq, new Object[]{ir});
  3648. Object n1 = create("node");
  3649. String clz = fte.getClass().getName();
  3650. setString(n1, "text", clz + ": diff=" + df.format(fte.difference()));
  3651. add(n, n1);
  3652. do {
  3653. n1 = create("node");
  3654. t = fte.term();
  3655. if (t == null) continue;
  3656. setString(n1, "text", "Term: field='" + t.field() +
  3657. "' text='" + t.text() + "', docFreq=" + fte.docFreq());
  3658. add(n, n1);
  3659. } while (fte.next());
  3660. } catch (Exception e) {
  3661. Object n1 = create("node");
  3662. setString(n1, "text", "FilteredTermEnum: Exception " + e.getMessage());
  3663. add(n, n1);
  3664. }
  3665. } else if (clazz.equals("TermRangeQuery")) {
  3666. TermRangeQuery rq = (TermRangeQuery)q;
  3667. setString(n, "text", getString(n, "text") + ", inclLower=" + rq.includesLower() + ", inclUpper=" + rq.includesUpper());
  3668. Object n1 = create("node");
  3669. setString(n1, "text", "lowerTerm=" + rq.getField() + ":" + rq.getLowerTerm() + "'");
  3670. add(n, n1);
  3671. n1 = create("node");
  3672. setString(n1, "text", "upperTerm=" + rq.getField() + ":" + rq.getUpperTerm() + "'");
  3673. add(n, n1);
  3674. } else if (q instanceof FilteredQuery) {
  3675. FilteredQuery fq = (FilteredQuery)q;
  3676. Object n1 = create("node");
  3677. setString(n1, "text", "Filter: " + fq.getFilter().toString());
  3678. add(n, n1);
  3679. _explainStructure(n, fq.getQuery());
  3680. } else if (q instanceof SpanQuery) {
  3681. SpanQuery sq = (SpanQuery)q;
  3682. Class sqlass = sq.getClass();
  3683. setString(n, "text", getString(n, "text") + ", field=" + sq.getField());
  3684. if (sqlass == SpanOrQuery.class) {
  3685. SpanOrQuery soq = (SpanOrQuery)sq;
  3686. setString(n, "text", getString(n, "text") + ", " + soq.getClauses().length + " clauses");
  3687. for (SpanQuery sq1 : soq.getClauses()) {
  3688. _explainStructure(n, sq1);
  3689. }
  3690. } else if (sqlass == SpanFirstQuery.class) {
  3691. SpanFirstQuery sfq = (SpanFirstQuery)sq;
  3692. setString(n, "text", getString(n, "text") + ", end=" + sfq.getEnd() + ", match:");
  3693. _explainStructure(n, sfq.getMatch());
  3694. } else if (q instanceof SpanNearQuery) { // catch also known subclasses
  3695. SpanNearQuery snq = (SpanNearQuery)sq;
  3696. setString(n, "text", getString(n, "text") + ", slop=" + snq.getSlop());
  3697. if (snq instanceof PayloadNearQuery) {
  3698. try {
  3699. java.lang.reflect.Field function = PayloadNearQuery.class.getDeclaredField("function");
  3700. function.setAccessible(true);
  3701. Object func = function.get(snq);
  3702. setString(n, "text", getString(n, "text") + ", func=" + func.getClass().getSimpleName());
  3703. } catch (Exception e) {
  3704. e.printStackTrace();
  3705. }
  3706. }
  3707. for (SpanQuery sq1 : snq.getClauses()) {
  3708. _explainStructure(n, sq1);
  3709. }
  3710. } else if (sqlass == SpanNotQuery.class) {
  3711. SpanNotQuery snq = (SpanNotQuery)sq;
  3712. Object n1 = create("node");
  3713. add(n, n1);
  3714. setString(n1, "text", "Include:");
  3715. _explainStructure(n1, snq.getInclude());
  3716. n1 = create("node");
  3717. add(n, n1);
  3718. setString(n1, "text", "Exclude:");
  3719. _explainStructure(n1, snq.getExclude());
  3720. } else if (q instanceof SpanTermQuery) {
  3721. SpanTermQuery stq = (SpanTermQuery)sq;
  3722. setString(n, "text", getString(n, "text") + ", term=" + stq.getTerm());
  3723. if (stq instanceof PayloadTermQuery) {
  3724. try {
  3725. java.lang.reflect.Field function = PayloadTermQuery.class.getDeclaredField("function");
  3726. function.setAccessible(true);
  3727. Object func = function.get(stq);
  3728. setString(n, "text", getString(n, "text") + ", func=" + func.getClass().getSimpleName());
  3729. } catch (Exception e) {
  3730. e.printStackTrace();
  3731. }
  3732. }
  3733. } else {
  3734. String defField = getDefaultField(find("srchOptTabs"));
  3735. setString(n, "text", "class=" + q.getClass().getName() + ", " + getString(n, "text") + ", toString=" + q.toString(defField));
  3736. HashSet<Term> terms = new HashSet<Term>();
  3737. sq.extractTerms(terms);
  3738. Object n1 = null;
  3739. if (terms != null) {
  3740. n1 = create("node");
  3741. setString(n1, "text", "Matched terms (" + terms.size() + "):");
  3742. add(n, n1);
  3743. Iterator<Term> it = terms.iterator();
  3744. while(it.hasNext()) {
  3745. Object n2 = create("node");
  3746. Term t = it.next();
  3747. setString(n2, "text", "field='" + t.field() + "' text='" + t.text() + "'");
  3748. add(n1, n2);
  3749. }
  3750. } else {
  3751. n1 = create("node");
  3752. setString(n1, "text", "<no terms matched>");
  3753. add(n, n1);
  3754. }
  3755. }
  3756. if (ir != null) {
  3757. Object n1 = null;
  3758. try {
  3759. Spans spans = sq.getSpans(ir);
  3760. if (spans != null) {
  3761. n1 = create("node");
  3762. int cnt = 0;
  3763. while (spans.next()) {
  3764. Object n2 = create("node");
  3765. setString(n2, "text", "doc=" + spans.doc() +
  3766. ", start=" + spans.start() + ", end=" + spans.end());
  3767. add(n1, n2);
  3768. cnt++;
  3769. }
  3770. if (cnt > 0) {
  3771. add(n, n1);
  3772. setString(n1, "text", "Spans (" + cnt + "):");
  3773. setBoolean(n1, "expanded", false);
  3774. }
  3775. }
  3776. } catch (Exception e) {
  3777. e.printStackTrace();
  3778. n1 = create("node");
  3779. setString(n1, "text", "Spans Exception: " + e.getMessage());
  3780. add(n, n1);
  3781. }
  3782. }
  3783. } else {
  3784. Object n1 = create("node");
  3785. String defField = getDefaultField(find("srchOptTabs"));
  3786. setString(n1, "text", q.getClass().getName() + ": " + q.toString(defField));
  3787. add(n, n1);
  3788. }
  3789. }
  3790. /**
  3791. * Update the parsed and rewritten query views.
  3792. *
  3793. */
  3794. public void showParsed() {
  3795. Object qField = find("qField");
  3796. Object qFieldParsed = find("qFieldParsed");
  3797. Object qFieldRewritten = find("qFieldRewritten");
  3798. String queryS = getString(qField, "text");
  3799. if (queryS.trim().equals("")) {
  3800. setString(qFieldParsed, "text", "<empty query>");
  3801. setBoolean(qFieldParsed, "enabled", false);
  3802. return;
  3803. } else {
  3804. setBoolean(qFieldParsed, "enabled", true);
  3805. }
  3806. try {
  3807. Query q = createQuery(queryS);
  3808. setString(qFieldParsed, "text", q.toString());
  3809. putProperty(qField, "qParsed", q);
  3810. q = q.rewrite(ir);
  3811. setString(qFieldRewritten, "text", q.toString());
  3812. putProperty(qField, "qRewritten", q);
  3813. } catch (Throwable t) {
  3814. setString(qFieldParsed, "text", t.getMessage());
  3815. setString(qFieldRewritten, "text", t.getMessage());
  3816. }
  3817. }
  3818. /**
  3819. * Perform a search. NOTE: this method is usually invoked from the GUI.
  3820. * @param qField Thinlet widget containing the query
  3821. */
  3822. public void search(Object qField) {
  3823. if (ir == null) {
  3824. showStatus(MSG_NOINDEX);
  3825. return;
  3826. }
  3827. String queryS = getString(qField, "text");
  3828. if (queryS.trim().equals("")) {
  3829. showStatus("FAILED: Empty query.");
  3830. return;
  3831. }
  3832. Object srchOpts = find("srchOptTabs");
  3833. // query parser opts
  3834. Similarity sim = createSimilarity(srchOpts);
  3835. AccessibleHitCollector col;
  3836. try {
  3837. col = createCollector(srchOpts);
  3838. } catch (Throwable t) {
  3839. errorMsg("ERROR creating Collector: " + t.getMessage());
  3840. return;
  3841. }
  3842. Object sTable = find("sTable");
  3843. Object cntRepeat = find("cntRepeat");
  3844. int repeat = Integer.parseInt(getString(cntRepeat, "text"));
  3845. removeAll(sTable);
  3846. Query q = null;
  3847. try {
  3848. q = createQuery(queryS);
  3849. is.setSimilarity(sim);
  3850. showParsed();
  3851. _search(q, is, col, sTable, repeat);
  3852. } catch (Throwable e) {
  3853. e.printStackTrace();
  3854. errorMsg(e.getMessage());
  3855. }
  3856. }
  3857. int resStart = 0;
  3858. int resCount = 20;
  3859. LimitedException le = null;
  3860. private void _search(final Query q, final IndexSearcher is,
  3861. AccessibleHitCollector hc, final Object sTable, final int repeat) throws Exception {
  3862. if (hc == null) {
  3863. hc = new AccessibleTopHitCollector(1000, true, true);
  3864. }
  3865. final AccessibleHitCollector collector = hc;
  3866. le = null;
  3867. SlowThread t = new SlowThread(this) {
  3868. public void execute() {
  3869. long startTime = System.nanoTime();
  3870. for (int i = 0; i < repeat; i++) {
  3871. if (i > 0) {
  3872. collector.reset();
  3873. }
  3874. try {
  3875. is.search(q, collector);
  3876. } catch (LimitedException e) {
  3877. le = e;
  3878. } catch (Throwable th) {
  3879. th.printStackTrace();
  3880. errorMsg("ERROR searching: " + th.toString());
  3881. return;
  3882. }
  3883. }
  3884. long endTime = System.nanoTime();
  3885. long delta = (endTime - startTime) / 1000 / repeat;
  3886. String msg;
  3887. if (delta > 100000) {
  3888. msg = delta / 1000 + " ms";
  3889. } else {
  3890. msg = delta + " us";
  3891. }
  3892. if (repeat > 1) {
  3893. msg += " (avg of " + repeat + " runs)";
  3894. }
  3895. showSearchStatus(msg);
  3896. Object bsPrev = find("bsPrev");
  3897. Object bsNext = find("bsNext");
  3898. setBoolean(bsNext, "enabled", false);
  3899. setBoolean(bsPrev, "enabled", false);
  3900. int resNum = collector.getTotalHits();
  3901. if (resNum == 0) {
  3902. Object row = create("row");
  3903. Object cell = create("cell");
  3904. add(sTable, row);
  3905. add(row, cell);
  3906. cell = create("cell");
  3907. add(row, cell);
  3908. cell = create("cell");
  3909. setString(cell, "text", "No Results");
  3910. setBoolean(cell, "enabled", false);
  3911. add(row, cell);
  3912. setString(find("resNum"), "text", "0");
  3913. return;
  3914. }
  3915. if (resNum > resCount) {
  3916. setBoolean(bsNext, "enabled", true);
  3917. }
  3918. setString(find("resNum"), "text", String.valueOf(resNum));
  3919. putProperty(sTable, "resNum", new Integer(resNum));
  3920. putProperty(sTable, "query", q);
  3921. putProperty(sTable, "hc", collector);
  3922. if (le != null) {
  3923. putProperty(sTable, "le", le);
  3924. }
  3925. resStart = 0;
  3926. _showSearchPage(sTable);
  3927. }
  3928. };
  3929. if (slowAccess) {
  3930. t.start();
  3931. } else {
  3932. t.execute();
  3933. }
  3934. }
  3935. public void prevPage(Object sTable) {
  3936. int resNum = ((Integer)getProperty(sTable, "resNum")).intValue();
  3937. if (resStart == 0) {
  3938. setBoolean(find("bsPrev"), "enabled", false);
  3939. return;
  3940. }
  3941. resStart -= resCount;
  3942. if (resStart < 0) resStart = 0;
  3943. if (resStart - resCount < 0)
  3944. setBoolean(find("bsPrev"), "enabled", false);
  3945. if (resStart + resCount < resNum)
  3946. setBoolean(find("bsNext"), "enabled", true);
  3947. _showSearchPage(sTable);
  3948. }
  3949. public void nextPage(Object sTable) {
  3950. int resNum = ((Integer)getProperty(sTable, "resNum")).intValue();
  3951. resStart += resCount;
  3952. if (resStart >= resNum) {
  3953. resStart -= resCount;
  3954. setBoolean(find("bsNext"), "enabled", false);
  3955. return;
  3956. }
  3957. setBoolean(find("bsPrev"), "enabled", true);
  3958. if (resStart + resCount >= resNum) {
  3959. setBoolean(find("bsNext"), "enabled", false);
  3960. }
  3961. _showSearchPage(sTable);
  3962. }
  3963. private void _showSearchPage(final Object sTable) {
  3964. SlowThread t = new SlowThread(this) {
  3965. public void execute() {
  3966. try {
  3967. removeAll(sTable);
  3968. AccessibleHitCollector hc = (AccessibleHitCollector)getProperty(sTable, "hc");
  3969. int resNum = hc.getTotalHits();
  3970. int max = Math.min(resNum, resStart + resCount);
  3971. Object posLabel = find("resPos");
  3972. setString(posLabel, "text", resStart + "-" + (max - 1));
  3973. for (int i = resStart; i < max; i++) {
  3974. int docid = hc.getDocId(i);
  3975. float score = hc.getScore(i);
  3976. _createResultRow(i, docid, score, sTable);
  3977. }
  3978. } catch (Exception e) {
  3979. e.printStackTrace();
  3980. showStatus(e.getMessage());
  3981. }
  3982. }
  3983. };
  3984. if (slowAccess) {
  3985. t.start();
  3986. } else {
  3987. t.execute();
  3988. }
  3989. }
  3990. private void _createResultRow(int pos, int docId, float score, Object sTable) throws IOException {
  3991. Object row = create("row");
  3992. Object cell = create("cell");
  3993. add(sTable, row);
  3994. setString(cell, "text", String.valueOf(pos));
  3995. setChoice(cell, "alignment", "right");
  3996. add(row, cell);
  3997. cell = create("cell");
  3998. setString(cell, "text", String.valueOf(df.format(score)));
  3999. setChoice(cell, "alignment", "right");
  4000. add(row, cell);
  4001. cell = create("cell");
  4002. setString(cell, "text", String.valueOf(docId));
  4003. setChoice(cell, "alignment", "right");
  4004. add(row, cell);
  4005. Document doc = ir.document(docId);
  4006. putProperty(row, "docid", new Integer(docId));
  4007. StringBuffer vals = new StringBuffer();
  4008. for (int j = 0; j < idxFields.length; j++) {
  4009. cell = create("cell");
  4010. Decoder dec = decoders.get(idxFields[j]);
  4011. if (dec == null) dec = defDecoder;
  4012. String[] values = doc.getValues(idxFields[j]);
  4013. vals.setLength(0);
  4014. boolean decodeErr = false;
  4015. if (values != null) for (int k = 0; k < values.length; k++) {
  4016. if (k > 0) vals.append(' ');
  4017. String v;
  4018. try {
  4019. v = dec.decodeStored(idxFields[j], values[k]);
  4020. } catch (Throwable e) {
  4021. v = values[k];
  4022. decodeErr = true;
  4023. }
  4024. vals.append(Util.escape(v));
  4025. }
  4026. setString(cell, "text", vals.toString());
  4027. if (decodeErr) {
  4028. setColor(cell, "foreground", Color.RED);
  4029. }
  4030. add(row, cell);
  4031. }
  4032. }
  4033. /**
  4034. * Pop up a modal dialog explaining the selected result.
  4035. * @param sTable Thinlet table widget containing selected search result.
  4036. */
  4037. public void explainResult(Object sTable) {
  4038. Object row = getSelectedItem(sTable);
  4039. if (row == null) return;
  4040. final Integer docid = (Integer) getProperty(row, "docid");
  4041. if (docid == null) return;
  4042. if (ir == null) {
  4043. showStatus(MSG_NOINDEX);
  4044. return;
  4045. }
  4046. final Query q = (Query) getProperty(sTable, "query");
  4047. if (q == null) return;
  4048. Thread t = new Thread() {
  4049. public void run() {
  4050. try {
  4051. IndexSearcher is = new IndexSearcher(ir);
  4052. is.setSimilarity(createSimilarity(find("srchOptTabs")));
  4053. Explanation expl = is.explain(q, docid.intValue());
  4054. Object dialog = addComponent(null, "/xml/explain.xml", null, null);
  4055. Object eTree = find(dialog, "eTree");
  4056. addNode(eTree, expl);
  4057. //setBoolean(eTree, "expand", true);
  4058. add(dialog);
  4059. } catch (Exception e) {
  4060. e.printStackTrace();
  4061. errorMsg(e.getMessage());
  4062. }
  4063. }
  4064. };
  4065. if (slowAccess) {
  4066. t.start();
  4067. } else {
  4068. t.run();
  4069. }
  4070. }
  4071. private DecimalFormat df = new DecimalFormat("0.0000");
  4072. private String xmlQueryParserFactoryClassName=CorePlusExtensionsParserFactory.class.getName();
  4073. private void addNode(Object tree, Explanation expl) {
  4074. Object node = create("node");
  4075. setString(node, "text", df.format((double) expl.getValue()) + " " + expl.getDescription());
  4076. add(tree, node);
  4077. if (getClass(tree) == "tree") {
  4078. setFont(node, getFont().deriveFont(Font.BOLD));
  4079. }
  4080. Explanation[] kids = expl.getDetails();
  4081. if (kids != null && kids.length > 0) {
  4082. for (int i = 0; i < kids.length; i++) {
  4083. addNode(node, kids[i]);
  4084. }
  4085. }
  4086. }
  4087. public void gotoDoc(Object sTable) {
  4088. Object row = getSelectedItem(sTable);
  4089. if (row == null) return;
  4090. final Integer docid = (Integer) getProperty(row, "docid");
  4091. if (docid == null) return;
  4092. if (ir == null) {
  4093. showStatus(MSG_NOINDEX);
  4094. return;
  4095. }
  4096. SlowThread st = new SlowThread(this) {
  4097. public void execute() {
  4098. Document doc = null;
  4099. try {
  4100. doc = ir.document(docid.intValue());
  4101. } catch (Exception e) {
  4102. e.printStackTrace();
  4103. showStatus(e.getMessage());
  4104. return;
  4105. }
  4106. _showDocFields(docid.intValue(), doc);
  4107. Object tabpane = find("maintpane");
  4108. setInteger(tabpane, "selected", 1);
  4109. repaint();
  4110. }
  4111. };
  4112. if (slowAccess) {
  4113. st.start();
  4114. } else {
  4115. st.execute();
  4116. }
  4117. }
  4118. private void _showTermDoc(Object fText, final TermPositions td) {
  4119. if (ir == null) {
  4120. showStatus(MSG_NOINDEX);
  4121. return;
  4122. }
  4123. SlowThread st = new SlowThread(this) {
  4124. public void execute() {
  4125. try {
  4126. Document doc = ir.document(td.doc());
  4127. setString(find("docNum"), "text", String.valueOf(td.doc()));
  4128. setString(find("tFreq"), "text", String.valueOf(td.freq()));
  4129. _showDocFields(td.doc(), doc);
  4130. } catch (Exception e) {
  4131. e.printStackTrace();
  4132. showStatus(e.getMessage());
  4133. }
  4134. }
  4135. };
  4136. if (slowAccess) {
  4137. st.start();
  4138. } else {
  4139. st.execute();
  4140. }
  4141. }
  4142. public void deleteTermDoc(Object fText) {
  4143. Term t = (Term) getProperty(fText, "term");
  4144. if (t == null) return;
  4145. if (ir == null) {
  4146. showStatus(MSG_NOINDEX);
  4147. return;
  4148. }
  4149. if (readOnly) {
  4150. showStatus(MSG_READONLY);
  4151. return;
  4152. }
  4153. try {
  4154. showNextTerm(find("fCombo"), fText);
  4155. ir.deleteDocuments(t);
  4156. } catch (Exception e) {
  4157. e.printStackTrace();
  4158. showStatus(e.getMessage());
  4159. }
  4160. initOverview();
  4161. }
  4162. public void deleteDoc(Object docNum) {
  4163. int docid = 0;
  4164. if (ir == null) {
  4165. showStatus(MSG_NOINDEX);
  4166. return;
  4167. }
  4168. if (readOnly) {
  4169. showStatus(MSG_READONLY);
  4170. return;
  4171. }
  4172. try {
  4173. docid = Integer.parseInt(getString(docNum, "text"));
  4174. ir.deleteDocument(docid);
  4175. showDoc(docNum);
  4176. initOverview();
  4177. showFiles(dir, Collections.EMPTY_LIST);
  4178. showStatus("Document #" + docid + " deleted OK.");
  4179. } catch (Exception e) {
  4180. showStatus(e.getMessage());
  4181. e.printStackTrace();
  4182. }
  4183. }
  4184. public void actionDeleteDocList(Object docList) {
  4185. if (ir == null) {
  4186. showStatus(MSG_NOINDEX);
  4187. return;
  4188. }
  4189. if (readOnly) {
  4190. showStatus(MSG_READONLY);
  4191. return;
  4192. }
  4193. try {
  4194. String list = getString(docList, "text");
  4195. Ranges ranges = Ranges.parse(list);
  4196. if (ranges.cardinality() == 0) {
  4197. infoMsg("Empty list - no documents deleted.");
  4198. return;
  4199. }
  4200. long count = ranges.cardinality();
  4201. DocIdSetIterator it = ranges.iterator();
  4202. int doc;
  4203. while ((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
  4204. ir.deleteDocument(doc);
  4205. }
  4206. showDoc(find("docNum"));
  4207. initOverview();
  4208. showFiles(dir, Collections.EMPTY_LIST);
  4209. showStatus(count + " documents marked as deleted.");
  4210. } catch (Exception e) {
  4211. errorMsg("Error: " + e.toString());
  4212. e.printStackTrace();
  4213. }
  4214. }
  4215. public void deleteDocList(Object searchTable) {
  4216. Object[] rows = getSelectedItems(searchTable);
  4217. if (rows == null || rows.length == 0) return;
  4218. if (ir == null) {
  4219. showStatus(MSG_NOINDEX);
  4220. return;
  4221. }
  4222. if (readOnly) {
  4223. showStatus(MSG_READONLY);
  4224. return;
  4225. }
  4226. for (int i = 0; i < rows.length; i++) {
  4227. Integer docId = (Integer) getProperty(rows[i], "docid");
  4228. if (docId == null) continue;
  4229. try {
  4230. ir.deleteDocument(docId.intValue());
  4231. } catch (Exception e) {
  4232. continue;
  4233. }
  4234. remove(rows[i]);
  4235. }
  4236. try {
  4237. initOverview();
  4238. showFiles(dir, Collections.EMPTY_LIST);
  4239. } catch (Exception e) {
  4240. errorMsg("Error: " + e.toString());
  4241. }
  4242. }
  4243. public void actionAbout() {
  4244. Object about = addComponent(this, "/xml/about.xml", null, null);
  4245. Object lver = find(about, "lver");
  4246. setString(lver, "text", "Lucene version: " + LucenePackage.get().getImplementationVersion());
  4247. }
  4248. /**
  4249. * Pop up a modal font selection dialog.
  4250. *
  4251. */
  4252. public void actionShowFonts() {
  4253. addComponent(this, "/xml/selfont.xml", null, null);
  4254. }
  4255. /**
  4256. * Initialize the font selection dialog.
  4257. * @param selfont font selection dialog
  4258. */
  4259. public void setupSelFont(Object selfont) {
  4260. GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  4261. Font[] fonts = ge.getAllFonts();
  4262. Object cbFonts = find(selfont, "fonts");
  4263. String curfont = getFont().getFontName();
  4264. float cursize = getFont().getSize2D();
  4265. Object fsize = find(selfont, "fsize");
  4266. NumberFormat nf = NumberFormat.getNumberInstance();
  4267. nf.setMaximumFractionDigits(1);
  4268. setString(fsize, "text", nf.format(cursize));
  4269. removeAll(cbFonts);
  4270. Object def = create("choice");
  4271. setFont(def, "font", getFont().deriveFont(15.0f));
  4272. setString(def, "text", curfont + " (default)");
  4273. putProperty(def, "fnt", getFont());
  4274. add(cbFonts, def);
  4275. setInteger(cbFonts, "selected", 0);
  4276. for (int i = 0; i < fonts.length; i++) {
  4277. Object choice = create("choice");
  4278. setFont(choice, "font", fonts[i].deriveFont(15.0f));
  4279. setString(choice, "text", fonts[i].getFontName());
  4280. putProperty(choice, "fnt", fonts[i]);
  4281. add(cbFonts, choice);
  4282. if (curfont.equalsIgnoreCase(fonts[i].getFontName()))
  4283. setInteger(cbFonts, "selected", i + 1);
  4284. }
  4285. }
  4286. /**
  4287. * Show preview of the selected font.
  4288. * @param selfont font selection dialog
  4289. */
  4290. public void selectFont(Object selfont) {
  4291. Object preview = find(selfont, "fpreview");
  4292. Object cbFonts = find(selfont, "fonts");
  4293. Object fsize = find(selfont, "fsize");
  4294. Font f = (Font)getProperty(getSelectedItem(cbFonts), "fnt");
  4295. float size = getFont().getSize2D();
  4296. try {
  4297. size = Float.parseFloat(getString(fsize, "text"));
  4298. } catch (Exception e) {
  4299. e.printStackTrace();
  4300. }
  4301. f = f.deriveFont(size);
  4302. Object[] items = getItems(preview);
  4303. for (int i = 0; i < items.length; i++) {
  4304. setPreviewFont(f, items[i]);
  4305. }
  4306. }
  4307. private void setPreviewFont(Font f, Object item) {
  4308. try {
  4309. setFont(item, "font", f);
  4310. } catch (IllegalArgumentException iae) {
  4311. // shrug...
  4312. }
  4313. Object[] items = getItems(item);
  4314. for (int i = 0; i < items.length; i++) {
  4315. setPreviewFont(f, items[i]);
  4316. }
  4317. }
  4318. /**
  4319. * Set the default font in the UI.
  4320. * @param selfont font selection dialog
  4321. */
  4322. public void actionSetFont(Object selfont) {
  4323. Object cbFonts = find(selfont, "fonts");
  4324. Object fsize = find(selfont, "fsize");
  4325. Font f = (Font)getProperty(getSelectedItem(cbFonts), "fnt");
  4326. float size = getFont().getSize2D();
  4327. try {
  4328. size = Float.parseFloat(getString(fsize, "text"));
  4329. } catch (Exception e) {
  4330. e.printStackTrace();
  4331. }
  4332. f = f.deriveFont(size);
  4333. remove(selfont);
  4334. setFont(f);
  4335. courier = new Font("Courier", getFont().getStyle(), getFont().getSize());
  4336. repaint();
  4337. }
  4338. public void actionSetDecoder(Object fList, Object combo) {
  4339. Object row = getSelectedItem(fList);
  4340. if (row == null) {
  4341. return;
  4342. }
  4343. String fName = (String)getProperty(row, "fName");
  4344. Object choice = getSelectedItem(combo);
  4345. String decName = getString(choice, "name");
  4346. Decoder dec = null;
  4347. if (decName.equals("s")) {
  4348. dec = new StringDecoder();
  4349. } else if (decName.equals("b")) {
  4350. dec = new BinaryDecoder();
  4351. } else if (decName.equals("d")) {
  4352. dec = new DateDecoder();
  4353. } else if (decName.equals("nl")) {
  4354. dec = new NumLongDecoder();
  4355. } else if (decName.equals("nd")) {
  4356. dec = new NumDoubleDecoder();
  4357. } else if (decName.equals("ni")) {
  4358. dec = new NumIntDecoder();
  4359. } else if (decName.equals("nf")) {
  4360. dec = new NumFloatDecoder();
  4361. } else if (decName.equals("od")) {
  4362. dec = new OldDateFieldDecoder();
  4363. } else if (decName.equals("on")) {
  4364. dec = new OldNumberToolsDecoder();
  4365. } else {
  4366. dec = defDecoder;
  4367. }
  4368. decoders.put(fName, dec);
  4369. Object cell = getItem(row, 3);
  4370. setString(cell, "text", dec.toString());
  4371. repaint(fList);
  4372. actionTopTerms(find("nTerms"));
  4373. }
  4374. /**
  4375. * Returns current custom similarity implementation.
  4376. * @return
  4377. */
  4378. public Similarity getCustomSimilarity() {
  4379. return similarity;
  4380. }
  4381. /**
  4382. * Set the current custom similarity implementation.
  4383. * @param s
  4384. */
  4385. public void setCustomSimilarity(Similarity s) {
  4386. similarity = s;
  4387. Object cbSimCust = find("ckSimCust");
  4388. Object cbSimDef = find("ckSimDef");
  4389. Object simName = find("simName");
  4390. if (similarity != null) {
  4391. setString(simName, "text", similarity.getClass().getName());
  4392. setBoolean(cbSimCust, "enabled", true);
  4393. } else {
  4394. setString(simName, "text", "");
  4395. setBoolean(cbSimCust, "enabled", false);
  4396. setBoolean(cbSimDef, "selected", true);
  4397. setBoolean(cbSimCust, "selected", false);
  4398. }
  4399. }
  4400. /**
  4401. * Switch the view to display the SimilarityDesigner plugin, if present.
  4402. *
  4403. */
  4404. public void actionDesignSimilarity() {
  4405. LukePlugin designer = null;
  4406. for (int i = 0; i < plugins.size(); i++) {
  4407. if (plugins.get(i).getClass().getName().equals("org.getopt.luke.plugins.SimilarityDesignerPlugin")) {
  4408. designer = (LukePlugin)plugins.get(i);
  4409. break;
  4410. }
  4411. }
  4412. if (designer == null) {
  4413. showStatus("Designer Plugin not available");
  4414. return;
  4415. }
  4416. // a bit tricky: plugins are put within panels, and these in tabs
  4417. Object pluginsTab = find("pluginsTab");
  4418. Object maintab = getParent(pluginsTab);
  4419. int index = getIndex(maintab, pluginsTab);
  4420. setInteger(maintab, "selected", index);
  4421. Object pluginsTabs = find("pluginsTabs");
  4422. Object tab = getParent(getParent(designer.getMyUi()));
  4423. index = getIndex(pluginsTabs, tab);
  4424. setInteger(pluginsTabs, "selected", index);
  4425. repaint();
  4426. }
  4427. /**
  4428. * Shut down Luke. If {@link #exitOnDestroy} is true (such as when Luke was
  4429. * started from the main method), invoke also System.exit().
  4430. */
  4431. public boolean destroy() {
  4432. if (ir != null) try {
  4433. ir.close();
  4434. } catch (Exception e) {}
  4435. ;
  4436. if (dir != null) try {
  4437. dir.close();
  4438. } catch (Exception e) {}
  4439. ;
  4440. try {
  4441. Prefs.save();
  4442. } catch (Exception e) {}
  4443. ;
  4444. if (exitOnDestroy) System.exit(0);
  4445. return super.destroy();
  4446. }
  4447. public void actionExit() {
  4448. destroy();
  4449. }
  4450. /**
  4451. * Open URL in the system default browser.
  4452. * @param url
  4453. */
  4454. public void goUrl(Object url) {
  4455. String u = (String) getProperty(url, "url");
  4456. if (u == null) return;
  4457. try {
  4458. BrowserLauncher.openURL(u);
  4459. } catch (Exception e) {
  4460. e.printStackTrace();
  4461. showStatus(e.getMessage());
  4462. }
  4463. }
  4464. /**
  4465. * Start the GUI, and optionally open an index.
  4466. * @param args index parameters
  4467. * @return fully initialized Luke instance
  4468. */
  4469. public static Luke startLuke(String[] args) {
  4470. Luke luke = new Luke();
  4471. FrameLauncher f = new FrameLauncher("Luke - Lucene Index Toolbox, v 3.1.0 (2011-04-30)", luke, 800, 600);
  4472. f.setIconImage(Toolkit.getDefaultToolkit().createImage(Luke.class.getResource("/img/luke.gif")));
  4473. if (args.length > 0) {
  4474. boolean force = false, ro = false, ramdir = false;
  4475. String pName = null;
  4476. String script = null;
  4477. String xmlQueryParserFactoryClassName = null;
  4478. for (int i = 0; i < args.length; i++) {
  4479. if (args[i].equalsIgnoreCase("-ro")) ro = true;
  4480. else if (args[i].equalsIgnoreCase("-force")) force = true;
  4481. else if (args[i].equalsIgnoreCase("-ramdir")) ramdir = true;
  4482. else if (args[i].equalsIgnoreCase("-index")) pName = args[++i];
  4483. else if (args[i].equalsIgnoreCase("-script")) script = args[++i];
  4484. else if (args[i].equalsIgnoreCase("-xmlQueryParserFactory")) xmlQueryParserFactoryClassName = args[++i];
  4485. else {
  4486. System.err.println("Unknown argument: " + args[i]);
  4487. usage();
  4488. luke.actionExit();
  4489. return null;
  4490. }
  4491. }
  4492. if (pName != null) luke.openIndex(pName, force, null, ro, ramdir, false, null, 1);
  4493. if(xmlQueryParserFactoryClassName != null) luke.setParserFactoryClassName(xmlQueryParserFactoryClassName);
  4494. if (script != null) {
  4495. LukePlugin plugin = luke.getPlugin("org.getopt.luke.plugins.ScriptingPlugin");
  4496. if (plugin == null) {
  4497. String msg = "ScriptingPlugin not present - cannot execute scripts.";
  4498. System.err.println(msg);
  4499. luke.actionExit();
  4500. } else {
  4501. ((ScriptingPlugin)plugin).execute("load('" + script + "');");
  4502. }
  4503. }
  4504. } else luke.actionOpen();
  4505. return luke;
  4506. }
  4507. private void setParserFactoryClassName(String xmlQueryParserFactoryClassName) {
  4508. this.xmlQueryParserFactoryClassName = xmlQueryParserFactoryClassName;
  4509. }
  4510. /**
  4511. * Main method. If you just want to instantiate Luke from other classes or scripts,
  4512. * use {@link #startLuke(String[])} instead.
  4513. * @param args
  4514. */
  4515. public static void main(String[] args) {
  4516. exitOnDestroy = true;
  4517. startLuke(args);
  4518. }
  4519. public static void usage() {
  4520. System.err.println("Command-line usage:\n");
  4521. System.err.println("Luke [-index path_to_index] [-ro] [-force] [-mmap] [-script filename]\n");
  4522. System.err.println("\t-index path_to_index\topen this index");
  4523. System.err.println("\t-ro\topen index read-only");
  4524. System.err.println("\t-force\tforce unlock if the index is locked (use with caution)");
  4525. System.err.println("\t-xmlQueryParserFactory\tFactory for loading custom XMLQueryParsers. E.g.:");
  4526. System.err.println("\t\t\torg.getopt.luke.xmlQuery.CoreParserFactory (default)");
  4527. System.err.println("\t\t\torg.getopt.luke.xmlQuery.CorePlusExtensionsParserFactory");
  4528. System.err.println("\t-mmap\tuse MMapDirectory");
  4529. System.err.println("\t-script filename\trun this script using the ScriptingPlugin.");
  4530. System.err.println("\t\tIf an index name is specified, the index is open prior to");
  4531. System.err.println("\t\tstarting the script. Note that you need to escape special");
  4532. System.err.println("\t\tcharacters twice - first for shell and then for JavaScript.");
  4533. }
  4534. /*
  4535. * (non-Javadoc)
  4536. *
  4537. * @see java.awt.datatransfer.ClipboardOwner#lostOwnership(java.awt.datatransfer.Clipboard,
  4538. * java.awt.datatransfer.Transferable)
  4539. */
  4540. public void lostOwnership(Clipboard arg0, Transferable arg1) {
  4541. }
  4542. /**
  4543. * @return the numTerms
  4544. */
  4545. public int getNumTerms() {
  4546. return numTerms;
  4547. }
  4548. }