Ignore:
Timestamp:
2003-07-15T13:55:22+12:00 (21 years ago)
Author:
jmt12
Message:

Major CDM rewrite so it uses DOM.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java

    r4675 r4932  
    66 * University of Waikato, New Zealand.
    77 *
    8  * <BR><BR>
    9  *
    108 * Author: John Thompson, Greenstone Digital Library, University of Waikato
    119 *
    12  * <BR><BR>
    13  *
    1410 * Copyright (C) 1999 New Zealand Digital Library Project
    15  *
    16  * <BR><BR>
    1711 *
    1812 * This program is free software; you can redistribute it and/or modify
     
    2115 * (at your option) any later version.
    2216 *
    23  * <BR><BR>
    24  *
    2517 * This program is distributed in the hope that it will be useful,
    2618 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2719 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2820 * GNU General Public License for more details.
    29  *
    30  * <BR><BR>
    3121 *
    3222 * You should have received a copy of the GNU General Public License
     
    3525 *########################################################################
    3626 */
    37 
    38  
    39 
    40 
    41 
    42 
    4327package org.greenstone.gatherer.cdm;
    4428/**************************************************************************************
    45  * Title:        Gatherer
    46  * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
    47  * Copyright:    Copyright (c) 2001
    48  * Company:      The University of Waikato
    49  * Written:      02/05/02
    50  * Revised:      17/11/02 - Commented
     29 * Written:      ??/??/02
     30 * Revised:      04/07/03 - DOM support
    5131 **************************************************************************************/
    5232import java.awt.*;
     
    5636import javax.swing.event.*;
    5737import org.greenstone.gatherer.Gatherer;
     38import org.greenstone.gatherer.cdm.CollectionConfiguration;
     39import org.greenstone.gatherer.cdm.CollectionDesignManager;
     40import org.greenstone.gatherer.cdm.Control;
     41import org.greenstone.gatherer.cdm.DOMProxyListModel;
    5842import org.greenstone.gatherer.cdm.Subcollection;
    59 import org.greenstone.gatherer.cdm.SubIndex;
    60 import org.greenstone.gatherer.cdm.SubIndexes;
     43import org.greenstone.gatherer.gui.NonWhitespaceField;
    6144import org.greenstone.gatherer.msm.ElementWrapper;
     45import org.greenstone.gatherer.msm.MSMUtils;
    6246import org.greenstone.gatherer.util.ExclusiveListSelectionListener;
    63 import org.w3c.dom.Element;
    64 /** This class maintains a list of subcollections within our collection, and also records which of these subcollections we are building indexes for.
     47import org.greenstone.gatherer.util.StaticStrings;
     48import org.greenstone.gatherer.util.Utility;
     49import org.w3c.dom.*;
     50/** This class maintains a list of subcollections within our collection.
    6551 * @author John Thompson, Greenstone Digital Library, University of Waikato
    66  * @version 2.1
     52 * @version 2.4
    6753 */
    6854public class SubcollectionManager
    69     extends DefaultListModel {
    70     /** A reference to the manager so we can get access to languages. */
    71     private CollectionDesignManager manager;
     55    extends DOMProxyListModel {
     56
     57    static final private String CLASS_DICTIONARY_NAME = "CDM.SubcollectionManager.";
     58
    7259    /** The controls used to edit the settings of this manager. */
    7360    private Control controls = null;
    74     /** A reference to this class so we can use it as a model in our inner classes. */
    75     private DefaultListModel model = null;
    76     /** The default index for the subcollections. */
    77     private DefaultSubIndex default_index = null;
    78     /** A reference to the Gatherer. */
    79     private Gatherer gatherer = null;
    80     /** A hashtable of subcollections, with mappings from name to subcollection. */
    81     private Hashtable subcollections = null;
    82     /** A vector-type structure of subcollection indexes. */
    83     private SubIndexes subindexes = null;
    84     /** A vector containing all of the subcollection commands that are unresolved, or in other words require that all 'subcollection <name> "<exp>"' to have been previously parsed before we can be certain their references will make sense. */
    85     private ArrayList unresolved = null;
    86     /** Constructor.
    87      * @param gatherer A reference to the <Strong>Gatherer</strong>.
    88      * @see org.greenstone.gatherer.cdm.SubIndexes
    89      */
    90     public SubcollectionManager(Gatherer gatherer, CollectionDesignManager manager) {
    91     super();
    92     this.gatherer = gatherer;
    93     this.manager = manager;
     61
     62    private DOMProxyListModel model;
     63
     64    /** Constructor.
     65     * @see org.greenstone.gatherer.Gatherer
     66     * @see org.greenstone.gatherer.cdm.CollectionConfiguration
     67     * @see org.greenstone.gatherer.cdm.CollectionDesignManager
     68     * @see org.greenstone.gatherer.cdm.DOMProxyListModel
     69     * @see org.greenstone.gatherer.cdm.Subcollection
     70     */
     71    public SubcollectionManager() {
     72    super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.SUBCOLLECTION_ELEMENT, new Subcollection());
     73    Gatherer.println("SubcollectionManager: " + getSize() + " subcollections parsed.");
    9474    this.model = this;
    95     this.subcollections = new Hashtable();
    96     this.subindexes = new SubIndexes();
    97     this.unresolved = new ArrayList();
    98     }
    99     /** Method to add a subindex.
    100      * @param subindex A <strong>SubIndex</strong>.
     75    }
     76
     77    /** Method to add a new subcollection.
     78     * @param subcollection the Subcollection to add
    10179     * @see org.greenstone.gatherer.Gatherer
     80     * @see org.greenstone.gatherer.cdm.CollectionConfiguration
     81     * @see org.greenstone.gatherer.cdm.DOMProxyListModel
    10282     * @see org.greenstone.gatherer.collection.CollectionManager
    10383     */
    104     public void addSubIndex(SubIndex subindex) {
    105     if(!subindexes.contains(subindex)) {
    106         subindexes.addElement(subindex);
    107         gatherer.c_man.configurationChanged();
    108     }
    109     }
    110     /** Method to add a new subcollection. Adds it to both the underlying list model and the hashtable mapping names to subcollections.
    111       * @param sub The <strong>Subcollection</strong> to add.
    112       * @return A <i>boolean</i> indicating if the addition was successful (<i>true</i>) or not (<i>false</i>).
    113         * @see org.greenstone.gatherer.Gatherer
    114         * @see org.greenstone.gatherer.collection.CollectionManager
    115       */
    116     public boolean addSubcollection(Subcollection sub) {
    117     if(!contains(sub)) {
    118         addElement(sub);
    119         subcollections.put(sub.getName(), sub);
    120         gatherer.c_man.configurationChanged();
    121         return true;
    122     }
    123     return false;
    124     }
    125     /** A method to add a new subcollection, by specifying its name, metadata element if applicable and Perl expression to filter pages into or out of this collection.
    126      * @param name A <>>String</>> which is a unique identifier of a subcollection.
    127      * @param include A <i>boolean</i> indicating whether this is an inclusion filter (<i>true</i>) or an exclusion one (<i>false</i>).
    128      * @param element An <>>Element</>> which is either the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name.
    129      * @param exp A <>>String</>> containing a Perl expression which is used as the filter for this subcollection.
    130      * @param flags A <strong>String<strong> listing any special flags to be applied when matching the expression.
    131      * @return A <i>boolean</i> with a value of <i>true</i> if the addition was successful.
    132      * @see org.greenstone.gatherer.cdm.Subcollection
    133      */
    134     public boolean addSubcollection(String name, boolean include, String element, String exp, String flags) {
    135     Subcollection sub = null;
    136     if(element != null) {
    137         sub = new Subcollection(name, include, element, exp, flags);
    138     }
    139     else {
    140         sub = new Subcollection(name, include, exp, flags);
    141     }
    142     return addSubcollection(sub);
    143     }
    144     /** Refresh all derived components using this manager as a model.
    145      */
    146     public void changed() {
    147     fireContentsChanged(this, 0, getSize() - 1);
    148     }
    149     /** Method to retrieve the controls for this manager.
    150      * @return A <Strong>Control</strong> object which contains the controls used to edit the subcollection data.
    151      */
    152     public Control getControls() {
    153     if(controls == null) {
    154         controls = new Control();
    155     }
    156     return controls;
    157     }
    158     /** Method to retrieve the default index.
    159       * @return A <strong>DefaultSubIndex</strong> object.
    160       */
    161     public DefaultSubIndex getDefaultSubIndex() {
    162     return default_index;
    163     }
    164     /** Method to retrieve a certain subcollection by its name.
    165      * @param name A <strong>String</strong> which is used as the key for finding the matching subcollection.
    166      * @return The requested <strong>Subcollection</strong> or <i>null</i> if no such subcollection exists.
    167      */
    168     public Subcollection getSubcollection(String name) {
    169     return (Subcollection) subcollections.get(name);
    170     }
    171 
    172     /** Retrieve a certain subindex given its name.
    173      * @param name the String representation of a subindex.
    174      * @return the SubIndex requested or null if no such subindex.
    175      */
    176     public SubIndex getSubIndex(String name) {
    177     for(int i = 0; i < subindexes.size(); i++) {
    178         SubIndex subindex = (SubIndex) subindexes.get(i);
    179         if(subindex.toString().equals(name)) {
    180         return subindex;
    181         }
    182     }
    183     return null;
    184     }
    185 
    186     /** Method to get all of the subindexes set.
    187      * @return A <strong>SubIndexes</strong> object containing all the defined indexes.
    188      */
    189     public SubIndexes getSubIndexes() {
    190     return subindexes;
    191     }
    192     /** Method to get all of the subcollections defined.
    193      * @return A <strong>Vector</strong> of subcollections.
    194      */
    195     public Vector getSubcollections() {
    196     Vector subcollections = new Vector();
    197     for(int i = 0; i < size(); i++) {
    198         subcollections.add(get(i));
    199     }
    200     return subcollections;
    201     }
    202     /** Mark the current controls, if any, as invalid and deallocate them. Any further use of the controls will requires them being rebuilt.
    203      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control
    204      */
    205     public void invalidateControls() {
     84    public void addSubcollection(Subcollection subcollection) {
     85    if(!contains(subcollection)) {
     86        Element element = subcollection.getElement();
     87        // Locate where we should insert this new subcollection.
     88        Node target_node = CollectionConfiguration.findInsertionPoint(element);
     89        // Failing that we insert immediately after a language string
     90        add(root, subcollection, target_node);
     91        Gatherer.c_man.configurationChanged();
     92    }
     93    }
     94
     95    public void destroy() {
    20696    if(controls != null) {
    20797        controls.destroy();
     
    20999    }
    210100    }
    211     /** This method attempts to parse a subcollection related command from the given command string. If such a string is successfully parsed, it is immediately added to the data within this collection.
    212      * @param command The <strong>String</strong> to be parsed.
    213      * @param finished This <i>boolean</i> is usually <i>false</i> when called, unless this parse call is being made -after- the entire collection configuration file has been read in in which case it is <i>true</i>.
    214      * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
    215      * @see org.greenstone.gatherer.cdm.CommandTokenizer
    216      * @see org.greenstone.gatherer.cdm.DefaultSubIndex
    217      * @see org.greenstone.gatherer.cdm.Subcollection
    218      * @see org.greenstone.gatherer.cdm.SubIndex
    219      */
    220     public boolean parse(String command, boolean finished) {
    221     String temp = command.toLowerCase();
    222     CommandTokenizer tokenizer = new CommandTokenizer(command);
    223     tokenizer.nextToken(); // Throw away head.
    224     if(temp.startsWith("subcollection")) {
    225         if(tokenizer.countTokens() >= 2) {
    226         String name = tokenizer.nextToken();
    227         String pattern = tokenizer.nextToken();
    228         addSubcollection(new Subcollection(name, pattern));
    229         return true;
    230         }
    231     }
    232     else if(temp.startsWith("indexsubcollections")) {
    233                 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
    234         if(!finished) {
    235         unresolved.add(command);
    236         }
    237         else {
    238         while(tokenizer.hasMoreTokens()) {
    239             addSubIndex(new SubIndex(tokenizer.nextToken(), this));
    240         }
    241         }
    242         return true;
    243     }
    244     else if(temp.startsWith("defaultsubcollection")) {
    245                 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
    246         if(!finished) {
    247         unresolved.add(command);
    248         }
    249         else {
    250         if(tokenizer.hasMoreTokens()) {
    251             setDefaultSubIndex(new DefaultSubIndex(tokenizer.nextToken(), this));
    252         }
    253         }
    254         return true;
    255     }
    256     return false;
    257     }
    258     /** Method to remove a certain subindex.
    259       * @param subindex The <strong>SubIndex</strong> you wish to remove.
    260       * @see org.greenstone.gatherer.Gatherer
    261       * @see org.greenstone.gatherer.collection.CollectionManager
    262       */
    263     public void removeSubIndex(SubIndex subindex) {
    264     subindexes.removeElement(subindex);
    265     gatherer.c_man.configurationChanged();
    266     }
    267     /** Method to remove all of the subindexes that contain a certain subcollection.
    268       * @param sub The <strong>Subcollection</strong> that you wish to remove.
    269       * @see org.greenstone.gatherer.Gatherer
    270       * @see org.greenstone.gatherer.cdm.SubIndex
    271       * @see org.greenstone.gatherer.collection.CollectionManager
    272       */
    273     public void removeSubIndexes(Subcollection sub) {
    274     for(int i = subindexes.size() - 1; i >= 0; i--) {
    275         SubIndex subindex = (SubIndex)subindexes.get(i);
    276         if(subindex.containsSubcollection(sub.getName())) {
    277         subindexes.removeElement(subindex);
    278         }
    279     }
    280     gatherer.c_man.configurationChanged();
    281     }
     101
     102    /** Method to retrieve the controls for this manager.
     103     * @return the Control used to edit the subcollection data
     104     */
     105    public Control getControls() {
     106    if(controls == null) {
     107        controls = new SubcollectionControl();
     108    }
     109    return controls;
     110    }
     111
     112    /** Method to retrieve a certain subcollection by its name.
     113     * @param name a String which is used as the key for finding the matching subcollection
     114     * @return the requested Subcollection or null if no such subcollection exists.
     115     */
     116    public Subcollection getSubcollection(String name) {
     117    Subcollection result = null;
     118    int size = getSize();
     119    for(int i = 0; i < size; i++) {
     120        Subcollection subcollection = (Subcollection) getElementAt(i);
     121        if(subcollection.getName().equals(name)) {
     122        result = subcollection;
     123        }
     124    }
     125    return result;
     126    }
     127
     128    /** Method to get all of the subcollections defined.
     129     * @return an ArrayList of subcollections
     130     */
     131    public ArrayList getSubcollections() {
     132    return children();
     133    }
     134
    282135    /** Method to remove the given subcollection.
    283       * @param sub The <strong>Subcollection</strong> you want to remove.
    284       * @see org.greenstone.gatherer.Gatherer
    285       * @see org.greenstone.gatherer.collection.CollectionManager
    286       */
    287     public void removeSubcollection(Subcollection sub) {
    288     removeElement(sub);
    289     subcollections.remove(sub);
    290     gatherer.c_man.configurationChanged();
    291     }
    292     /** Method to retry the parsing of commands that were previously unable to be parsed as they referenced subcollections that may not have been instantiated.
    293       */
    294     public void reparseUnresolved() {
    295     for(int i = 0; i < unresolved.size(); i++) {
    296         parse((String)unresolved.get(i), true);
    297     }
    298     unresolved.clear();
    299     }
    300     /** Method to set the default subcollection index.
    301       * @param subcollection The <strong>Subcollection</strong> to use as the default index.
    302       * @see org.greenstone.gatherer.Gatherer
    303       * @see org.greenstone.gatherer.collection.CollectionManager
    304       */
    305     public void setDefaultSubIndex(DefaultSubIndex subindex) {
    306     this.default_index = subindex;
    307     if(subindex != null) {
    308         addSubIndex(subindex.getSubIndex());
    309     }
    310     gatherer.c_man.configurationChanged();
    311     }
    312     /** This method causes the contents of this manager to be converted to a string, which is accomplished by calling <i>toString()</i> on each subcollection, then printing out the contents of the index vector.
    313       * @return A <strong>String</strong> containing a block of configuration commands.
    314         * @see org.greenstone.gatherer.cdm.SubIndex
    315         * @see org.greenstone.gatherer.cdm.Subcollection
    316       */
    317     public String toString() {
    318     String text = "";
    319     // Retrieve the subcollection names and sort them.
    320     if(subcollections.size() > 0) {
    321         Vector names = new Vector(subcollections.keySet());
    322         Collections.sort(names);
    323         for(int i = 0; i < names.size(); i++) {
    324         Subcollection sub =
    325             (Subcollection) subcollections.get(names.get(i));
    326         text = text + sub.toString();
    327         }
    328                 // Now add a entry, separated by spaces for each subcollection
    329                 // index.
    330         if(subindexes.size() > 0) {
    331         text = text + subindexes.toString();
    332         }
    333                 // Finally add the default subcollection index if necessary.
    334         if(default_index != null) {
    335         text = text + default_index.toString();
    336         }
    337         text = text + "\n";
    338     }
    339     // Otherwise if there were no subcollections, there aren't going to be
    340     // subcollection indexes, nor a default subcollection index are there.
    341     return text;
    342     }
     136     * @param subcollection the Subcollection you want to remove
     137     * @see org.greenstone.gatherer.Gatherer
     138     * @see org.greenstone.gatherer.collection.CollectionManager
     139     */
     140    public void removeSubcollection(Subcollection subcollection) {
     141    remove(subcollection);
     142    Gatherer.c_man.configurationChanged();
     143    }
     144
     145    public void updateSubcollection(Subcollection subcollection, String name, boolean include, String source, String pattern, String flags) {
     146    subcollection.setFlags(flags);
     147    subcollection.setInclusive(include);
     148    subcollection.setName(name);
     149    subcollection.setPattern(pattern);
     150    subcollection.setSource(source);
     151    refresh(subcollection);
     152    Gatherer.c_man.configurationChanged();
     153    }
     154
    343155    /** Method to retrieve a phrase from the dictionary based on a key.
    344       * @param key A <strong>String</strong> used to find the correct phrase.
    345       * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
    346       * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
    347       */
     156     * @param key A <strong>String</strong> used to find the correct phrase.
     157     * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
     158     * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
     159     */
    348160    private String get(String key) {
    349     return get(key, null);
    350     }
    351     /** Method to retrieve a phrase from the dictionary based on a key.
    352       * @param key A <strong>String</strong> used to find the correct phrase.
    353       * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
    354       * @see org.greenstone.gatherer.Dictionary
    355       * @see org.greenstone.gatherer.Gatherer
    356       */
    357     private String get(String key, String args[]) {
    358161    if(key.indexOf(".") == -1) {
    359         key = "CDM.SubcollectionManager." + key;
    360     }
    361     return gatherer.dictionary.get(key, args);
    362     }
     162        key = CLASS_DICTIONARY_NAME + key;
     163    }
     164    return Gatherer.dictionary.get(key);
     165    }
     166
    363167    /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
    364     private class Control
    365     extends JPanel {
    366     /** <i>true</i> if the current selection has changed. */
    367     private boolean changed = false;
    368     /** Button to add a subcollection. */
    369     private JButton add = null;
    370     /** Button to add a subindex. */
    371     private JButton add_index = null;
    372     /** Button to clear the default subindex. */
    373     private JButton clear_default = null;
    374     /** Button to remove a subcollection. */
    375     private JButton remove = null;
    376     /** Button to remove a subindex. */
    377     private JButton remove_index = null;
    378     /** Button to set the default subindex. */
    379     private JButton set_default = null;
    380     /** Button to cause an update of the subcollections. */
    381     private JButton update = null;
    382     /** A combobox allowing you to choose which field the data for matching should be taken from. Includes text body and filename, as well as all assigned metadata elements. */
    383     private JComboBox source = null;
    384     /** The list of assigned subcollections. */
    385     private JList subcollection_list = null;
    386     /** The list of subcollections available for the creation of subindexes. */
    387     private JList subcollection_list_2 = null;
    388     /** The list of assigned subindexes. */
    389     private JList subindexes_list = null;
    390     /** The label denoting the list of subindexes. */
    391     private JLabel subindexes_label = null;
    392     /** The panel containing the subcollection controls. */
    393     private JPanel subcollection_pane = null;
    394     /** The panel containing the subindex controls. */
    395     private JPanel subindex_pane = null;
    396     /** The tabbed pane used to store the subcollection and subindex controls. */
    397     private JTabbedPane tabbed_pane = null;
    398     /** The area used to display inline instructions. */
    399     private JTextArea instructions = null;
    400     /** The field displaying the name of the default subindex. */
    401     private JTextField default_value = null;
    402     /** A field used for specifying flags for the PERL expression matching, such as 'i' for case insensitive. */
    403     private JTextField flags = null;
    404     /** The pattern the source text must match. */
    405     private JTextField match = null;
    406     /** The name of this subcollection. */
    407     private JTextField name = null;
    408     /** The name of this subindex. */
    409     private JTextField subindex_name;
    410     /** When this button is selected the filter matching files are excluded. */
    411     private JToggleButton exclude = null;
    412     /** When this button is selected the filter matching files are included. */
    413     private JToggleButton include = null;
    414     /** The existing subcollection whose details you are reviewing, if any. */
    415     private Subcollection current = null;
    416     /** Constructor, creates the outer parts of the view, then calls two methods in turn to create the subcollection controls and subindex controls.
    417      */
    418     public Control() {
     168    private class SubcollectionControl
     169    extends JPanel
     170    implements Control {
     171
     172    private JButton add_button;
     173    private JButton remove_button;
     174    private JButton update_button;
     175    private JComboBox source_combobox;
     176    private JList subcollection_list;
     177    private JTabbedPane tabbed_pane;
     178    private JTextArea instructions_area;
     179    private JTextField flags_field;
     180    private JTextField match_field;
     181    private JTextField name_field;
     182    private JToggleButton exclude_button;
     183    private JToggleButton include_button;
     184
     185    /** Constructor */
     186    public SubcollectionControl() {
    419187        // Create
    420188        JPanel border_pane = new JPanel();
    421189        JPanel header_pane = new JPanel();
    422         instructions = new JTextArea(get("Instructions"));
    423         instructions.setEditable(false);
    424         instructions.setLineWrap(true);
    425         instructions.setRows(5);
    426         instructions.setWrapStyleWord(true);
     190        instructions_area = new JTextArea(get("Instructions"));
     191        instructions_area.setEditable(false);
     192        instructions_area.setLineWrap(true);
     193        instructions_area.setRows(5);
     194        instructions_area.setWrapStyleWord(true);
    427195        tabbed_pane = new JTabbedPane();
    428196        JLabel title = new JLabel(get("Title"));
    429197        title.setHorizontalAlignment(JLabel.CENTER);
    430         createSubCollection();
    431         createSubIndex();
     198       
     199        JPanel button_pane_3 = new JPanel();
     200        add_button = new JButton(get("Add"));
     201        add_button.setMnemonic(KeyEvent.VK_A);
     202        add_button.setEnabled(false);
     203        remove_button = new JButton(get("Remove"));
     204        remove_button.setMnemonic(KeyEvent.VK_R);
     205        remove_button.setEnabled(false);
     206        update_button = new JButton(get("Update"));
     207        update_button.setMnemonic(KeyEvent.VK_C);
     208        update_button.setEnabled(false);
     209
     210        JPanel button_pane = new JPanel();
     211        JPanel button_pane_1 = new JPanel();
     212        exclude_button = new JToggleButton(get("Exclude"));
     213        exclude_button.setMnemonic(KeyEvent.VK_X);
     214        flags_field = new NonWhitespaceField();
     215        JLabel flags_label = new JLabel(get("Flags"));
     216        include_button = new JToggleButton(get("Include"));
     217        include_button.setMnemonic(KeyEvent.VK_I);
     218        JLabel inclusive_label = new JLabel(get("Inclusive"));
     219        JPanel inclusive_pane = new JPanel();
     220        match_field = new JTextField();
     221        JLabel match_label = new JLabel(get("Match"));
     222        name_field = new NonWhitespaceField();
     223        JLabel name_label = new JLabel(get("Name"));
     224        Vector source_model = Gatherer.c_man.getCollection().msm.getAssignedElements();
     225        source_model.add(0, StaticStrings.FILENAME_STR);
     226        source_combobox = new JComboBox(source_model);
     227        JLabel source_label = new JLabel(get("Source"));
     228        subcollection_list = new JList(model);
     229        subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     230        JPanel subcollection_pane = new JPanel();
     231        ButtonGroup bg = new ButtonGroup();
     232        bg.add(include_button);
     233        bg.add(exclude_button);
     234        include_button.setSelected(true);
     235        JPanel subcollection_list_pane = new JPanel();
     236        JLabel subcollection_list_label = new JLabel(get("Assigned"));
     237
    432238        // Add listeners
     239        SubCollectionChangeListener cl = new SubCollectionChangeListener();
     240        add_button.addActionListener(new AddSubCollectionListener());
     241        remove_button.addActionListener(new RemoveSubCollectionListener());
     242        update_button.addActionListener(new UpdateSubCollectionListener());
     243        exclude_button.addActionListener(cl);
     244        include_button.addActionListener(cl);
     245        source_combobox.addActionListener(cl);
     246        flags_field.getDocument().addDocumentListener(cl);
     247        match_field.getDocument().addDocumentListener(cl);
     248        name_field.getDocument().addDocumentListener(cl);
     249        subcollection_list.addListSelectionListener(new SubCollectionListListener());
     250
    433251        // Layout
    434         instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
     252        instructions_area.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
     253
    435254        header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    436255        header_pane.setLayout(new BorderLayout());
    437256        header_pane.add(title, BorderLayout.NORTH);
    438         header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
    439         tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane);
    440         tabbed_pane.addTab(get("Subindex_Controls"), subindex_pane);
    441         tabbed_pane.addTab(get("Language_Controls"), manager.languages.getControls());
    442         border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
    443         border_pane.setLayout(new BorderLayout());
    444         border_pane.add(tabbed_pane, BorderLayout.CENTER);
    445         setLayout(new BorderLayout());
    446         add(header_pane, BorderLayout.NORTH);
    447         add(border_pane, BorderLayout.CENTER);
    448     }
    449     /** Create the subcollection controls.
    450      * @see org.greenstone.gatherer.Gatherer
    451      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddListener
    452      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ListListener
    453      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveListener
    454      * @see org.greenstone.gatherer.collection.CollectionManager
    455      * @see org.greenstone.gatherer.msm.MetadataSetManager
    456      */
    457     public void createSubCollection() {
    458         // Create
    459         add = new JButton(get("Add"));
    460         add.setMnemonic(KeyEvent.VK_A);
    461         add.setEnabled(false);
    462         JPanel button_pane = new JPanel();
    463         JPanel button_pane_1 = new JPanel();
    464         JPanel button_pane_3 = new JPanel();
    465         exclude = new JToggleButton(get("Exclude"));
    466         exclude.setMnemonic(KeyEvent.VK_X);
    467         flags = new JTextField();
    468         JLabel flags_label = new JLabel(get("Flags"));
    469         include = new JToggleButton(get("Include"));
    470         include.setMnemonic(KeyEvent.VK_I);
    471         JLabel inclusive_label = new JLabel(get("Inclusive"));
    472         JPanel inclusive_pane = new JPanel();
    473         match = new JTextField();
    474         JLabel match_label = new JLabel(get("Match"));
    475         name = new JTextField();
    476         JLabel name_label = new JLabel(get("Name"));
    477         remove = new JButton(get("Remove"));
    478         remove.setMnemonic(KeyEvent.VK_R);
    479         remove.setEnabled(false);
    480         Vector source_model = gatherer.c_man.msm.getAssignedElements();
    481         source_model.add(0, "Filename");
    482         source = new JComboBox(source_model);
    483         JLabel source_label = new JLabel(get("Source"));
    484         subcollection_list = new JList(model);
    485         subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    486         subcollection_pane = new JPanel();
    487         ButtonGroup bg = new ButtonGroup();
    488         bg.add(include);
    489         bg.add(exclude);
    490         include.setSelected(true);
    491         JPanel subcollection_list_pane = new JPanel();
    492         JLabel subcollection_list_label = new JLabel(get("Assigned"));
    493 
    494         // Add listeners
    495         SubCollectionChangeListener cl = new SubCollectionChangeListener();
    496         add.addActionListener(new AddSubCollectionListener());
    497         remove.addActionListener(new RemoveSubCollectionListener());
    498         subcollection_list.addListSelectionListener(new SubCollectionListListener());
    499         //exclude.addActionListener(cl);
    500         //include.addActionListener(cl);
    501         //source.addActionListener(cl);
    502         //flags.addDocumentListener(cl);
    503         match.getDocument().addDocumentListener(cl);
    504         name.getDocument().addDocumentListener(cl);
    505 
    506         // Layout
     257        header_pane.add(new JScrollPane(instructions_area), BorderLayout.CENTER);
     258
    507259        inclusive_pane.setLayout(new GridLayout());
    508         inclusive_pane.add(include);
    509         inclusive_pane.add(exclude);
     260        inclusive_pane.add(include_button);
     261        inclusive_pane.add(exclude_button);
     262
    510263        button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
    511264        button_pane_1.setLayout(new GridLayout(5, 2));
    512265        button_pane_1.add(name_label);
    513         button_pane_1.add(name);
     266        button_pane_1.add(name_field);
    514267        button_pane_1.add(source_label);
    515         button_pane_1.add(source);
     268        button_pane_1.add(source_combobox);
    516269        button_pane_1.add(match_label);
    517         button_pane_1.add(match);
     270        button_pane_1.add(match_field);
    518271        button_pane_1.add(inclusive_label);
    519272        button_pane_1.add(inclusive_pane);
    520273        button_pane_1.add(flags_label);
    521         button_pane_1.add(flags);
     274        button_pane_1.add(flags_field);
     275
    522276        button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
    523         button_pane_3.setLayout(new GridLayout(1,2));
    524         button_pane_3.add(add);
    525         button_pane_3.add(remove);
     277        button_pane_3.setLayout(new GridLayout(1,3));
     278        button_pane_3.add(add_button);
     279        button_pane_3.add(update_button);
     280        button_pane_3.add(remove_button);
     281
    526282        button_pane.setLayout(new BorderLayout());
    527283        button_pane.add(button_pane_1, BorderLayout.CENTER);
    528284        button_pane.add(button_pane_3, BorderLayout.SOUTH);
     285
    529286        subcollection_list_pane.setLayout(new BorderLayout());
    530287        subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
     
    534291        subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
    535292        subcollection_pane.add(button_pane, BorderLayout.SOUTH);
    536     }
    537     /** Create the subindex controls.
    538      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddSubIndexListener
    539      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ClearDefaultListener
    540      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ChangeListener
    541      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveSubIndexListener
    542      * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.SetDefaultListener
    543      * @see org.greenstone.gatherer.util.ExclusiveListListener
    544      */
    545     public void createSubIndex() {
    546         // Creation
    547         JPanel subindex_name_panel = new JPanel();
    548         JLabel subindex_name_label = new JLabel(get("PartitionName"));
    549         subindex_name = new JTextField();
    550 
    551         add_index = new JButton(get("Add_Subindex"));
    552         add_index.setMnemonic(KeyEvent.VK_A);
    553         add_index.setEnabled(false);
    554         JPanel button_pane_2 = new JPanel();
    555         clear_default = new JButton(get("Clear_Default_Subindex"));
    556         clear_default.setMnemonic(KeyEvent.VK_C);
    557         if(default_index == null) {
    558         clear_default.setEnabled(false);
    559         }
    560         JLabel default_label = new JLabel(get("Default_Subindex"));
    561         JPanel default_pane = new JPanel();
    562         if(default_index == null) {
    563         default_value = new JTextField();
    564         }
    565         else {
    566         default_value = new JTextField(default_index.getSubIndex().toString());
    567         }
    568         default_value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
    569         default_value.setEditable(false);
    570         JPanel subindex_inner_pane_1 = new JPanel();
    571         JPanel subindex_inner_pane_2 = new JPanel();
    572         remove_index = new JButton(get("Remove_Subindex"));
    573         remove_index.setMnemonic(KeyEvent.VK_R);
    574         set_default = new JButton(get("Set_Default_Subindex"));
    575         set_default.setMnemonic(KeyEvent.VK_S);
    576         JLabel subcollection_label = new JLabel(get("Subcollection"));
    577         subcollection_list_2 = new JList(model);
    578         JPanel list_2_pane = new JPanel();
    579         subindex_pane = new JPanel();
    580         JLabel subindexes_label = new JLabel(get("Subindexes"));
    581         subindexes_list = new JList(subindexes);
    582         subindexes_list.setCellRenderer(new SubIndexListCellRenderer());
    583         subindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    584         JPanel subindexes_pane = new JPanel();
    585 
    586         // Add listeners
    587         ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener();
    588         ell.add(subcollection_list_2);
    589         ell.add(subindexes_list);
    590         add_index.addActionListener(new AddSubIndexListener());
    591         clear_default.addActionListener(new ClearDefaultSubIndexListener());
    592         remove_index.addActionListener(new RemoveSubIndexListener());
    593         set_default.addActionListener(new SetDefaultSubIndexListener());
    594 
    595         subindex_name.getDocument().addDocumentListener(new SubIndexNameDocumentListener());
    596         subcollection_list_2.addListSelectionListener(new SubCollectionList2Listener());
    597 
    598         // Layout
    599         subindex_name_panel.setLayout(new BorderLayout());
    600         subindex_name_panel.add(subindex_name_label, BorderLayout.WEST);
    601         subindex_name_panel.add(subindex_name, BorderLayout.CENTER);
    602 
    603         list_2_pane.setLayout(new BorderLayout());
    604         list_2_pane.add(subcollection_label, BorderLayout.NORTH);
    605         list_2_pane.add(new JScrollPane(subcollection_list_2), BorderLayout.CENTER);
    606        
    607         subindexes_pane.setLayout(new BorderLayout());
    608         subindexes_pane.add(subindexes_label, BorderLayout.NORTH);
    609         subindexes_pane.add(new JScrollPane(subindexes_list), BorderLayout.CENTER);
    610        
    611         subindex_inner_pane_2.setLayout(new GridLayout(1,2,0,5));
    612         subindex_inner_pane_2.add(list_2_pane);
    613         subindex_inner_pane_2.add(subindexes_pane);
    614        
    615         default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
    616         default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()), BorderFactory.createEmptyBorder(2,2,2,2)));
    617         default_pane.setLayout(new BorderLayout());
    618         default_pane.add(default_label, BorderLayout.WEST);
    619         default_pane.add(default_value, BorderLayout.CENTER);
    620        
    621         subindex_inner_pane_1.setLayout(new BorderLayout());
    622         subindex_inner_pane_1.add(subindex_name_panel, BorderLayout.NORTH);
    623         subindex_inner_pane_1.add(subindex_inner_pane_2, BorderLayout.CENTER);
    624         subindex_inner_pane_1.add(default_pane, BorderLayout.SOUTH);
    625        
    626         button_pane_2.setLayout(new GridLayout(2,2));
    627         button_pane_2.add(add_index);
    628         button_pane_2.add(remove_index);
    629         button_pane_2.add(clear_default);
    630         button_pane_2.add(set_default);
    631        
    632         subindex_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    633         subindex_pane.setLayout(new BorderLayout());
    634         subindex_pane.add(subindex_inner_pane_1, BorderLayout.CENTER);
    635         subindex_pane.add(button_pane_2, BorderLayout.SOUTH);
    636     }
    637    
    638    
     293
     294        tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane);
     295        tabbed_pane.addTab(get("Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
     296        tabbed_pane.addTab(get("Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
     297
     298        border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
     299        border_pane.setLayout(new BorderLayout());
     300        border_pane.add(tabbed_pane, BorderLayout.CENTER);
     301
     302        setLayout(new BorderLayout());
     303        add(header_pane, BorderLayout.NORTH);
     304        add(border_pane, BorderLayout.CENTER);
     305    }
     306       
    639307    /** Method to unregister any listeners to avoid memory leaks.
    640308     */
    641309    public void destroy() {
    642310    }
    643     /** We have overriden this method to provide completely different functionality, given that our JPanel will never actually have focus. We call this method in GUI on the view we are about to replace, and this method checks if a change has occured and if so updates the current object.
    644      * @return A <i>boolean</i> which is always <i>false</i>.
    645      * @see org.greenstone.gatherer.msm.ElementWrapper
    646      */
    647     public boolean hasFocus() {
    648         // If we have a current metadata open, and something has changed then save the change.
    649         if(changed && current != null) {
    650         String n = name.getText();
    651         String s = null;
    652         Object o = source.getSelectedItem();
    653         if(o instanceof ElementWrapper) {
    654             ElementWrapper e = (ElementWrapper)o;
    655             s = e.toString();
    656         }
    657         String e = match.getText();
    658         String f = flags.getText();
    659         if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
    660             current.update(n, s, e, include.isSelected(), f);
    661             int index = model.indexOf(current);
    662             changed();
    663             subindexes.changed();
    664             if(default_index != null) {
    665             default_value.setText(default_index.getSubIndex().toString());
    666             }
    667         }
    668         changed = false;
    669         }
    670         return false;
    671     }
    672     /** Overriden to ensure the instructions are scrolled to top.
    673      */
    674     public void updateUI() {
    675         if(instructions != null) {
    676         instructions.setCaretPosition(0);
    677         }
    678         super.updateUI();
    679     }
    680 
    681     /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values.
    682      * we want to disable add until a new name is present
    683      */
    684     protected void validateAdd() {
    685         if(changed && name.getText().length() > 0 && match.getText().length() > 0) {
    686         if (subcollections.containsKey(name.getText())) {
    687             add.setEnabled(false);
    688         } else {
    689             add.setEnabled(true);
    690         }
    691         }
    692         else {
    693         add.setEnabled(false);
    694         }
    695     }
     311
     312    public void gainFocus() {
     313        // Rebuild the sources combobox
     314        Vector source_model = Gatherer.c_man.getCollection().msm.getAssignedElements();
     315        source_model.add(0, "Filename"); // Add filename as a possible source.
     316        source_combobox.setModel(new DefaultComboBoxModel(source_model));
     317    }
     318
     319    public void loseFocus() {
     320    }
     321
    696322    /** Listens for actions apon the 'add' button in the SubcollectionManager controls, and if detected calls the addSubcollection method of the manager with a newly created subcollection. */
    697323    private class AddSubCollectionListener
     
    703329         */
    704330        public void actionPerformed(ActionEvent event) {
    705         String n = name.getText(); // not allowed spaces!
    706         if (n.indexOf(' ')!=-1) {
    707             n = n.substring(0, n.indexOf(' '));
    708             name.setText(n);
    709         }
    710         String s = null;
    711         Object o = source.getSelectedItem();
    712         if(o instanceof ElementWrapper) {
    713             ElementWrapper e = (ElementWrapper)o;
    714             s = e.toString();
    715         }
    716         String e = match.getText();
    717         String f = flags.getText();
    718         if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
    719             Subcollection sub = new Subcollection(n, include.isSelected(), s, e, f);
    720             addSubcollection(sub);
    721         }
    722         changed = false;
    723         validateAdd();
    724         }
    725     }
    726     /** 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. */
    727     private class AddSubIndexListener
    728         implements ActionListener {
    729         /** 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.
    730          * @param event An <strong>ActionEvent</strong> containing information about the event.
    731          * @see org.greenstone.gatherer.cdm.SubIndex
    732          */
    733         public void actionPerformed(ActionEvent event) {
    734         if(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0) {
    735             Vector selected = new Vector();
    736             Object raw[] = subcollection_list_2.getSelectedValues();
    737             for(int i = 0; i < raw.length; i++) {
    738             selected.add(raw[i]);
     331        String name = name_field.getText();
     332        String source = null;
     333        Object object = source_combobox.getSelectedItem();
     334        if(object instanceof ElementWrapper) {
     335            ElementWrapper element_wrapper = (ElementWrapper)object;
     336            source = element_wrapper.getName();
     337            if(source.indexOf(MSMUtils.NS_SEP) == -1) {
     338            source = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + source;
    739339            }
    740             SubIndex subindex = new SubIndex(selected);
    741             addSubIndex(subindex);
    742             // Add the subindexes name.
    743             CollectionMeta metadata = new CollectionMeta(manager, subindex, manager.languages.getDefaultLanguage(), subindex_name.getText());
    744             manager.collectionmetadatum.addMetadata(metadata);
    745         }
    746         }
    747     }
    748     /** This class listens for any key entry in a text field, selection change in a combobox or button click, and when detected sets the changed flag to true. Its also convenient to use this class to test if the add button should be active yet. */
     340        }
     341        else {
     342            source = object.toString();
     343        }
     344        String pattern = match_field.getText();
     345        String flags = flags_field.getText();
     346        if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
     347            Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
     348            addSubcollection(subcollection);
     349            // Change the selection to the new subcollection
     350            subcollection_list.setSelectedValue(subcollection, true);
     351        }
     352        add_button.setEnabled(false);
     353        }
     354    }
     355
     356    /** This class listens for any key entry in a text field, selection change in a combobox or button click, and updates a subcollection as appropriate. Its also convenient to use this class to test if the add button should be active yet. */
    749357    private class SubCollectionChangeListener
    750358        implements DocumentListener, ActionListener {
     
    753361         */
    754362        public void actionPerformed(ActionEvent event) {
    755         changed = true;
    756363        validateAdd();
    757364        }
    758365
    759366        public void changedUpdate(DocumentEvent event) {
    760         changed = true;
    761367        validateAdd();
    762368        }
     369
    763370        public void insertUpdate(DocumentEvent event) {
    764         changed = true;
    765371        validateAdd();
    766372
     
    768374
    769375        public void removeUpdate(DocumentEvent event) {
    770         changed = true;
    771376        validateAdd();
    772377        }
    773     }
    774     /** Listens for actions apon the 'clear default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex() method of the manager with <i>null</i>. */
    775     private class ClearDefaultSubIndexListener
    776         implements ActionListener {
    777         /** 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.
    778          * @param event An <strong>ActionEvent</strong> containing information about the event.
    779          */
    780         public void actionPerformed(ActionEvent event) {
    781         setDefaultSubIndex(null);
    782         clear_default.setEnabled(false);
    783         default_value.setText("");
    784         }
    785     }
     378
     379        /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
     380        private void validateAdd() {
     381        if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
     382            if (getSubcollection(name_field.getText()) == null) {
     383            add_button.setEnabled(true);
     384            } else {
     385            add_button.setEnabled(false);
     386            }
     387        }
     388        else {
     389            add_button.setEnabled(false);
     390        }
     391        }
     392    }
     393
    786394    /** Listens for actions apon the 'remove' button in the SubcollectionManager controls, and if detected calls the remove method of the manager with the SubIndex selected for removal. */
    787395    private class RemoveSubCollectionListener
     
    793401        public void actionPerformed(ActionEvent event) {
    794402        if(!subcollection_list.isSelectionEmpty()) {
    795             Subcollection sub_col = (Subcollection)subcollection_list.getSelectedValue();
    796             removeSubIndexes(sub_col);
    797             removeSubcollection(sub_col);
    798         }
    799         }
    800     }
    801     /** Listens for actions apon the 'remove subindex' button in the SubcollectionManager controls, and if detected calls the removeSubIndex method of the manager with the SubIndex selected for removal. */
    802     private class RemoveSubIndexListener
     403            Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
     404            removeSubcollection(subcollection);
     405            // And remove subcollection indexes dependant on this subcollection
     406            CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
     407        }
     408        remove_button.setEnabled(false);
     409        }
     410    }
     411
     412    private class UpdateSubCollectionListener
    803413        implements ActionListener {
    804         /** 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.
    805          * @param event An <strong>ActionEvent</strong> containing information about the event.
    806          * @see org.greenstone.gatherer.cdm.SubIndex
    807          */
    808414        public void actionPerformed(ActionEvent event) {
    809         if(!subindexes_list.isSelectionEmpty()) {
    810             removeSubIndex((SubIndex)subindexes_list.getSelectedValue());
    811         }
    812         }
    813     }
    814     /** Listens for actions apon the 'set default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex method of the manager with the SubIndex selected for default. */
    815     private class SetDefaultSubIndexListener
    816         implements ActionListener {
    817         /** 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.
    818          * @param event An <strong>ActionEvent</strong> containing information about the event.
    819          * @see org.greenstone.gatherer.cdm.DefaultSubIndex
    820          * @see org.greenstone.gatherer.cdm.SubIndex
    821          */
    822         public void actionPerformed(ActionEvent event) {
    823         if(!subindexes_list.isSelectionEmpty()) {
    824             setDefaultSubIndex(new DefaultSubIndex((SubIndex)subindexes_list.getSelectedValue()));
    825             clear_default.setEnabled(true);
    826             default_value.setText(default_index.getSubIndex().toString());
    827         }
    828         }
    829     }
    830 
     415        if(!subcollection_list.isSelectionEmpty()) {
     416            Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
     417            String name = name_field.getText();
     418            String source = null;
     419            Object object = source_combobox.getSelectedItem();
     420            if(object instanceof ElementWrapper) {
     421            ElementWrapper element_wrapper = (ElementWrapper)object;
     422            source = element_wrapper.getName();
     423            if(source.indexOf(MSMUtils.NS_SEP) == -1) {
     424                source = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + source;
     425            }
     426            }
     427            else {
     428            source = object.toString();
     429            }
     430            String pattern = match_field.getText();
     431            String flags = flags_field.getText();
     432            if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
     433            updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
     434            }
     435        }
     436        }
     437    }
    831438
    832439    /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
     
    839446         */
    840447        public void valueChanged(ListSelectionEvent event) {
    841         // If we have a previous collection and the users changed something, but not added, then update subcollection.
    842         if(changed && current != null) {
    843             String n = name.getText();
    844             String s = null;
    845             Object o = source.getSelectedItem();
    846             if(o instanceof ElementWrapper) {
    847             ElementWrapper e = (ElementWrapper)o;
    848             s = e.toString();
    849             }
    850             String e = match.getText();
    851             String f = flags.getText();
    852             if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
    853             current.update(n, s, e, include.isSelected(), f);
    854             int index = model.indexOf(current);
    855             changed();
    856             subindexes.changed();
    857             if(default_index != null) {
    858                 default_value.setText(default_index.getSubIndex().toString());
    859             }
    860             }
    861         }
    862         // Now load the new entry.
     448        // Now the entry
    863449        if(!subcollection_list.isSelectionEmpty()) {
    864             current = (Subcollection) subcollection_list.getSelectedValue();
    865             flags.setText(current.getFlags());
    866             include.setSelected(current.getInclude());
    867             exclude.setSelected(!current.getInclude());
    868             match.setText(current.getExpression());
    869             name.setText(current.getName());
    870             String s = current.getSource();
     450            Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
     451            flags_field.setText(subcollection.getFlags());
     452            include_button.setSelected(subcollection.isInclusive());
     453            exclude_button.setSelected(!subcollection.isInclusive());
     454            match_field.setText(subcollection.getPattern());
     455            name_field.setText(subcollection.getName());
     456            String s = subcollection.getSource();
    871457            int pos = 0;
    872             Object value = source.getItemAt(pos);
     458            Object value = source_combobox.getItemAt(pos);
     459            //ystem.err.println("Search for: " + s);
    873460            while(value != null) {
    874461            if(value instanceof ElementWrapper) {
    875462                ElementWrapper e = (ElementWrapper) value;
    876                 if(e.toString().equals(s)) {
    877                 source.setSelectedIndex(pos);
     463                String e_name = e.getName();
     464                if(e_name.indexOf(MSMUtils.NS_SEP) == -1) {
     465                e_name = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + e_name;
     466                }
     467                //ystem.err.print("Compare to: " + e_name);
     468                if(e_name.equals(s)) {
     469                source_combobox.setSelectedIndex(pos);
    878470                value = null;
     471                //ystem.err.println(" - Match");
    879472                }
    880473                else {
    881474                pos++;
    882                 value = source.getItemAt(pos);
     475                value = source_combobox.getItemAt(pos);
     476                //ystem.err.println(" - Fail");
    883477                }
    884478            }
    885479            else if(value.toString().equals(s)) {
    886                 source.setSelectedIndex(pos);
     480                source_combobox.setSelectedIndex(pos);
    887481                value = null;
    888482            }
    889483            else {
    890484                pos++;
    891                 value = source.getItemAt(pos);
     485                value = source_combobox.getItemAt(pos);
    892486            }
    893487            }
    894488            // Can't add one thats already there.
    895             add.setEnabled(false);
    896             // You can remove it though...
    897             remove.setEnabled(true);
     489            add_button.setEnabled(false);
     490            // You can update or remove it though...
     491            remove_button.setEnabled(true);
     492            update_button.setEnabled(true);
    898493        }
    899494        else {
    900             flags.setText("");
    901             include.setSelected(true);
    902             match.setText("");
    903             name.setText("");
    904             source.setSelectedIndex(0);
    905             remove.setEnabled(false);
    906         }
    907         // Have to do this after so we don't get called when nothings actually changed.
    908         changed = false;
    909        
    910         }
    911     }
    912 
    913     private class SubCollectionList2Listener
    914         implements ListSelectionListener {
    915 
    916         public void valueChanged(ListSelectionEvent event) {
    917         if(!event.getValueIsAdjusting()) {
    918             add_index.setEnabled(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0);
    919         }
    920         }
    921     }
    922    
    923     private class SubIndexListCellRenderer
    924         extends DefaultListCellRenderer {
    925        
    926         public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    927         StringBuffer text = new StringBuffer(value.toString());
    928         // Retrieve the indexes name if any.
    929         CollectionMeta metadata = manager.collectionmetadatum.getMetadata(value, manager.languages.getDefaultLanguage(), true);
    930         if(metadata != null) {
    931             text.append(" \"");
    932             text.append(metadata.getValue());
    933             text.append("\"");
    934         }
    935         return super.getListCellRendererComponent(list, text.toString(), index, isSelected, cellHasFocus);
    936         }
    937 
    938     }
    939    
    940     private class SubIndexNameDocumentListener
    941         implements DocumentListener {
    942         /** Gives notification that an attribute or set of attributes changed. */
    943         public void changedUpdate(DocumentEvent e) {
    944         update();
    945         }
    946         /** Gives notification that there was an insert into the document. */
    947         public void insertUpdate(DocumentEvent e) {
    948         update();
    949         }
    950         /** Gives notification that a portion of the document has been removed. */
    951         public void removeUpdate(DocumentEvent e) {
    952         update();
    953         }
    954         /** 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. */
    955         private void update() {
    956         add_index.setEnabled(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0);
    957         }
    958     }
    959 
     495            flags_field.setText("");
     496            include_button.setSelected(true);
     497            match_field.setText("");
     498            name_field.setText("");
     499            source_combobox.setSelectedIndex(0);
     500            remove_button.setEnabled(false);
     501            update_button.setEnabled(false);
     502        }
     503        }
     504    }
    960505    }
    961506}
Note: See TracChangeset for help on using the changeset viewer.