/** *######################################################################### * * 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.cdm.CollectionConfiguration; import org.greenstone.gatherer.cdm.CollectionDesignManager; import org.greenstone.gatherer.cdm.Control; import org.greenstone.gatherer.cdm.DOMProxyListModel; import org.greenstone.gatherer.cdm.Subcollection; import org.greenstone.gatherer.cdm.SubcollectionIndex; import org.greenstone.gatherer.gui.GLIButton; import org.greenstone.gatherer.util.ExclusiveListSelectionListener; import org.greenstone.gatherer.util.StaticStrings; import org.greenstone.gatherer.util.Utility; import org.w3c.dom.*; /** This class maintains a list of indexes partitions for the purpose of defining subcollections. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 2.4 */ public class SubcollectionIndexManager extends DOMProxyListModel { private Control controls; private DOMProxyListModel model; private SubcollectionIndex default_index; /** Constructor. */ public SubcollectionIndexManager(Element subindexes) { super(subindexes, CollectionConfiguration.INDEX_ELEMENT, new SubcollectionIndex()); DebugStream.println("SubcollectionIndexManager: " + getSize() + " subcollection indexes parsed."); model = this; // Parse and retrieve the default index NodeList default_index_elements = CollectionDesignManager.collect_config.getDocumentElement().getElementsByTagName(CollectionConfiguration.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT); if(default_index_elements.getLength() > 0) { default_index = new SubcollectionIndex((Element)default_index_elements.item(0)); } } /** Method to add a subindex. * @param subindex a SubcollectionIndex * @see org.greenstone.gatherer.Gatherer * @see org.greenstone.gatherer.collection.CollectionManager */ private void addSubcollectionIndex(SubcollectionIndex subindex) { if(!contains(subindex)) { add(getSize(), subindex); Gatherer.c_man.configurationChanged(); } } public void destroy() { if(controls != null) { controls.destroy(); controls = null; } default_index = null; model = null; } public Control getControls() { if(controls == null) { controls = new SubcollectionIndexControl(); } return controls; } /** Method to retrieve the default index. * @return the default Index, or null if no such index assigned */ /* private SubcollectionIndex getDefaultSubcollectionIndex() { if(default_index != null && default_index.isAssigned()) { return default_index; } else { return null; } } */ /** Retrieve a certain subindex given its name. * @param id the String identifier of a subcollectionindex * @return the SubcollectionIndex requested or null if no such subindex */ private SubcollectionIndex getSubcollectionIndex(String id) { int size = getSize(); for(int i = 0; i < size; i++) { SubcollectionIndex subindex = (SubcollectionIndex) getElementAt(i); if(subindex.getID().equals(id)) { return subindex; } } return null; } /** Method to get all of the subindexes set. * @return an ArrayList containing all the defined indexes */ public ArrayList getSubcollectionIndexes() { return children(); } /** Method to remove a certain subindex. * @param subindex the Index you wish to remove * @see org.greenstone.gatherer.Gatherer * @see org.greenstone.gatherer.collection.CollectionManager */ private void removeSubcollectionIndex(SubcollectionIndex subindex) { if(subindex != null) { // Remove any current metadata from this index CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + subindex.getID()); // Check if the index removed happens to be the default index if(default_index != null && default_index.equals(subindex)) { default_index.setAssigned(false); ((SubcollectionIndexControl)controls).clearDefaultIndex(); } // Remove the index remove(subindex); Gatherer.c_man.configurationChanged(); } } /** Method to remove all of the subindexes that contain a certain subcollection. * @param subcollection the Subcollection that has been removed * @see org.greenstone.gatherer.cdm.Subcollection * @see org.greenstone.gatherer.cdm.SubcollectionIndex */ public void removeSubcollectionIndexes(Subcollection subcollection) { String subcollection_name = subcollection.getName(); int size = getSize(); for(int i = size - 1; i >= 0; i--) { SubcollectionIndex subindex = (SubcollectionIndex)getElementAt(i); if(subindex.getSources().contains(subcollection_name)) { removeSubcollectionIndex(subindex); } subindex = null; } subcollection_name = null; } /** Method to set the default subcollection index. * @param index The SubcollectionIndex to use as the default index. * @see org.greenstone.gatherer.Gatherer * @see org.greenstone.gatherer.collection.CollectionManager * @see org.greenstone.gatherer.cdm.SubcollectionIndex */ private void setDefaultSubcollectionIndex(SubcollectionIndex index) { if(index != null) { if(default_index == null) { // Create the default index element, and place immediately after indexes element. Element default_index_element = root.getOwnerDocument().createElement(CollectionConfiguration.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT); default_index = new SubcollectionIndex(default_index_element); Node target_node = CollectionConfiguration.findInsertionPoint(default_index_element); if(target_node != null) { root.getOwnerDocument().getDocumentElement().insertBefore(default_index_element, target_node); } else { root.getOwnerDocument().getDocumentElement().appendChild(default_index_element); } } default_index.setAssigned(true); default_index.setSources(index.getSources()); } else { if(default_index != null) { default_index.setAssigned(false); } } Gatherer.c_man.configurationChanged(); } private class SubcollectionIndexControl extends JPanel implements Control { private JButton add_index_button; private JButton clear_default_button; private JButton remove_index_button; private JButton set_default_button; private JList subcollection_list; private JList subcollectionindexes_list; private JTextField default_value_field; private JTextField subcollectionindex_name_field; public SubcollectionIndexControl() { super(); // Creation JPanel subcollection_panel = new JPanel(); JPanel subindex_name_panel = new JPanel(); JLabel subindex_name_label = new JLabel(); Dictionary.registerText(subindex_name_label, "CDM.SubcollectionIndexManager.PartitionName"); subcollectionindex_name_field = new JTextField(); subcollectionindex_name_field.setPreferredSize(Utility.LABEL_SIZE); Dictionary.registerTooltip(subcollectionindex_name_field, "CDM.SubcollectionIndexManager.PartitionName_Tooltip"); JPanel button_pane = new JPanel(); add_index_button = new GLIButton(); add_index_button.setMnemonic(KeyEvent.VK_A); add_index_button.setEnabled(false); Dictionary.registerBoth(add_index_button, "CDM.SubcollectionIndexManager.Add_Subindex", "CDM.SubcollectionIndexManager.Add_Subindex_Tooltip"); clear_default_button = new GLIButton(); clear_default_button.setMnemonic(KeyEvent.VK_C); clear_default_button.setEnabled(default_index != null); Dictionary.registerBoth(clear_default_button, "CDM.SubcollectionIndexManager.Clear_Default_Subindex", "CDM.SubcollectionIndexManager.Clear_Default_Subindex_Tooltip"); JLabel default_label = new JLabel(); Dictionary.registerText(default_label, "CDM.SubcollectionIndexManager.Default_Subindex"); JPanel default_pane = new JPanel(); if(default_index == null) { default_value_field = new JTextField(); } else { default_value_field = new JTextField(default_index.toString()); } default_value_field.setPreferredSize(Utility.LABEL_SIZE); default_value_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); default_value_field.setEditable(false); remove_index_button = new GLIButton(); remove_index_button.setMnemonic(KeyEvent.VK_R); remove_index_button.setEnabled(false); Dictionary.registerBoth(remove_index_button, "CDM.SubcollectionIndexManager.Remove_Subindex", "CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip"); set_default_button = new GLIButton(); set_default_button.setMnemonic(KeyEvent.VK_S); set_default_button.setEnabled(false); Dictionary.registerBoth(set_default_button, "CDM.SubcollectionIndexManager.Set_Default_Subindex", "CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip"); JLabel subcollection_label = new JLabel(); Dictionary.registerText(subcollection_label, "CDM.SubcollectionIndexManager.Subcollection"); subcollection_list = new JList(CollectionDesignManager.subcollection_manager); JPanel list_pane = new JPanel(); JLabel subindexes_label = new JLabel(); Dictionary.registerText(subcollection_label, "CDM.SubcollectionIndexManager.Subindexes"); subcollectionindexes_list = new JList(model); subcollectionindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JPanel subindexes_pane = new JPanel(); // Add listeners ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener(); ell.add(subcollection_list); ell.add(subcollectionindexes_list); add_index_button.addActionListener(new AddSubIndexListener()); clear_default_button.addActionListener(new ClearDefaultSubIndexListener()); remove_index_button.addActionListener(new RemoveSubIndexListener()); set_default_button.addActionListener(new SetDefaultSubIndexListener()); subcollectionindexes_list.addListSelectionListener(new SubcollectionListListener()); subcollectionindex_name_field.getDocument().addDocumentListener(new SubcollectionIndexListener()); subcollection_list.addListSelectionListener(new SubcollectionIndexListener()); // Layout default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2,0,0,0), BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createEmptyBorder(2,2,2,2)))); default_pane.setLayout(new BorderLayout(5,0)); default_pane.add(default_label, BorderLayout.WEST); default_pane.add(default_value_field, BorderLayout.CENTER); subindexes_pane.setLayout(new BorderLayout()); subindexes_pane.add(subindexes_label, BorderLayout.NORTH); subindexes_pane.add(new JScrollPane(subcollectionindexes_list), BorderLayout.CENTER); subindexes_pane.add(default_pane, BorderLayout.SOUTH); subindex_name_panel.setBorder(BorderFactory.createEmptyBorder(2,0,0,0)); subindex_name_panel.setLayout(new BorderLayout(5,0)); subindex_name_panel.add(subindex_name_label, BorderLayout.WEST); subindex_name_panel.add(subcollectionindex_name_field, BorderLayout.CENTER); list_pane.setBorder(BorderFactory.createEmptyBorder(5,0,2,0)); list_pane.setLayout(new BorderLayout()); list_pane.add(subcollection_label, BorderLayout.NORTH); list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER); list_pane.add(subindex_name_panel, BorderLayout.SOUTH); button_pane.setLayout(new GridLayout(2,2)); button_pane.add(add_index_button); button_pane.add(remove_index_button); button_pane.add(set_default_button); button_pane.add(clear_default_button); subcollection_panel.setLayout(new BorderLayout()); //subcollection_panel.add(subindex_name_panel, BorderLayout.NORTH); subcollection_panel.add(list_pane, BorderLayout.CENTER); subcollection_panel.add(button_pane, BorderLayout.SOUTH); setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); setLayout(new BorderLayout()); add(subindexes_pane, BorderLayout.CENTER); add(subcollection_panel, BorderLayout.SOUTH); } public void clearDefaultIndex() { clear_default_button.doClick(); } public void destroy() { } public void gainFocus() { } public void loseFocus() { } /** Listens for actions apon the 'add subindex' button in the SubcollectionManager controls, and if detected calls the addSubindex method of the manager with a newly created subindex. */ private class AddSubIndexListener implements ActionListener { /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a series of subcollections selected, and if so build an new subindex based apon them. * @param event An ActionEvent containing information about the event. * @see org.greenstone.gatherer.cdm.SubcollectionIndex */ public void actionPerformed(ActionEvent event) { if(!subcollection_list.isSelectionEmpty() && subcollectionindex_name_field.getText().length() > 0) { SubcollectionIndex subindex = new SubcollectionIndex(subcollection_list.getSelectedValues()); addSubcollectionIndex(subindex); // Add the subindexes name. CollectionMeta metadatum = new CollectionMeta("." + subindex.getID()); metadatum.setValue(subcollectionindex_name_field.getText()); CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum); } } } /** Listens for actions apon the 'clear default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubcollectionIndex() method of the manager with null. */ private class ClearDefaultSubIndexListener implements ActionListener { /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to clear the default subindex. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { setDefaultSubcollectionIndex(null); default_value_field.setText(""); clear_default_button.setEnabled(false); set_default_button.setEnabled(!subcollectionindexes_list.isSelectionEmpty()); } } /** Listens for actions apon the 'remove subindex' button in the SubcollectionManager controls, and if detected calls the removeSubcollectionIndex method of the manager with the SubcollectionIndex selected for removal. */ private class RemoveSubIndexListener implements ActionListener { /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so remove it. * @param event An ActionEvent containing information about the event. * @see org.greenstone.gatherer.cdm.SubcollectionIndex */ public void actionPerformed(ActionEvent event) { if(!subcollectionindexes_list.isSelectionEmpty()) { removeSubcollectionIndex((SubcollectionIndex)subcollectionindexes_list.getSelectedValue()); } } } /** Listens for actions apon the 'set default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubcollectionIndex method of the manager with the SubIndex selected for default. */ private class SetDefaultSubIndexListener implements ActionListener { /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so set it as default. * @param event An ActionEvent containing information about the event. * @see org.greenstone.gatherer.cdm.SubcollectionIndex */ public void actionPerformed(ActionEvent event) { if(!subcollectionindexes_list.isSelectionEmpty()) { setDefaultSubcollectionIndex((SubcollectionIndex)subcollectionindexes_list.getSelectedValue()); default_value_field.setText(default_index.toString()); clear_default_button.setEnabled(true); set_default_button.setEnabled(false); } } } private class SubcollectionIndexListener implements DocumentListener, ListSelectionListener { /** Gives notification that an attribute or set of attributes changed. */ public void changedUpdate(DocumentEvent e) { update(); } /** Gives notification that there was an insert into the document. */ public void insertUpdate(DocumentEvent e) { update(); } /** Gives notification that a portion of the document has been removed. */ public void removeUpdate(DocumentEvent e) { update(); } public void valueChanged(ListSelectionEvent event) { if(!event.getValueIsAdjusting()) { update(); } } /** The text area has changed in some way. Given that this can only happed when we are editing or adding a text fragment we better respond appropriately. */ private void update() { if(!subcollection_list.isSelectionEmpty() && subcollectionindex_name_field.getText().length() > 0) { if (getSubcollectionIndex(subcollectionindex_name_field.getText()) == null) { SubcollectionIndex subindex = new SubcollectionIndex(subcollection_list.getSelectedValues()); add_index_button.setEnabled(!model.contains(subindex)); } else { add_index_button.setEnabled(false); } } else { add_index_button.setEnabled(false); } } } private class SubcollectionListListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent event) { if(!event.getValueIsAdjusting()) { boolean enable = !subcollectionindexes_list.isSelectionEmpty(); remove_index_button.setEnabled(enable); set_default_button.setEnabled(enable); } } } } }