/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * Author: John Thompson, Greenstone Digital Library, University of Waikato * * Copyright (C) 1999 New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *######################################################################## */ package org.greenstone.gatherer.cdm; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.DebugStream; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.gui.DesignPaneHeader; import org.greenstone.gatherer.gui.GComboBox; import org.greenstone.gatherer.gui.GLIButton; import org.greenstone.gatherer.util.JarTools; import org.w3c.dom.*; /** This class maintains an ordered list of the search types available in the collection (MGPP/lucene command available in G2.39 or later). Currently only 'form' and 'plain' are valid. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 2.4 */ public class SearchTypeManager extends DOMProxyListModel { static final private Dimension LABEL_SIZE = new Dimension(150, 25); static final public String BUILD_TYPE_LUCENE = "lucene"; static final public String BUILD_TYPE_MGPP = "mgpp"; static final public String[] SEARCH_TYPES = { "plain" , "form"}; static final public String[] BUILD_TYPES = { BUILD_TYPE_LUCENE, BUILD_TYPE_MGPP }; /** the buildtype element in the config file - searchtypemanager looks * after this now */ public CollectionMeta build_type = null; /** The controls used to edit the search types. */ private Control controls = null; /** A reference to ourselves so our inner classes have access. */ private DOMProxyListModel model; public SearchTypeManager(Element searchtypes_element) { super(searchtypes_element, CollectionConfiguration.CONTENT_ELEMENT, new SearchType()); this.model = this; DebugStream.println("SearchTypeManager: parsed " + getSize() + " search types."); build_type = new CollectionMeta(CollectionDesignManager.collect_config.getBuildType()); } private void addSearchType(SearchType searchtype) { if(!contains(searchtype)) { add(getSize(), searchtype); Gatherer.c_man.configurationChanged(); } } public Control getControls() { if(controls == null) { controls = new SearchTypeControl(); } return controls; } /** Return a list of the currently assigned search types as a comma separated string. * @return a String */ public String getSearchTypes() { StringBuffer search_types = new StringBuffer(); ArrayList types = children(); for (int i = 0; i < types.size(); i++) { if (i>0) { search_types.append(","); } search_types.append(((SearchType)types.get(i)).getName()); } return search_types.toString(); } /** By examining the SearchType 'root' we were created with, determine if mgpp is enabled. * @return true if MGPP is enabled, false otherwise */ public boolean isSearchTypeEnabled() { return root.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.TRUE_STR); } public boolean isMGPP() { return isSearchTypeEnabled() && build_type.getValue(CollectionMeta.TEXT).equals(BUILD_TYPE_MGPP); } public boolean isLucene() { return isSearchTypeEnabled() && build_type.getValue(CollectionMeta.TEXT).equals(BUILD_TYPE_LUCENE); } private void moveSearchType(SearchType search_type, boolean direction) { // Try to move the classifier one step in the desired direction. int index = indexOf(search_type); if(direction) { index--; } else { index++; } // Check we aren't at an edge if((direction && index < 0) || (!direction && index >= getSize())) { String args[] = new String[2]; args[0] = Dictionary.get("CDM.SearchTypeManager.SearchType"); args[1] = search_type.toString(); String message = null; if (direction) { message = Dictionary.get("CDM.Move.At_Top", args); } else { message = Dictionary.get("CDM.Move.At_Bottom", args); } JOptionPane.showMessageDialog(Gatherer.g_man, message, Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); return; } remove(search_type); add(index, search_type); Gatherer.c_man.configurationChanged(); } private void removeSearchType(SearchType searchtype) { if(contains(searchtype)) { remove(searchtype); Gatherer.c_man.configurationChanged(); } } private class SearchTypeControl extends JPanel implements Control { private GComboBox search_type_combobox; private GComboBox build_type_combobox; private JButton add_button; private JButton move_down_button; private JButton move_up_button; private JButton remove_button; private JCheckBox enable_advanced_searches_checkbox; private JLabel current_search_types_label; private JLabel search_type_label; private JList current_search_types_list; public SearchTypeControl() { // Creation JPanel header_panel = new DesignPaneHeader("CDM.GUI.SearchTypes", "searchtypes"); JPanel spacer_panel = new JPanel(); JPanel empty_panel = new JPanel(); JPanel inner_panel = new JPanel(); JPanel indexer_type_panel = new JPanel(); JPanel build_type_panel = new JPanel(); enable_advanced_searches_checkbox = new JCheckBox(); Dictionary.registerText(enable_advanced_searches_checkbox, "CDM.SearchTypeManager.Enable"); build_type_combobox = new GComboBox(BUILD_TYPES); build_type_combobox.setPreferredSize(LABEL_SIZE); build_type_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false)); build_type_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); build_type_combobox.setEditable(true); build_type_combobox.setSelectedIndex(1);// mgpp is at 1 String selected_value = build_type.getValue(CollectionMeta.TEXT); if (!selected_value.equals("")) { for (int i=0; i 1 && !current_search_types_list.isSelectionEmpty() && advanced_search_enabled); } /** Listenes for actions on the Add button, and if detected adds a new search type. */ private class AddActionListener implements ActionListener { /** Called when someone actions the Add button. * @param event an ActionEvent containing information about the add button click */ public void actionPerformed(ActionEvent event) { Object selected_item = search_type_combobox.getSelectedItem(); if(selected_item != null) { if(search_type_combobox.getSelectedIndex() == -1) { search_type_combobox.insertItemAt(selected_item, search_type_combobox.getItemCount()); } // Add the search type SearchType new_searchtype = new SearchType((String)selected_item); addSearchType(new_searchtype); } add_button.setEnabled(false); } } /** Listens for selections within the search types list and updates the remove button appropriately. */ private class CurrentSearchTypesListSelectionListener implements ListSelectionListener { /** Called when the selection in the list changes. * @param event a ListSelectionEvent containing information about the selection change */ public void valueChanged(ListSelectionEvent event) { if(!event.getValueIsAdjusting()) { SearchType search_type = null; if ((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) { int index = model.indexOf(search_type); // Move up is only enabled if the current selection isn't at index 0 move_up_button.setEnabled(index != 0); // Move down is only enabled if the current selection isn't at index getSize() - 1 move_down_button.setEnabled(index != model.getSize() - 1); // Remove is only enabled if this isn't the last search type remove_button.setEnabled(current_search_types_list.getModel().getSize() > 1); } else { move_up_button.setEnabled(false); move_down_button.setEnabled(false); remove_button.setEnabled(false); } } } } /** The most complex listener in this class, this listens for changes to the enable advanced searches checkbox, and when they occur it not only updates the controls on this page, but asks the IndexManager to action the appropriate changes to the underlying DOM so as to support either MG or MGPP styles of indexes. */ private class EnableAdvancedSearchesActionListener implements ActionListener { /** Called whenever the checkbox is checked or unchecked. * @param event an ActionEvent containing information about the checking action */ public void actionPerformed(ActionEvent event) { Gatherer.g_man.wait(true); boolean advanced_search_enabled = enable_advanced_searches_checkbox.isSelected(); model.root.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (advanced_search_enabled ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR)); validateControls(advanced_search_enabled); if ((!build_type.isAssigned() && advanced_search_enabled) || (build_type.isAssigned() && !advanced_search_enabled)) { build_type.setAssigned(advanced_search_enabled); Gatherer.c_man.configurationChanged(); } if (build_type.isAssigned() && build_type.getValue(true).equals("")) { build_type.setValue((String)build_type_combobox.getSelectedItem()); } Gatherer.g_man.wait(false); } } private class BuildTypeActionListener implements ActionListener { public void actionPerformed(ActionEvent event) { if (!build_type.getValue(CollectionMeta.TEXT).equals((String)build_type_combobox.getSelectedItem())) { build_type.setValue((String)build_type_combobox.getSelectedItem()); } } } /** Listenes for actions on the Remove button, and if detected removes the currently selected search types. */ private class RemoveActionListener implements ActionListener { /** Called when someone actions the Remove button. * @param event an ActionEvent containing information about the remove button click */ public void actionPerformed(ActionEvent event) { if(!current_search_types_list.isSelectionEmpty()) { Object[] selected_items = current_search_types_list.getSelectedValues(); for(int i = 0; model.getSize() > 1 && i < selected_items.length; i++) { removeSearchType((SearchType)selected_items[i]); } } Object selected_object = search_type_combobox.getSelectedItem(); if(selected_object != null) { add_button.setEnabled(!model.contains(selected_object)); } else { add_button.setEnabled(false); } remove_button.setEnabled(false); } } private class MoveListener implements ActionListener { private boolean move_up; public MoveListener(boolean move_up) { this.move_up = move_up; } public void actionPerformed(ActionEvent event) { // Retrieve the first selected search type (if any) SearchType search_type = null; if((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) { // Move search type moveSearchType(search_type, move_up); // Reselect the moved search type current_search_types_list.setSelectedValue(search_type, true); } // No selection - no movement else { move_up_button.setEnabled(false); move_down_button.setEnabled(false); } } } /** Listens for changes in the search types combobox, and enabled add button appropriately. */ private class SearchTypesActionDocumentListener implements ActionListener, DocumentListener { /** Called whenever a selection action occurs on the combobox. * @param event an ActionEvent containing information about the selection event */ public void actionPerformed(ActionEvent event) { validateAddButton(); } /** Gives notification that an attribute or set of attributes changed. * @param event a DocumentEvent containing information about the text changed */ public void changedUpdate(DocumentEvent event) { validateAddButton(); } /** Gives notification that there was an insert into the document. * @param event a DocumentEvent containing information about the text added */ public void insertUpdate(DocumentEvent event) { validateAddButton(); } /** Gives notification that a portion of the document has been removed. * @param event a DocumentEvent containing information about the text removed */ public void removeUpdate(DocumentEvent event) { validateAddButton(); } /** Change the enable state of the add button depending on the current value in the search type combobox. */ private void validateAddButton() { Object selected_object = search_type_combobox.getSelectedItem(); if(selected_object != null) { add_button.setEnabled(!model.contains(selected_object)); } else { add_button.setEnabled(false); } } } } }