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/PlugInManager.java

    r4838 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;
    44 /**
    45  * Title:        The Gatherer<br>
    46  * Description:  The Gatherer: a tool for gathering and enriching digital collections.<br>
    47  * Copyright:    Copyright (c) 2001<br>
    48  * Company:      The University of Waikato<br>
    49  * First Coded:  01/05/02
    50  * @author John Thompson, Greenstone Digital Libraries
    51  * @version 2.1
    52  */
     28
    5329import java.awt.*;
    5430import java.awt.event.*;
     
    5733import javax.swing.*;
    5834import javax.swing.event.*;
    59 import javax.swing.plaf.basic.BasicArrowButton;
    60 import org.apache.xerces.parsers.DOMParser;
     35import javax.swing.plaf.basic.*;
     36import org.apache.xerces.parsers.*;
    6137import org.greenstone.gatherer.Gatherer;
    6238import org.greenstone.gatherer.cdm.Argument;
    6339import org.greenstone.gatherer.cdm.ArgumentConfiguration;
     40import org.greenstone.gatherer.cdm.CollectionDesignManager;
    6441import org.greenstone.gatherer.cdm.CommandTokenizer;
     42import org.greenstone.gatherer.cdm.Control;
    6543import org.greenstone.gatherer.cdm.DynamicListModel;
    6644import org.greenstone.gatherer.cdm.PlugIn;
    67 import org.greenstone.gatherer.msm.ElementWrapper;
     45import org.greenstone.gatherer.gui.GComboBox;
    6846import org.greenstone.gatherer.msm.MSMUtils;
     47import org.greenstone.gatherer.util.StaticStrings;
    6948import org.greenstone.gatherer.util.Utility;
    7049import org.w3c.dom.*;
    71 import org.xml.sax.InputSource;
     50import org.xml.sax.*;
    7251/** This class is resposible for maintaining a list of known plug-ins, and importing new plugins using the parser. */
    73 public class PlugInManager {
    74     /** A reference to the main manager for this module. */
    75     private CollectionDesignManager manager = null;
     52public class PlugInManager
     53    extends DOMProxyListModel {
     54    /** The library 'reserve' of base plugins. */
     55    private ArrayList library = null;
    7656    /** The controls for editing the contents of this manager. */
    7757    private Control controls = null;
    78     /** A list of assigned plugins. */
    79     private DynamicListModel assigned = null;
    80     /** A list of those plugins that have not yet been assigned. Begins as a copy of reserve. */
    81     private DynamicListModel available = null;
    82     /** A list of known, but currently unassigned, plug-ins. */
    83     private DynamicListModel reserve = null;
    84     /** A reference to the Gatherer. */
    85     private Gatherer gatherer = null;
    86     /** The current index of the separator. */
    87     private JPanel separator = null;
     58    private DOMProxyListModel model;
     59    private JPanel separator;
     60    private PlugIn separator_plugin;
    8861    /** The default size for a label. */
    8962    static final private Dimension LABEL_SIZE = new Dimension(140, 20);
    9063    /** Constructor.
    9164     */
    92     public PlugInManager(Gatherer gatherer, CollectionDesignManager manager) {
    93     this.assigned = new DynamicListModel();
    94     this.gatherer = gatherer;
    95     this.manager = manager;
    96     this.separator = getSeparator();
    97     // Add the movement separator
    98     assigned.addElement(separator);
     65    public PlugInManager() {
     66    super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.PLUGIN_ELEMENT, new PlugIn());
     67    Gatherer.println("PlugInManager: " + getSize() + " plugins parsed.");
     68    model = this;
     69    // Reload/Create the library
    9970    loadPlugIns();
    10071    savePlugIns();
    101     }
    102     /** Method to add a new plugin to reserve.
    103       * @param plugin The new <strong>PlugIn</strong>.
    104       */
     72    // Create the separator, cause we can reuse it.
     73    separator = getSeparator();
     74    }
     75    /** Method to add a new plugin to the library
     76     * @param plugin the new base PlugIn
     77     */
    10578    public void addPlugIn(PlugIn plugin) {
    106     if(!reserve.contains(plugin)) {
    107         reserve.addElement(plugin);
    108         available.addElement(plugin);
    109     }
    110     }
    111     /** Method to assign a plugin.
    112       * @param plugin The reserve <strong>PlugIn</strong> to assign.
    113       */
     79    if(!library.contains(plugin)) {
     80        library.add(plugin);
     81    }
     82    }
     83
     84    /** Method to assign a plugin
     85     * @param plugin the PlugIn to assign
     86     */
    11487    public void assignPlugIn(PlugIn plugin) {
    115     if(!assigned.contains(plugin)) {
    116         if(plugin.getName().equals("RecPlug") || plugin.getName().equals("ArcPlug")) {
    117         assigned.addElement(plugin); // Adds after separator
    118         }
    119         else {
    120         int index = assigned.indexOf(separator);
    121         assigned.add(index, plugin);
    122         }
    123                 // Remove from available
    124         available.removeElement(plugin);
    125         gatherer.c_man.configurationChanged();
    126     }
    127     }
     88    if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR)) {
     89        addAfter(plugin, separator_plugin); // Adds after separator
     90    }
     91    else {
     92        addBefore(plugin, separator_plugin);
     93    }
     94    Gatherer.c_man.configurationChanged();
     95    }
     96
     97    /** Destructor. */
     98    public void destroy() {
     99    if(controls != null) {
     100        controls.destroy();
     101        controls = null;
     102    }
     103    library.clear();
     104    library = null;
     105    }
     106
    128107    /** Method to retrieve the control for this manager.
    129       * @return A <strong>JPanel</strong> containing the controls.
    130       */
    131     public JPanel getControls() {
     108     * @return the Control
     109     */
     110    public Control getControls() {
    132111    if(controls == null) {
    133         controls = new Control();
     112        // Build controls
     113        controls = new PlugInControl();
    134114    }
    135115    return controls;
    136116    }
    137     /** Method to retrieve the named plugin.
    138       * @param name The name of the desired plugin as a <strong>String</strong>.
    139       * @return The requested <strong>PlugIn</strong> or <i>null</i> if no such plugin exists.
    140       */
    141     public PlugIn getPlugIn(String name) {
    142     for(int i = 0; i < reserve.size(); i++) {
    143         Object object = reserve.get(i);
    144         if(object instanceof PlugIn) {
    145         PlugIn plugin = (PlugIn) object;
    146         if(plugin.getName().equals(name)) {
    147             return plugin;
    148         }
     117
     118    /** Retrieve the base pluging of the given name, or null if no such plugin.
     119     * @param name the name of the base plugin to retrieve as a String
     120     * @return the PlugIn requested or null if no such plugin
     121     */
     122    public PlugIn getBasePlugIn(String name) {
     123    int library_size = library.size();
     124    for(int i = 0; i < library_size; i++) {
     125        PlugIn plugin = (PlugIn) library.get(i);
     126        if(plugin.getName().equals(name)) {
     127        return plugin;
    149128        }
    150129    }
     
    152131    return null;
    153132    }
    154     /** Method to invalidate controls after a significant change in the system state.
    155       */
    156     public void invalidateControls() {
    157     if(controls != null) {
    158         controls.destroy();
    159     }
    160     controls = null;
    161     }
     133
     134    /** Method to move a plugin in the list order.
     135     * @param plugin the PlugIn you want to move.
     136     * @param direction true to move the plugin up, false to move it down.
     137     * @param all true to move to move all the way, false for a single step.
     138     */
     139    public void movePlugIn(PlugIn plugin, boolean direction, boolean all) {
     140    // Can't ever move RecPlug or ArcPlug.
     141    if(getSize() < 3) {
     142        Gatherer.println("Not enough plugins to allow moving.");
     143        return;
     144    }
     145    if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR)) {
     146        JOptionPane.showMessageDialog(Gatherer.g_man, get("CDM.Move.Fixed"), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
     147        return;
     148    }
     149    if(all) {
     150        // Move to top
     151        if(direction) {
     152        // Remove the moving plugin
     153        remove(plugin);
     154        // Retrieve the first plugin
     155        PlugIn first_plugin = (PlugIn) getElementAt(0);
     156        // Add the moving plugin before the first plugin
     157        addBefore(plugin, first_plugin);
     158        first_plugin = null;
     159        Gatherer.c_man.configurationChanged();
     160        }
     161        else {
     162        // Remove the moving plugin
     163        remove(plugin);
     164        // Locate the plugin immediately before the separator. We have to ensure the separator index is up to date, given we've just removed a plugin.
     165        int separator_index = -1;
     166        if((separator_index = findSeparatorIndex()) != -1) {
     167            PlugIn separator_plugin = (PlugIn) getElementAt(separator_index);
     168            // Add the moving plugin before the separator
     169            addBefore(plugin, separator_plugin);
     170            Gatherer.c_man.configurationChanged();     
     171        }
     172        // Otherwise we aren't moving anywhere!
     173        }
     174    }
     175    else {
     176        // Try to move the plugin one step in the desired direction.
     177        int index = indexOf(plugin);
     178        ///ystem.err.println("Index of " + plugin + " = " + index);
     179        if(direction) {
     180        index--;
     181        if(index < 0) {
     182            String args[] = new String[2];
     183            args[0] = get("CDM.PlugInManager.PlugIn_Str");
     184            args[1] = plugin.getName();
     185            JOptionPane.showMessageDialog(Gatherer.g_man, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
     186            return;
     187        }
     188        remove(plugin);
     189        add(index, plugin);
     190        Gatherer.c_man.configurationChanged();
     191        }
     192        else {
     193        index++;
     194        PlugIn next_plugin = (PlugIn) getElementAt(index);
     195        if(next_plugin.isSeparator()) {
     196            String args[] = new String[1];
     197            args[0] = plugin.getName();
     198            JOptionPane.showMessageDialog(Gatherer.g_man, get("CDM.Move.Cannot", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
     199            // Still not going to move RecPlug or ArcPlug.
     200            return;
     201        }
     202        remove(plugin);
     203        add(index, plugin);
     204        Gatherer.c_man.configurationChanged();
     205        }
     206    }
     207    }
     208
     209    /** We attempt to place the separator between the unfixed and the fixed plugins. Since we only know of two fixed plugins, we search for either of them, and place the separator before them.
     210     */
     211    public void placeSeparator() {
     212    ///ystem.err.println("Placing separator.");
     213    int separator_index = getSize();
     214    if(separator_index > 0) {
     215        boolean found_fixed = false;
     216        int index = separator_index - 1;
     217        while(index > 0) {
     218        PlugIn plugin = (PlugIn) getElementAt(index);
     219        String name = plugin.getName();
     220        if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR)) {
     221            found_fixed = true;
     222            index--;
     223        }
     224        else {
     225            if(found_fixed) {
     226            separator_index = index + 1;
     227            index = -1;
     228            }
     229            else {
     230            index--;
     231            }
     232        }
     233        name = null;
     234        plugin = null;
     235        }
     236    }
     237    Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
     238    element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, CollectionConfiguration.SEPARATOR_ATTRIBUTE);
     239    element.setAttribute(CollectionConfiguration.SEPARATOR_ATTRIBUTE, CollectionConfiguration.TRUE_STR);
     240    separator_plugin = new PlugIn(element, null);
     241    ///atherer.println("Adding plugin separator at: " + separator_index);
     242    add(separator_index, separator_plugin);
     243    }
     244
     245    /** This method removes an assigned plugin. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a plugin from the library.
     246     * @param plugin The <strong>PlugIn</strong> to remove.
     247     */
     248    public void removePlugIn(PlugIn plugin) {
     249    remove(plugin);
     250    Gatherer.c_man.configurationChanged();
     251    }
     252
     253    /** Method to cache the current contents of library (known plugins) to file.
     254     */
     255    public void savePlugIns() {
     256    try {
     257        FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "plugins.dat");
     258        ObjectOutputStream out = new ObjectOutputStream(file);
     259        out.writeObject(library);
     260        out.close();
     261    }
     262    catch (Exception error) {
     263        Gatherer.printStackTrace(error);
     264    }
     265    }
     266
     267    /** Determine the current separator index. */
     268    private int findSeparatorIndex() {
     269    int separator_index = getSize() - 1;
     270    while(separator_index >= 0) {
     271        PlugIn search = (PlugIn) getElementAt(separator_index);
     272        if(search.isSeparator()) {
     273        return separator_index;
     274        }
     275        separator_index--;
     276    }
     277    return separator_index;
     278    }
     279
     280    /* Retrieve a phrase from the dictionary based on a certain key.
     281     * @param key The search <strong>String</strong>.
     282     * @return The matching phrase from the Dictionary.
     283     */
     284    private String get(String key) {
     285    return get(key, (String[])null);
     286    }
     287   
     288    private String get(String key, String arg) {
     289    String args[] = new String[1];
     290    args[0] = arg;
     291    return get(key, args);
     292    }
     293
     294    /* Retrieve a phrase from the dictionary based on a certain key and arguments.
     295     * @param key The search <strong>String</strong>.
     296     * @param args A <strong>String[]</strong> of arguments used to complete and format the choosen phrase.
     297     * @return The matching phrase from the Dictionary.
     298     */
     299    private String get(String key, String args[]) {
     300    if(key.indexOf(".") == -1) {
     301        key = "CDM.PlugInManager." + key;
     302    }
     303    return Gatherer.dictionary.get(key, args);
     304    }   
     305
     306    /** Retrieve a list of those plugins that are in library but not in the assigned plugins. */
     307    private Object[] getAvailable() {
     308    ArrayList available = new ArrayList();
     309    available.addAll(library);
     310    // Now go through the assigned plugins, and remove any that match.
     311    available.removeAll(children());
     312    return available.toArray();
     313    }
     314
     315    /** Method to extract just the plugins name from a file object.
     316     * @param plugin The <strong>File</strong> which references a certain plugin.
     317     * @return A <strong>String</strong> containing just the plugins name, without extension.
     318     */
     319    private String getPlugInName(File plugin) {
     320    String name = plugin.getName();
     321    if(name.indexOf(".") != -1) {
     322        name = name.substring(0, name.indexOf("."));
     323    }
     324    return name;
     325    }
     326
    162327    /** Method to load the details of a single plug-in.
    163       * @param plugin The plugin <strong>File</strong> you wish to load.
    164       */
    165     public void loadPlugIn(File plugin) {
     328     * @param plugin The plugin <strong>File</strong> you wish to load.
     329     */
     330    private void loadPlugIn(File plugin) {
    166331    Document document = null;
    167332    // Run pluginfo on this plugin, and then send the results for parsing.
     
    170335        if(Utility.isWindows()) {
    171336        args = new String[4];
    172         if(gatherer.config.perl_path != null) {
    173             args[0] = gatherer.config.perl_path;
     337        if(Gatherer.config.perl_path != null) {
     338            args[0] = Gatherer.config.perl_path;
    174339        }
    175340        else {
    176341            args[0] = "Perl.exe";
    177342        }
    178         args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "pluginfo.pl";
     343        args[1] = Gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "pluginfo.pl";
    179344        args[2] = "-xml";
    180345        args[3] = getPlugInName(plugin);
     
    229394    }
    230395    if(document != null) {
    231         parse(document.getDocumentElement());
    232     }
    233     }
    234     /** Method to move a plugin higher in the list order.
    235       * @param plugin The <strong>PlugIn</strong> you want to move.
    236       * @param direction <i>true</i> to move the plugin up, <i>false</i> to move it down.
    237       * @param all <i>true</i> to move to move all the way, <i>false</i> for a single step.
    238       */
    239     public void movePlugIn(PlugIn plugin, boolean direction, boolean all) {
    240     // Can't ever move RecPlug or ArcPlug.
    241     if(plugin.getName().equals("ArcPlug") || plugin.getName().equals("RecPlug")) {
    242         JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Fixed"), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
    243         return;
    244     }
    245     if(all) {
    246         if(direction) {
    247         assigned.removeElement(plugin);
    248         assigned.add(0, plugin);
    249         gatherer.c_man.configurationChanged();
    250         }
    251         else {
    252         assigned.removeElement(plugin);
    253         int index = assigned.size() - 1;
    254         boolean found = false;
    255         while(!found) {
    256             Object temp = assigned.get(index);
    257             if(temp instanceof PlugIn) {
    258             PlugIn current = (PlugIn) temp;
    259             if(current.getName().equals("ArcPlug") || current.getName().equals("RecPlug")) {
    260                 index--;
    261             }
    262             else {
    263                 found = true;
    264             }
    265             }
    266             else {
    267             found = true;
    268             }
    269         }
    270         assigned.add(index, plugin);
    271         gatherer.c_man.configurationChanged();
    272         }
    273     }
    274     else {
    275                 // Try to move the plugin one step in the desired direction.
    276         int index = assigned.indexOf(plugin);
    277                 ///ystem.err.println("Index of " + plugin + " = " + index);
    278         if(direction) {
    279         index--;
    280         if(index < 0) {
    281             String args[] = new String[1];
    282             args[0] = plugin.getName();
    283             JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
    284             return;
    285         }
    286         assigned.removeElement(plugin);
    287         assigned.add(index, plugin);
    288         gatherer.c_man.configurationChanged();
    289         }
    290         else {
    291         index++;
    292         Object object = assigned.get(index);
    293         if(index == assigned.size()) {
    294             String args[] = new String[1];
    295             args[0] = plugin.getName();
    296             JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Bottom", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
    297             // Still not going to move RecPlug or ArcPlug.
    298             return;
    299         }
    300         else if(!(object instanceof PlugIn) || ((PlugIn)object).getName().equals("ArcPlug") || ((PlugIn)object).getName().equals("RecPlug")) {
    301             String args[] = new String[1];
    302             args[0] = plugin.getName();
    303             JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Cannot", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
    304             // Still not going to move RecPlug or ArcPlug.
    305             return;
    306         }
    307         assigned.removeElement(plugin);
    308         assigned.add(index, plugin);
    309         gatherer.c_man.configurationChanged();
    310         }
    311     }
    312     }
    313 
    314     /** This method attempts to parse a plugin command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct plugin be matched by also all of the parameters given must be legal. If such a command is found, the plugin is immediately assigned.
    315       * @param command The coomand <strong>String</strong> that may include plugin information.
    316       * @return <i>true</i> if a plugin command was parsed, <i>false</i> otherwise.
    317       */
    318     public boolean parse(String command) {
    319     String command_lc = command.toLowerCase();
    320     if(command_lc.startsWith("plugin")) {
    321         CommandTokenizer tokenizer = new CommandTokenizer(command);
    322         if(tokenizer.countTokens() >= 2) {
    323         tokenizer.nextToken(); // Throw away 'plugin'
    324         String name = tokenizer.nextToken();
    325         // Try to locate the plugin with this name.
    326         PlugIn plugin = getPlugIn(name);
    327         // And if successful start to parse the arguments.
    328         if(plugin != null) {
    329             // Take a copy.
    330             plugin = plugin.copy();
    331             String key = null;
    332             while(tokenizer.hasMoreTokens()) {
    333             if(key == null) {
    334                 key = tokenizer.nextToken();
    335             }
    336             // Try to retrieve a matching argument.
    337             Argument argument = plugin.getArgument(key);
    338             if(argument != null) {
    339                 // Set as assigned.
    340                 argument.setAssigned(true);
    341                 // And if the argument is of a parameter type, parse a parameter.
    342                 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) {
    343                 String value = tokenizer.nextToken();
    344                 ElementWrapper element = null;
    345                 if(argument.getType() == Argument.METADATA) {
    346                     value = value.replace(':', MSMUtils.NS_SEP);
    347                     if (value.indexOf(MSMUtils.NS_SEP)==-1){
    348                     value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
    349                     }
    350                     // Now retrieve the element this refers to, if available.
    351                     element = Gatherer.c_man.getCollection().msm.getElement(value);
    352                 }
    353                 if(element != null) {
    354                     argument.setElementValue(element);
    355                     element = null;
    356                 }
    357                 else {
    358                     argument.setValue(value);
    359                 }
    360                 }
    361                 key = null;
    362             }
    363             // Argument cannot be matched.
    364             else {
    365                 String cur_key = key;
    366                 String value = tokenizer.nextToken();
    367                 if(value.startsWith("-")) {
    368                 key = value;
    369                 value = null;
    370                 }
    371                 else {
    372                 key = null;
    373                 }
    374                 String custom = plugin.getCustom();
    375                 if(custom == null) {
    376                 if(value == null) {
    377                     plugin.setCustom(cur_key);
    378                 }
    379                 else {
    380                     plugin.setCustom(cur_key + " " + value);
    381                 }
    382                 }
    383                 else {
    384                 if(value == null) {
    385                     plugin.setCustom(custom + " " + cur_key);
    386                 }
    387                 else {
    388                     plugin.setCustom(custom + " " + cur_key + " " + value);
    389                 }
    390                 }
    391             }
    392             }
    393             // Slight tweak. If the plugin is the RecPlug we want to set use_metadata_files by default.
    394             if(plugin.getName().equalsIgnoreCase("RecPlug")) {
    395             Argument argument = plugin.getArgument("-use_metadata_files");
    396             if(argument != null) {
    397                 argument.setAssigned(true);
    398             }
    399             }
    400             // Second tweak. If the plugin is the HTMLPlug we want to modify the block expression so our backup files are ignored.
    401             if(plugin.getName().equalsIgnoreCase("HTMLPlug")) {
    402             Argument argument = plugin.getArgument("-block_exp");
    403             if(argument != null) {
    404                 argument.setValue(argument.getDefaultValue() + "|(~$)");
    405             }
    406             }
    407             // Add the plugin to our reserve
    408             assignPlugIn(plugin);
    409             return true;
    410         }
    411         else {
    412             //ystem.err.println("Unknown plugin");
    413         }
    414         }
    415     }
    416     return false;
    417     }
    418     /** This method removes an assigned plugin. I was tempted to call it unassign, by remove is more consistant. Note that there is no way to remove a plugin from the reserve.
    419       * @param plugin The <strong>PlugIn</strong> to remove.
    420       */
    421     public void removePlugIn(PlugIn plugin) {
    422     assigned.removeElement(plugin);
    423     available.addElement(plugin);
    424     gatherer.c_man.configurationChanged();
    425     }
    426     /** Method to cache the current contents of reserve (known plugins) to file.
    427       */
    428     public void savePlugIns() {
    429     try {
    430         FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "plugins.dat");
    431         ObjectOutputStream out = new ObjectOutputStream(file);
    432         out.writeObject(reserve);
    433         out.close();
    434     }
    435     catch (Exception error) {
    436     }
    437     }
    438     /** Method used to determine the number of plugins that have been assigned.
    439       * @return An <i>int</i> which is the number of plugins.
    440       */
    441     public int size() {
    442     return assigned.size();
    443     }
    444     /** Method to print out a block of plugin commands, much like you'd find in a collection configuration file.
    445       * @return A <strong>String</strong> containing a series of plugin commands separated by new lines.
    446       */
    447     public String toString() {
    448     String text = "";
    449     for(int i = 0; i < assigned.size(); i++) {
    450         Object object = assigned.get(i);
    451         if(object instanceof PlugIn) {
    452         PlugIn plugin = (PlugIn) object;
    453         text = text + plugin.toString() + "\n";
    454         }
    455     }
    456     text = text + "\n";
    457     return text;
    458     }
    459     /* Retrieve a phrase from the dictionary based on a certain key.
    460       * @param key The search <strong>String</strong>.
    461       * @return The matching phrase from the Dictionary.
    462       */
    463     private String get(String key) {
    464     return get(key, (String[])null);
    465     }
    466 
    467     private String get(String key, String arg) {
    468     String args[] = new String[1];
    469     args[0] = arg;
    470     return get(key, args);
    471     }
    472 
    473     /* Retrieve a phrase from the dictionary based on a certain key and arguments.
    474       * @param key The search <strong>String</strong>.
    475       * @param args A <strong>String[]</strong> of arguments used to complete and format the choosen phrase.
    476       * @return The matching phrase from the Dictionary.
    477       */
    478     private String get(String key, String args[]) {
    479     if(key.indexOf(".") == -1) {
    480         key = "CDM.PlugInManager." + key;
    481     }
    482     return gatherer.dictionary.get(key, args);
    483     }   
    484     /** Method to extract just the plugins name from a file object.
    485       * @param plugin The <strong>File</strong> which references a certain plugin.
    486       * @return A <strong>String</strong> containing just the plugins name, without extension.
    487       */
    488     private String getPlugInName(File plugin) {
    489     String name = plugin.getName();
    490     if(name.indexOf(".") != -1) {
    491         name = name.substring(0, name.indexOf("."));
    492     }
    493     return name;
    494     }
    495     /** Method to retrieve the CData value from a node. Requires a search for the #text node.
    496       * @param node The <strong>Node</strong> whose value we wish to find.
    497       * @return The value of node as a <strong>String</strong>, or <i>null</i> if no value exists.
    498       */
    499     private String getValue(Node node) {
    500     if(node.hasChildNodes()) {
    501         Node text = node.getFirstChild();
    502                 //ystem.err.println("Value of " + node.getNodeName() + " = " + text.getNodeValue());
    503         return text.getNodeValue();
    504     }
    505     return node.getNodeValue();
    506     }
     396        parseXML(document.getDocumentElement());
     397    }
     398    }
     399
    507400    /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
    508401      */
     
    512405        FileInputStream file = new FileInputStream(Utility.BASE_DIR + "plugins.dat");
    513406        ObjectInputStream input = new ObjectInputStream(file);
    514         reserve = (DynamicListModel) input.readObject();
    515         available = reserve.shallowCopy();
     407        library = (ArrayList) input.readObject();
    516408    }
    517409    catch (Exception error) {
    518410    }
    519     if(reserve == null) {
    520         available = new DynamicListModel();
    521         reserve = new DynamicListModel();
    522         reserve.setAutoOrder(true);
    523                 // Retrieve the gsdl home directory...
    524         String directory = gatherer.config.gsdl_path;
     411    if(library == null) {
     412        library = new ArrayList();
     413        // Retrieve the gsdl home directory...
     414        String directory = Gatherer.config.gsdl_path;
    525415        directory = directory + "perllib" + File.separator + "plugins" + File.separator;
    526416        loadPlugIns(new File(directory));
     
    533423    File files[] = directory.listFiles();
    534424    if(files != null) {
    535                 // Create a progress indicator.
     425        // Create a progress indicator.
    536426        ParsingProgress progress = new ParsingProgress(get("CDM.PlugInManager.Parsing.Title"), get("CDM.PlugInManager.Parsing.Message"), files.length);
    537427        for(int i = 0; i < files.length; i++) {
     
    546436    }
    547437
    548     private PlugIn parse(Node root) {
     438    private PlugIn parseXML(Node root) {
    549439    PlugIn plugin = new PlugIn();
    550440    String node_name = null;
     
    553443        node_name = node.getNodeName();
    554444        if(node_name.equals("Name")) {
    555         String name = getValue(node);
     445        String name = MSMUtils.getValue(node);
    556446        // We can save ourselves some processing time if a plugin with this name already exists in our manager. If so retrieve it and return it.
    557         PlugIn existing = getPlugIn(name);
     447        PlugIn existing = getBasePlugIn(name);
    558448        if(existing != null) {
    559449            return existing;
     
    562452        }
    563453        else if(node_name.equals("Desc")) {
    564         plugin.setDesc(getValue(node));
     454        plugin.setDescription(MSMUtils.getValue(node));
    565455        }
    566456                // Parse the multitude of arguments.
     
    575465                node_name = det.getNodeName();
    576466                if(node_name.equals("Name")) {
    577                 argument.setName(getValue(det));
     467                argument.setName(MSMUtils.getValue(det));
    578468                }
    579469                else if(node_name.equals("Desc")) {
    580                 argument.setDesc(getValue(det));
     470                argument.setDescription(MSMUtils.getValue(det));
    581471                }
    582472                else if(node_name.equals("Type")) {
    583                 argument.setType(getValue(det));
     473                argument.setType(MSMUtils.getValue(det));
    584474                }
    585475                else if(node_name.equals("Default")) {
    586                 argument.setDefault(getValue(det));
     476                argument.setDefaultValue(MSMUtils.getValue(det));
    587477                }
    588478                else if(node_name.equals("List")) {
     
    595485                        node_name = subvalue.getNodeName();
    596486                        if(node_name.equals("Name")) {
    597                         key = getValue(subvalue);
     487                        key = MSMUtils.getValue(subvalue);
    598488                        }
    599489                        else if(node_name.equals("Desc")) {
    600                         desc = getValue(subvalue);
     490                        desc = MSMUtils.getValue(subvalue);
    601491                        }
    602492                    }
     
    608498                }
    609499                else if(node_name.equals("Required")) {
    610                 String v = getValue(det);
     500                String v = MSMUtils.getValue(det);
    611501                if(v != null && v.equals("yes")) {
    612502                    argument.setRequired(true);
     
    618508            // A super plugin class.
    619509            else if(node_name.equals("PlugInfo")) {
    620             PlugIn super_plugin = parse(arg);
     510            PlugIn super_plugin = parseXML(arg);
    621511            plugin.setSuper(super_plugin);
    622512            }
     
    632522
    633523    /** A class which provodes controls for assigned and editing plugins. */
    634     private class Control
    635     extends JPanel {
     524    private class PlugInControl
     525    extends JPanel
     526    implements Control {
    636527    /** Button for adding plugins. */
    637528    private JButton add = null;
     
    649540    private JButton remove = null;
    650541    /** A combobox containing all of the known plugins, including those that may have already been assigned. */
    651     private JComboBox plugin = null;
     542    private GComboBox plugin = null;
    652543    /** The label next to the plugin combobox. */
    653544    private JLabel plugin_label = null;
     
    674565    /** Constructor.
    675566     */
    676     public Control() {
    677         Object plugins[] = reserve.toArray();
     567    public PlugInControl() {
     568        Object plugins[] = library.toArray();
    678569        Vector plugin_model = new Vector();
    679570        for(int i = 0; i < plugins.length; i++) {
     
    681572        }
    682573        Collections.sort(plugin_model);
    683                 // Create
     574        // Create
    684575        add = new JButton(get("Add"));
    685576        add.setMnemonic(KeyEvent.VK_A);
     
    697588        instructions.setWrapStyleWord(true);
    698589        move_bottom = new JButton();
    699         JLabel move_bottom_label = new JLabel(get("Move_Bottom"));
     590        JLabel move_bottom_label = new JLabel(get("CDM.Move.Move_Bottom"));
    700591        move_bottom_label.setHorizontalAlignment(JLabel.CENTER);
    701592        move_bottom_label.setPreferredSize(LABEL_SIZE);
     
    706597        move_bottom.setMnemonic(KeyEvent.VK_B);
    707598        move_down = new JButton();
    708         JLabel move_down_label = new JLabel(get("Move_Down"));
     599        JLabel move_down_label = new JLabel(get("CDM.Move.Move_Down"));
    709600        move_down_label.setHorizontalAlignment(JLabel.CENTER);
    710601        move_down_label.setPreferredSize(LABEL_SIZE);
     
    715606        move_down.setMnemonic(KeyEvent.VK_D);
    716607        move_top = new JButton();
    717         JLabel move_top_label = new JLabel(get("Move_Top"));
     608        JLabel move_top_label = new JLabel(get("CDM.Move.Move_Top"));
    718609        move_top_label.setHorizontalAlignment(JLabel.CENTER);
    719610        move_top_label.setPreferredSize(LABEL_SIZE);
     
    724615        move_top.setMnemonic(KeyEvent.VK_T);
    725616        move_up = new JButton();
    726         JLabel move_up_label = new JLabel(get("Move_Up"));
     617        JLabel move_up_label = new JLabel(get("CDM.Move.Move_Up"));
    727618        move_up_label.setHorizontalAlignment(JLabel.CENTER);
    728619        move_up_label.setPreferredSize(LABEL_SIZE);
     
    733624        move_up.setMnemonic(KeyEvent.VK_U);
    734625        movement_pane = new JPanel();
    735         plugin = new JComboBox(available);
    736         //plugin.setEditable(true);
     626
     627        plugin = new GComboBox(getAvailable());
     628        plugin.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.editable", false));
     629        plugin.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
     630        plugin.setEditable(true);
    737631        plugin.setSelectedIndex(0);
     632        plugin.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
     633        plugin.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
     634
    738635        plugin_label = new JLabel(get("PlugIn"));
    739         plugin_list = new JList(assigned);
     636        plugin_list = new JList(model);
    740637        plugin_list.setCellRenderer(new ListRenderer());
    741638        plugin_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     
    822719    public void destroy() {
    823720    }
    824     /** This method is overridden in some control classes to allow for the updating of collection configuration when the focus is lost to another view. In this case however the updates are asynchronous and so no 'has the configuration changed without the user updating' check is needed.
    825             * @return <i>true</i> if this control has focus, <i>false</i> otherwise.
    826             */
    827     public boolean hasFocus() {
    828         return super.hasFocus();
    829     }
     721
    830722    /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
    831             */
    832     public void updateUI() {
     723     */
     724    public void gainFocus() {
    833725        if(instructions != null) {
    834726        instructions.setCaretPosition(0);
     
    836728        super.updateUI();
    837729    }
    838     /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugIn()</i> method.
    839             */
     730
     731    public void loseFocus() {
     732
     733    }
     734
     735    /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugIn()</i> method. */
    840736    private class AddListener
    841737        implements ActionListener {
    842                 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
    843                 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
    844                 */
     738        /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
     739        * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
     740        */
    845741        public void actionPerformed(ActionEvent event) {
    846         PlugIn new_plugin = null;
    847         Object object = plugin.getSelectedItem();
    848         if(object instanceof PlugIn) {
    849             PlugIn target = (PlugIn)object;
    850             new_plugin = target.copy();
    851         }
    852         else {
    853             new_plugin = new PlugIn(object.toString(), "", null);
    854         }
    855         object = null;
    856         // Automatically chain to configuration. This ensures required arguments are filled out.
    857         ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, new_plugin);
    858         if(ac.display()) {
    859             assignPlugIn(new_plugin);
    860             plugin_list.setSelectedValue(new_plugin, true);
    861         }
    862         ac = null;
    863         new_plugin = null;
    864         plugin.setSelectedIndex(0);
    865         }
    866     }
    867     /** This class listens for actions upon the configure button in the controls, and if detected creates a new <strong>ArgumentConfiguration</strong> dialog box to allow for configuration.
    868             * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
    869             */
    870     private class ConfigureListener
    871         implements ActionListener {
    872                 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
    873                  * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
    874                  */
    875         public void actionPerformed(ActionEvent event) {
    876         if(!plugin_list.isSelectionEmpty()) {
    877             Object object = plugin_list.getSelectedValue();
    878             if(object instanceof PlugIn) {
    879             ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object);
     742        Object selected_object = plugin.getSelectedItem();
     743        // If there is something in the combobox, but we haven't registered a selection, then add the object and select it!
     744        if(selected_object != null && plugin.getSelectedIndex() == -1) {
     745            plugin.insertItemAt(selected_object, plugin.getItemCount());
     746        }
     747        if(selected_object != null) {
     748            // Create a new element in the DOM
     749            Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
     750            // Remember that the plugin supplied might be a custom string rather than a base plugin
     751            PlugIn new_plugin = null;
     752            if(selected_object instanceof PlugIn) {
     753            PlugIn base_plugin = (PlugIn) selected_object;
     754            element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_plugin.getName());
     755            new_plugin = new PlugIn(element, base_plugin);
     756            base_plugin = null;
     757            }
     758            else {
     759            element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString());
     760            new_plugin = new PlugIn(element, null);
     761            }
     762            if(!model.contains(new_plugin)) {
     763            // Automatically chain to configuration. This ensures required arguments are filled out.
     764            ArgumentConfiguration ac = new ArgumentConfiguration(new_plugin);
    880765            if(ac.display()) {
    881                 assigned.refresh();
     766                assignPlugIn(new_plugin);
     767                plugin_list.setSelectedValue(new_plugin, true);
    882768            }
    883             }
    884         }
    885         }
    886     }
    887     /** A special list renderer which is able to render separating lines as well. */
    888     private class ListRenderer
    889         extends DefaultListCellRenderer {
    890                 /** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize  can be invoked.
    891                  * @param list - The <strong>JList</strong> we're painting.
    892                  * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
    893                  * @param index - The cells index as an <i>int</i>.
    894                  * @param isSelected - <i>true</i> if the specified cell was selected.
    895                  * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
    896                  * @return A <strong>Component</strong> whose paint() method will render the specified value.
    897                  * @see javax.swing.JList
    898                  * @see javax.swing.JSeparator
    899                  * @see javax.swing.ListModel
    900                  * @see javax.swing.ListSelectionModel
    901                  */
    902         public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    903         if(value instanceof JPanel) {
    904             return (JPanel) value;
    905         }
    906         else {
    907             return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    908         }
    909         }
    910     }
     769            ac = null;
     770            new_plugin = null;
     771            plugin.setSelectedIndex(0);
     772            }
     773            else {
     774            JOptionPane.showMessageDialog(Gatherer.g_man, get("PlugIn_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
     775            }
     776        }
     777        }
     778    }
     779
    911780    /** Listens for double clicks apon the list and react as if the configure button was pushed. */
    912781    private class ClickListener
    913782        extends MouseAdapter {
    914                 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
    915                 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
    916                 */
     783        /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
     784        * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
     785        */
    917786        public void mouseClicked(MouseEvent event) {
    918787        if(event.getClickCount() == 2 ) {
    919788            if(!plugin_list.isSelectionEmpty()) {
    920             Object object = plugin_list.getSelectedValue();
    921             if(object instanceof PlugIn) {
    922                 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object);
     789            PlugIn plugin = (PlugIn) plugin_list.getSelectedValue();
     790            if(!plugin.isSeparator()) {
     791                ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
    923792                if(ac.display()) {
    924                 assigned.refresh();
     793                refresh(plugin);
    925794                }
     795                ac.destroy();
     796                ac = null;
    926797            }
     798            }
     799        }
     800        }
     801    }
     802
     803    /** This class listens for actions upon the configure button in the controls, and if detected creates a new <strong>ArgumentConfiguration</strong> dialog box to allow for configuration.
     804     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
     805     */
     806    private class ConfigureListener
     807        implements ActionListener {
     808        /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
     809         * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
     810         */
     811        public void actionPerformed(ActionEvent event) {
     812        if(!plugin_list.isSelectionEmpty()) {
     813            PlugIn plugin = (PlugIn) plugin_list.getSelectedValue();
     814            if(!plugin.isSeparator()) {
     815            ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
     816            if(ac.display()) {
     817                refresh(plugin);
     818            }
     819            ac.destroy();
     820            ac = null;
    927821            }
    928822        }
     
    946840        }
    947841    }
     842
     843    /** A special list renderer which is able to render separating lines as well. */
     844    private class ListRenderer
     845        extends DefaultListCellRenderer {
     846        /** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize  can be invoked.
     847         * @param list - The <strong>JList</strong> we're painting.
     848         * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
     849         * @param index - The cells index as an <i>int</i>.
     850         * @param isSelected - <i>true</i> if the specified cell was selected.
     851         * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
     852         * @return A <strong>Component</strong> whose paint() method will render the specified value.
     853         * @see javax.swing.JList
     854         * @see javax.swing.JSeparator
     855         * @see javax.swing.ListModel
     856         * @see javax.swing.ListSelectionModel
     857         */
     858        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
     859        PlugIn plugin = (PlugIn) value;
     860        if(plugin.isSeparator()) {
     861            return separator;
     862        }
     863        else {
     864            return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
     865        }
     866        }
     867    }
     868
    948869
    949870    /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>movePlugIn()</i> method of the manager with the appropriate details. */
     
    999920    }
    1000921    /** Creates a list separator.
    1001       * Code courtesy of Farwell, Paul. Contact <a href="mailto:[email protected]">[email protected]</a>
    1002       */
     922     * Code courtesy of Farwell, Paul. Contact <a href="mailto:[email protected]">[email protected]</a>
     923     */
    1003924    static private JPanel getSeparator() {
    1004925    // we put the separator inside a panel to control
     
    1014935    }
    1015936}
    1016 
    1017 
    1018 
    1019 
Note: See TracChangeset for help on using the changeset viewer.