Ignore:
Timestamp:
2003-05-27T15:57:37+12:00 (21 years ago)
Author:
kjdon
Message:

re-tabbed the code for java

File:
1 edited

Legend:

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

    r4293 r4366  
    112112// ####################################################################################
    113113public class ClassifierManager
    114     implements MSMListener {
    115     /** An interface to the Gatherer, the creator of this cdm module, for access to the Greenstone installation directory. */
    116     private Gatherer gatherer = null;
    117     /** A reference to the CollectionDesignManager for access to other configuration managers. */
    118     private CollectionDesignManager manager = null;
    119     /** The controls for editing the contents of this manager. */
    120     private Control controls = null;
    121     /** A list of assigned classifiers. */
    122     private DynamicListModel assigned = null;
    123     /** A list of known, but currently unassigned, classifiers. */
    124     private DynamicListModel reserve = null;
    125     /** We may have somehow recieved a classifier command that are, in fact, custom classifiers which can refer to classifiers that haven't been parsed yet, so this holds a list of failed commands which are retried after the loading is complete. */
    126     private ArrayList unresolved_commands = null;
    127     /** Constructor.
    128       * @param gatherer A reference to the <strong>Gatherer</strong> for access to the Dictionary.
    129       * @param manager A reference to the <strong>CollectionDesignManager</strong> itself.
    130       * @see org.greenstone.gatherer.Gatherer
    131       * @see org.greenstone.gatherer.cdm.DynamicListModel
    132       * @see org.greenstone.gatherer.collection.CollectionManager
    133       * @see org.greenstone.gatherer.msm.MetadataSetManager
    134       * @see org.greenstone.gatherer.msm.MSMListener
    135       */
    136     public ClassifierManager(Gatherer gatherer, CollectionDesignManager manager) {
    137           this.assigned = new DynamicListModel();
    138           this.gatherer = gatherer;
    139           this.manager = manager;
    140           this.unresolved_commands = new ArrayList();
    141           loadClassifiers();
    142           saveClassifiers();
    143           // Register as a MSMListener.
    144           Gatherer.c_man.getCollection().msm.addMSMListener(this);
    145     }
    146     /** Method to add a new classifier to reserve.
     114    implements MSMListener {
     115    /** An interface to the Gatherer, the creator of this cdm module, for access to the Greenstone installation directory. */
     116    private Gatherer gatherer = null;
     117    /** A reference to the CollectionDesignManager for access to other configuration managers. */
     118    private CollectionDesignManager manager = null;
     119    /** The controls for editing the contents of this manager. */
     120    private Control controls = null;
     121    /** A list of assigned classifiers. */
     122    private DynamicListModel assigned = null;
     123    /** A list of known, but currently unassigned, classifiers. */
     124    private DynamicListModel reserve = null;
     125    /** We may have somehow recieved a classifier command that are, in fact, custom classifiers which can refer to classifiers that haven't been parsed yet, so this holds a list of failed commands which are retried after the loading is complete. */
     126    private ArrayList unresolved_commands = null;
     127    /** Constructor.
     128     * @param gatherer A reference to the <strong>Gatherer</strong> for access to the Dictionary.
     129     * @param manager A reference to the <strong>CollectionDesignManager</strong> itself.
     130     * @see org.greenstone.gatherer.Gatherer
     131     * @see org.greenstone.gatherer.cdm.DynamicListModel
     132     * @see org.greenstone.gatherer.collection.CollectionManager
     133     * @see org.greenstone.gatherer.msm.MetadataSetManager
     134     * @see org.greenstone.gatherer.msm.MSMListener
     135     */
     136    public ClassifierManager(Gatherer gatherer, CollectionDesignManager manager) {
     137    this.assigned = new DynamicListModel();
     138    this.gatherer = gatherer;
     139    this.manager = manager;
     140    this.unresolved_commands = new ArrayList();
     141    loadClassifiers();
     142    saveClassifiers();
     143    // Register as a MSMListener.
     144    Gatherer.c_man.getCollection().msm.addMSMListener(this);
     145    }
     146    /** Method to add a new classifier to reserve.
    147147      * @param classifier The new <strong>Classifier</strong>.
    148148      * @see org.greenstone.gatherer.cdm.DynamicListModel
    149149      */
    150     public void addClassifier(Classifier classifier) {
    151           if(!reserve.contains(classifier)) {
    152                 reserve.addElement(classifier);
    153           }
    154     }
    155     /** Method to assign a classifier.
     150    public void addClassifier(Classifier classifier) {
     151    if(!reserve.contains(classifier)) {
     152        reserve.addElement(classifier);
     153    }
     154    }
     155    /** Method to assign a classifier.
    156156      * @param classifier The reserve <strong>Classifier</strong> to assign.
    157157      * @see org.greenstone.gatherer.cdm.DynamicListModel
    158158      */
    159     public void assignClassifier(Classifier classifier) {
    160           if(!assigned.contains(classifier)) {
    161                 assigned.addElement(classifier);
    162                 classifier.setManager(this);
    163                 gatherer.c_man.configurationChanged();
    164           }
    165     }
    166     /** Method to assign a classifier.
     159    public void assignClassifier(Classifier classifier) {
     160    if(!assigned.contains(classifier)) {
     161        assigned.addElement(classifier);
     162        classifier.setManager(this);
     163        gatherer.c_man.configurationChanged();
     164    }
     165    }
     166    /** Method to assign a classifier.
    167167      * @param classifier The <strong>CustomClassifier</strong> to assign.
    168168      * @see org.greenstone.gatherer.cdm.DynamicListModel
    169169      */
    170     public void assignClassifier(CustomClassifier classifier) {
    171           if(!assigned.contains(classifier)) {
    172                 assigned.addElement(classifier);
    173                classifier.setManager(this);
    174                 gatherer.c_man.configurationChanged();
    175           }
    176     }
    177     /** Destructor.
     170    public void assignClassifier(CustomClassifier classifier) {
     171    if(!assigned.contains(classifier)) {
     172        assigned.addElement(classifier);
     173        classifier.setManager(this);
     174        gatherer.c_man.configurationChanged();
     175    }
     176    }
     177    /** Destructor.
    178178      * @see org.greenstone.gatherer.Gatherer
    179179      * @see org.greenstone.gatherer.cdm.CollectionDesignManager
    180180      * @see org.greenstone.gatherer.cdm.DynamicListModel
    181181      */
    182     public void destroy() {
    183           // Deregister as a listener
    184           if(gatherer.c_man != null && gatherer.c_man.msm != null) {
    185                 gatherer.c_man.msm.removeMSMListener(this);
    186           }
    187           // Null globals
    188           assigned = null;
    189           controls = null;
    190           gatherer = null;
    191           manager = null;
    192           reserve = null;
    193           unresolved_commands = null;
    194     }
    195     /** Method to retrieve the classifier with the given index.
     182    public void destroy() {
     183    // Deregister as a listener
     184    if(gatherer.c_man != null && gatherer.c_man.msm != null) {
     185        gatherer.c_man.msm.removeMSMListener(this);
     186    }
     187    // Null globals
     188    assigned = null;
     189    controls = null;
     190    gatherer = null;
     191    manager = null;
     192    reserve = null;
     193    unresolved_commands = null;
     194    }
     195    /** Method to retrieve the classifier with the given index.
    196196      * @param index The index of the desired classifier as an <i>int</i>.
    197197      * @return The requested Classifier as an <strong>Object</strong> or <i>null</i> if no such classifier exists.
    198198      * @see org.greenstone.gatherer.cdm.DynamicListModel
    199199      */
    200     public Object getClassifier(int index) {
    201           if(0 <= index && index < assigned.size()) {
    202                 return assigned.get(index);
    203           }
    204           return null;
    205     }
    206     /** Method to retrieve the named classifier.
     200    public Object getClassifier(int index) {
     201    if(0 <= index && index < assigned.size()) {
     202        return assigned.get(index);
     203    }
     204    return null;
     205    }
     206    /** Method to retrieve the named classifier.
    207207      * @param name The name of the desired classifier as a <strong>String</strong>.
    208208      * @return The requested <strong>Classifier</strong> or <i>null</i> if no such classifier exists.
    209209      * @see org.greenstone.gatherer.cdm.DynamicListModel
    210210      */
    211     public Classifier getClassifier(String name) {
    212           for(int i = 0; i < reserve.size(); i++) {
    213                 Classifier classifier = (Classifier)reserve.get(i);
    214                 if(classifier.getName().equals(name)) {
    215                      return classifier;
    216                 }
    217           }
    218           // No success.
    219           return null;
    220     }
    221     /** Method to retrieve the control for this manager.
     211    public Classifier getClassifier(String name) {
     212    for(int i = 0; i < reserve.size(); i++) {
     213        Classifier classifier = (Classifier)reserve.get(i);
     214        if(classifier.getName().equals(name)) {
     215        return classifier;
     216        }
     217    }
     218    // No success.
     219    return null;
     220    }
     221    /** Method to retrieve the control for this manager.
    222222      * @return A <strong>JPanel</strong> containing the controls.
    223223      */
    224     public JPanel getControls() {
    225           if(controls == null) {
    226                 controls = new Control();
    227           }
    228           return controls;
    229     }
    230     /** Called whenever a metadata element changes significantly.
     224    public JPanel getControls() {
     225    if(controls == null) {
     226        controls = new Control();
     227    }
     228    return controls;
     229    }
     230    /** Called whenever a metadata element changes significantly.
    231231      * @param event A <strong>MSMEvent</strong> choc' full of event informationy goodness.
    232232      */
    233     public void elementChanged(MSMEvent event) {
    234           // Don't really care, as the elements dealt with here are all live references so changes like identifier change will propagate immediately.
    235     }
    236     /** Method to find the index of the given classifier within the assigned classifiers.
     233    public void elementChanged(MSMEvent event) {
     234    // Don't really care, as the elements dealt with here are all live references so changes like identifier change will propagate immediately.
     235    }
     236    /** Method to find the index of the given classifier within the assigned classifiers.
    237237      * @param classifier The <strong>Classifier</strong> whose index you wish to find.
    238238      * @return The index of the classifier as an <i>int</i>, which has a value of -1 if the classifier was not found.
    239239      * @see org.greenstone.gatherer.cdm.DynamicListModel
    240240      */
    241     public int indexOf(Classifier classifier) {
    242           for(int i = 0; i < assigned.size(); i++) {
    243                 Classifier sibling = (Classifier) assigned.get(i);
    244                 if(sibling.equals(classifier)) {
    245                      return i;
    246                 }
    247           }
    248           return -1;
    249     }
    250     /** Method to invalidate controls after a significant change in the system state.
    251       */
    252     public void invalidateControls() {
    253           if(controls != null) {
    254                 controls.destroy();
    255           }
    256           controls = null;
    257     }
    258     /** Method to load the details of a single plug-in.
     241    public int indexOf(Classifier classifier) {
     242    for(int i = 0; i < assigned.size(); i++) {
     243        Classifier sibling = (Classifier) assigned.get(i);
     244        if(sibling.equals(classifier)) {
     245        return i;
     246        }
     247    }
     248    return -1;
     249    }
     250    /** Method to invalidate controls after a significant change in the system state.
     251      */
     252    public void invalidateControls() {
     253    if(controls != null) {
     254        controls.destroy();
     255    }
     256    controls = null;
     257    }
     258    /** Method to load the details of a single plug-in.
    259259      * @param classifier The classifier <strong>File</strong> you wish to load.
    260260      */
    261     public void loadClassifier(File classifier) {
    262           ///ystem.err.println("Attempting to parse " + classifier.toString());
    263           Document document = null;
    264           long start;
    265           long end;
    266           // Run classinfo on this classifier, and then send the results for parsing.
    267           try {
    268                 String args[] = null;
    269                 if(Utility.isWindows()) {
    270                      args = new String[4];
    271                      if(Gatherer.config.perl_path != null) {
    272                           args[0] = gatherer.config.perl_path + "Perl.exe";
    273                      }
    274                      else {
    275                           args[0] = "Perl.exe";
    276                      }
    277                      args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl";
    278                      args[2] = "-xml";
    279                      args[3] = getClassifierName(classifier);
    280                 }
    281                 else {
    282                      args = new String[3];
    283                      args[0] = "classinfo.pl";
    284                      args[1] = "-xml";
    285                      args[2] = getClassifierName(classifier);
    286                 }
     261    public void loadClassifier(File classifier) {
     262    ///ystem.err.println("Attempting to parse " + classifier.toString());
     263    Document document = null;
     264    long start;
     265    long end;
     266    // Run classinfo on this classifier, and then send the results for parsing.
     267    try {
     268        String args[] = null;
     269        if(Utility.isWindows()) {
     270        args = new String[4];
     271        if(Gatherer.config.perl_path != null) {
     272            args[0] = gatherer.config.perl_path + "Perl.exe";
     273        }
     274        else {
     275            args[0] = "Perl.exe";
     276        }
     277        args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl";
     278        args[2] = "-xml";
     279        args[3] = getClassifierName(classifier);
     280        }
     281        else {
     282        args = new String[3];
     283        args[0] = "classinfo.pl";
     284        args[1] = "-xml";
     285        args[2] = getClassifierName(classifier);
     286        }
    287287
    288288                // Create the process.
    289                 Runtime runtime = Runtime.getRuntime();
    290                 Process process = runtime.exec(args);
    291                 InputStream input_stream = process.getErrorStream();
    292                 BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    293                 String line = "";
    294                 StringBuffer xml = new StringBuffer("");
    295                 while((line = error_in.readLine()) != null) {
    296                      xml.append(line);
    297                      xml.append("\n");
    298                 }
     289        Runtime runtime = Runtime.getRuntime();
     290        Process process = runtime.exec(args);
     291        InputStream input_stream = process.getErrorStream();
     292        BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
     293        String line = "";
     294        StringBuffer xml = new StringBuffer("");
     295        while((line = error_in.readLine()) != null) {
     296        xml.append(line);
     297        xml.append("\n");
     298        }
    299299                // Then read the xml from the piped input stream.
    300                 InputSource source = new InputSource(new StringReader(xml.toString()));
    301                 DOMParser parser = new DOMParser();
    302                 parser.parse(source);
    303                 document = parser.getDocument();
    304           }
    305           catch (Exception error) {
    306                 error.printStackTrace();
     300        InputSource source = new InputSource(new StringReader(xml.toString()));
     301        DOMParser parser = new DOMParser();
     302        parser.parse(source);
     303        document = parser.getDocument();
     304    }
     305    catch (Exception error) {
     306        error.printStackTrace();
    307307                //ystem.err.println("Error: Cannot parse " + getClassifierName(classifier));
    308           }
    309           if(document != null) {
    310                 parse(document.getDocumentElement());
    311           }
    312     }
    313     /** Called whenever the metadata value associated to a certain record changes. */
    314     public void metadataChanged(MSMEvent event) {
    315           FileNode record = event.getRecord();
    316           if(record != null) {
    317                 for(int i = 0; i < assigned.size(); i++) {
    318                      Object object = assigned.get(i);
    319                      if(object instanceof CustomClassifier) {
    320                           CustomClassifier classifier = (CustomClassifier) object;
    321                           classifier.process(record);
    322                      }
    323                 }
    324           }
    325     }
    326     /** This method attempts to parse a classifier command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct classifier be matched but also all of the parameters given must be legal. If such a command is found, the classifier is immediately assigned.
     308    }
     309    if(document != null) {
     310        parse(document.getDocumentElement());
     311    }
     312    }
     313    /** Called whenever the metadata value associated to a certain record changes. */
     314    public void metadataChanged(MSMEvent event) {
     315    FileNode record = event.getRecord();
     316    if(record != null) {
     317        for(int i = 0; i < assigned.size(); i++) {
     318        Object object = assigned.get(i);
     319        if(object instanceof CustomClassifier) {
     320            CustomClassifier classifier = (CustomClassifier) object;
     321            classifier.process(record);
     322        }
     323        }
     324    }
     325    }
     326    /** This method attempts to parse a classifier command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct classifier be matched but also all of the parameters given must be legal. If such a command is found, the classifier is immediately assigned.
    327327      * @param command The command <strong>String</strong> that may include classifier information.
    328328      * @return <i>true</i> if a classifier command was parsed, <i>false</i> otherwise.
     
    331331      * @see org.greenstone.gatherer.cdm.CommandTokenizer
    332332      */
    333      public boolean parse(String command) {
    334           String command_lc = command.toLowerCase();
    335           if(command_lc.startsWith("classify")) {
    336                 CommandTokenizer tokenizer = new CommandTokenizer(command);
    337                 if(tokenizer.countTokens() >= 2) {
    338                      tokenizer.nextToken(); // Throw away 'classifier'
    339                      String name = tokenizer.nextToken();
    340                      // Try to locate the classifier with this name.
    341                      Classifier classifier = getClassifier(name);
    342                      // And if successful start to parse the arguments.
    343                      if(classifier != null) {
    344                           // Take a copy.
    345                           classifier = classifier.copy();
    346                           String key = null;
    347                           while((key = tokenizer.nextToken()) != null) {
    348                                 // Try to retrieve a matching argument.
    349                                 Argument argument = classifier.getArgument(key);
    350                                 if(argument != null) {
    351                                      // Set as assigned.
    352                                      argument.setAssigned(true);
    353                                      // And if the argument is of a parameter type, parse a parameter.
    354                                      if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) {
    355                                           String value = tokenizer.nextToken();
    356                                           value = value.replace(':', MSMUtils.NS_SEP);
    357                                           argument.setValue(value);
    358                                      }
    359                                 }
    360                                 // Argument cannot be matched.
    361                                 else {
    362                                      String cur_key = key;
    363                                      String value = tokenizer.nextToken();
    364                                      if(value.startsWith("-")) {
    365                                           key = value;
    366                                           value = null;
    367                                      }
    368                                      else {
    369                                           key = null;
    370                                      }
    371                                      String custom = classifier.getCustom();
    372                                      if(custom == null) {
    373                                           if(value == null) {
    374                                                 classifier.setCustom(cur_key);
    375                                           }
    376                                           else {
    377                                                 classifier.setCustom(cur_key + " " + value);
    378                                           }
    379                                      }
    380                                      else {
    381                                           if(value == null) {
    382                                                 classifier.setCustom(custom + " " + cur_key);
    383                                           }
    384                                           else {
    385                                                 classifier.setCustom(custom + " " + cur_key + " " + value);
    386                                           }
    387                                      }
    388                                 }
    389                           }
    390                           assignClassifier(classifier);
    391                           return true;
    392                      }
    393                      else {
    394                           ///ystem.err.println("Unknown classifier");
    395                      }
     333    public boolean parse(String command) {
     334    String command_lc = command.toLowerCase();
     335    if(command_lc.startsWith("classify")) {
     336        CommandTokenizer tokenizer = new CommandTokenizer(command);
     337        if(tokenizer.countTokens() >= 2) {
     338        tokenizer.nextToken(); // Throw away 'classifier'
     339        String name = tokenizer.nextToken();
     340        // Try to locate the classifier with this name.
     341        Classifier classifier = getClassifier(name);
     342        // And if successful start to parse the arguments.
     343        if(classifier != null) {
     344            // Take a copy.
     345            classifier = classifier.copy();
     346            String key = null;
     347            while((key = tokenizer.nextToken()) != null) {
     348            // Try to retrieve a matching argument.
     349            Argument argument = classifier.getArgument(key);
     350            if(argument != null) {
     351                // Set as assigned.
     352                argument.setAssigned(true);
     353                // And if the argument is of a parameter type, parse a parameter.
     354                if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) {
     355                String value = tokenizer.nextToken();
     356                value = value.replace(':', MSMUtils.NS_SEP);
     357                argument.setValue(value);
     358                }
     359            }
     360            // Argument cannot be matched.
     361            else {
     362                String cur_key = key;
     363                String value = tokenizer.nextToken();
     364                if(value.startsWith("-")) {
     365                key = value;
     366                value = null;
     367                }
     368                else {
     369                key = null;
     370                }
     371                String custom = classifier.getCustom();
     372                if(custom == null) {
     373                if(value == null) {
     374                    classifier.setCustom(cur_key);
    396375                }
    397           }
    398           else if(command_lc.startsWith("customclassifier")) {
    399                 unresolved_commands.add(command);
    400                 return true;
    401           }
    402           return false;
    403      }
    404      /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the reserve.
     376                else {
     377                    classifier.setCustom(cur_key + " " + value);
     378                }
     379                }
     380                else {
     381                if(value == null) {
     382                    classifier.setCustom(custom + " " + cur_key);
     383                }
     384                else {
     385                    classifier.setCustom(custom + " " + cur_key + " " + value);
     386                }
     387                }
     388            }
     389            }
     390            assignClassifier(classifier);
     391            return true;
     392        }
     393        else {
     394            ///ystem.err.println("Unknown classifier");
     395        }
     396        }
     397    }
     398    else if(command_lc.startsWith("customclassifier")) {
     399        unresolved_commands.add(command);
     400        return true;
     401    }
     402    return false;
     403    }
     404    /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the reserve.
    405405      * @param classifier The Classifier or CustomClassifier, as an <strong>Object</strong>, to remove.
    406406      * @see org.greenstone.gatherer.cdm.DynamicListModel
    407407      */
    408     public void removeClassifier(Object classifier) {
    409           assigned.removeElement(classifier);
    410           gatherer.c_man.configurationChanged();
    411     }
    412     /** Method which attempts to reparse obvious classifier commands which previously referenced unresovable Classifiers.
     408    public void removeClassifier(Object classifier) {
     409    assigned.removeElement(classifier);
     410    gatherer.c_man.configurationChanged();
     411    }
     412    /** Method which attempts to reparse obvious classifier commands which previously referenced unresovable Classifiers.
    413413      * @see org.greenstone.gatherer.cdm.Classifier
    414414      * @see org.greenstone.gatherer.cdm.CommandTokenizer
    415415      * @see org.greenstone.gatherer.cdm.CustomClassifier
    416416      */
    417     public void reparseUnresolved() {
    418           for(int i = 0; i < unresolved_commands.size(); i++) {
    419                 String command = (String) unresolved_commands.get(i);
    420                 CommandTokenizer tokenizer = new CommandTokenizer(command);
    421                 if(tokenizer.countTokens() >= 6) {
    422                      tokenizer.nextToken();// Loose customclassifier
    423                      // Get class name.
    424                      String class_name = tokenizer.nextToken();
    425                      // Parse arguments.
    426                      String replaces = null;
    427                      String separations = null;
    428                      while(tokenizer.hasMoreTokens()) {
    429                           String arg_name = tokenizer.nextToken();
    430                           if(arg_name.equalsIgnoreCase("-replaces")) {
    431                                 replaces = tokenizer.nextToken();
    432                           }
    433                           else {
    434                                 separations = tokenizer.nextToken();
    435                           }
    436                      }
    437                      try {
    438                           replaces = replaces.substring(2);
    439                           int index = Integer.parseInt(replaces);
    440                           Classifier original = (Classifier)getClassifier(index);
    441                           if(original != null) {
    442                                 Class custom_classifier_class = Class.forName("org.greenstone.gatherer.cdm.custom." + class_name);
    443                                 CustomClassifier custom_classifier = (CustomClassifier) custom_classifier_class.newInstance();
    444                                 custom_classifier.setGatherer(gatherer);
    445                                 custom_classifier.recreate(original, separations);
    446                                 assigned.add(indexOf(original), custom_classifier);
    447                                 assigned.removeElement(original);
    448                           }
    449                           else {
    450                                 ///ystem.err.println("Missing original.");
    451                           }
    452                      }
    453                      catch (Exception error) {
    454                           error.printStackTrace();
    455                      }
    456                 }
    457           }
    458           // Regardless of if they work, clear the commands.
    459           unresolved_commands.clear();
    460     }
    461     /** Method to cache the current contents of reserve (known classifiers) to file.
     417    public void reparseUnresolved() {
     418    for(int i = 0; i < unresolved_commands.size(); i++) {
     419        String command = (String) unresolved_commands.get(i);
     420        CommandTokenizer tokenizer = new CommandTokenizer(command);
     421        if(tokenizer.countTokens() >= 6) {
     422        tokenizer.nextToken();// Loose customclassifier
     423        // Get class name.
     424        String class_name = tokenizer.nextToken();
     425        // Parse arguments.
     426        String replaces = null;
     427        String separations = null;
     428        while(tokenizer.hasMoreTokens()) {
     429            String arg_name = tokenizer.nextToken();
     430            if(arg_name.equalsIgnoreCase("-replaces")) {
     431            replaces = tokenizer.nextToken();
     432            }
     433            else {
     434            separations = tokenizer.nextToken();
     435            }
     436        }
     437        try {
     438            replaces = replaces.substring(2);
     439            int index = Integer.parseInt(replaces);
     440            Classifier original = (Classifier)getClassifier(index);
     441            if(original != null) {
     442            Class custom_classifier_class = Class.forName("org.greenstone.gatherer.cdm.custom." + class_name);
     443            CustomClassifier custom_classifier = (CustomClassifier) custom_classifier_class.newInstance();
     444            custom_classifier.setGatherer(gatherer);
     445            custom_classifier.recreate(original, separations);
     446            assigned.add(indexOf(original), custom_classifier);
     447            assigned.removeElement(original);
     448            }
     449            else {
     450            ///ystem.err.println("Missing original.");
     451            }
     452        }
     453        catch (Exception error) {
     454            error.printStackTrace();
     455        }
     456        }
     457    }
     458    // Regardless of if they work, clear the commands.
     459    unresolved_commands.clear();
     460    }
     461    /** Method to cache the current contents of reserve (known classifiers) to file.
    462462      * @see org.greenstone.gatherer.util.Utility
    463463      */
    464     public void saveClassifiers() {
    465           try {
    466                 FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat");
    467                 ObjectOutputStream out = new ObjectOutputStream(file);
    468                 out.writeObject(reserve);
    469                 out.close();
    470           }
    471           catch (Exception error) {
    472           }
    473     }
    474     /** Called when a metadata set changed significantly.
     464    public void saveClassifiers() {
     465    try {
     466        FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat");
     467        ObjectOutputStream out = new ObjectOutputStream(file);
     468        out.writeObject(reserve);
     469        out.close();
     470    }
     471    catch (Exception error) {
     472    }
     473    }
     474    /** Called when a metadata set changed significantly.
    475475      * @param event A <strong>MSMEvent</strong> containing information about the set change.
    476476      */
    477     public void setChanged(MSMEvent event) {
    478           // Again, we would only worry about this if we contained 'inanimate' references to elements or something, but our references are live, and controls are rebuilt everytime a pop-up is needed.
    479     }
    480     /** Method used to determine the number of classifiers that have been assigned.
     477    public void setChanged(MSMEvent event) {
     478    // Again, we would only worry about this if we contained 'inanimate' references to elements or something, but our references are live, and controls are rebuilt everytime a pop-up is needed.
     479    }
     480    /** Method used to determine the number of classifiers that have been assigned.
    481481      * @return An <i>int</i> which is the number of classifiers.
    482482      */
    483     public int size() {
    484           return assigned.size();
    485     }
    486     /** Method to print out a block of classifier commands, much like you'd find in a collection configuration file.
     483    public int size() {
     484    return assigned.size();
     485    }
     486    /** Method to print out a block of classifier commands, much like you'd find in a collection configuration file.
    487487      * @return A <strong>String</strong> containing a series of classifier commands separated by new lines.
    488488      * @see org.greenstone.gatherer.cdm.Classifier
    489489      * @see org.greenstone.gatherer.cdm.CustomClassifier
    490490      */
    491     public String toString() {
    492           StringBuffer text = new StringBuffer();
    493           for(int i = 0; i < assigned.size(); i++) {
    494                 Object object = assigned.get(i);
    495                 if(object instanceof Classifier) {
    496                      Classifier classifier = (Classifier) object;
    497                      text.append(classifier.toString());
    498                 }
    499                 else if(object instanceof CustomClassifier) {
    500                      CustomClassifier classifier = (CustomClassifier) object;
    501                      text.append(classifier.getCommand());
    502                      text.append("\n");
    503                      text.append(classifier.getCustomCommand(i));
    504                 }
    505                 text.append("\n");
    506           }
    507           text.append("\n");
    508           return text.toString();
    509     }
    510     /** Called when a significant change has occured to a value tree for a certain element, however we take no further action.
     491    public String toString() {
     492    StringBuffer text = new StringBuffer();
     493    for(int i = 0; i < assigned.size(); i++) {
     494        Object object = assigned.get(i);
     495        if(object instanceof Classifier) {
     496        Classifier classifier = (Classifier) object;
     497        text.append(classifier.toString());
     498        }
     499        else if(object instanceof CustomClassifier) {
     500        CustomClassifier classifier = (CustomClassifier) object;
     501        text.append(classifier.getCommand());
     502        text.append("\n");
     503        text.append(classifier.getCustomCommand(i));
     504        }
     505        text.append("\n");
     506    }
     507    text.append("\n");
     508    return text.toString();
     509    }
     510    /** Called when a significant change has occured to a value tree for a certain element, however we take no further action.
    511511      * @param event A <strong>MSMEvent</strong> containing information relevant to the event.
    512512      */
    513     public void valueChanged(MSMEvent event) {
    514     }
    515     /** Retrieve a phrase from the dictionary based on a certain key.
     513    public void valueChanged(MSMEvent event) {
     514    }
     515    /** Retrieve a phrase from the dictionary based on a certain key.
    516516      * @param key The search <strong>String</strong>.
    517517      * @return The matching phrase from the Dictionary.
    518518      */
    519     private String get(String key) {
    520           return get(key, null);
    521     }
    522     /** Retrieve a phrase from the dictionary based on a certain key and certain arguments.
     519    private String get(String key) {
     520    return get(key, null);
     521    }
     522    /** Retrieve a phrase from the dictionary based on a certain key and certain arguments.
    523523      * @param key The search <strong>String</strong>.
    524524      * @param args A <strong>String[]</strong> used to complete and format the returned phrase.
     
    527527      * @see org.greenstone.gatherer.Gatherer
    528528      */
    529     private String get(String key, String args[]) {
    530           if(key.indexOf(".") == -1) {
    531                 key = "CDM.ClassifierManager." + key;
    532           }
    533           return gatherer.dictionary.get(key, args);
    534     }
    535     /** Method to extract just the classifiers name from a file object.
     529    private String get(String key, String args[]) {
     530    if(key.indexOf(".") == -1) {
     531        key = "CDM.ClassifierManager." + key;
     532    }
     533    return gatherer.dictionary.get(key, args);
     534    }
     535    /** Method to extract just the classifiers name from a file object.
    536536      * @param classifier The <strong>File</strong> which references a certain classifier.
    537537      * @return A <strong>String</strong> containing just the classifiers name, without extension.
    538538      */
    539     private String getClassifierName(File classifier) {
    540           String name = classifier.getName();
    541           if(name.indexOf(".") != -1) {
    542                 name = name.substring(0, name.indexOf("."));
    543           }
    544           return name;
    545     }
    546     /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
     539    private String getClassifierName(File classifier) {
     540    String name = classifier.getName();
     541    if(name.indexOf(".") != -1) {
     542        name = name.substring(0, name.indexOf("."));
     543    }
     544    return name;
     545    }
     546    /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
    547547      * @see org.greenstone.gatherer.cdm.DynamicListModel
    548548      * @see org.greenstone.gatherer.util.Utility
    549549      */
    550     private void loadClassifiers() {
    551           // Attempt to restore the cached file.
    552           try {
    553                 FileInputStream file = new FileInputStream(Utility.BASE_DIR + "classifiers.dat");
    554                 ObjectInputStream input = new ObjectInputStream(file);
    555                 reserve = (DynamicListModel) input.readObject();
    556           }
    557           catch (Exception error) {
    558           }
    559           if(reserve == null) {
    560                 reserve = new DynamicListModel();
     550    private void loadClassifiers() {
     551    // Attempt to restore the cached file.
     552    try {
     553        FileInputStream file = new FileInputStream(Utility.BASE_DIR + "classifiers.dat");
     554        ObjectInputStream input = new ObjectInputStream(file);
     555        reserve = (DynamicListModel) input.readObject();
     556    }
     557    catch (Exception error) {
     558    }
     559    if(reserve == null) {
     560        reserve = new DynamicListModel();
    561561                // Retrieve the gsdl home directory...
    562                 String directory = gatherer.config.gsdl_path;
    563                 directory = directory + "perllib" + File.separator + "classify" + File.separator;
    564                 loadClassifiers(new File(directory));
    565           }
    566     }
    567     /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location.
     562        String directory = gatherer.config.gsdl_path;
     563        directory = directory + "perllib" + File.separator + "classify" + File.separator;
     564        loadClassifiers(new File(directory));
     565    }
     566    }
     567    /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location.
    568568      * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins.
    569569      * @see org.greenstone.gatherer.cdm.ParsingProgress
    570570      */
    571     private void loadClassifiers(File directory) {
    572           File files[] = directory.listFiles();
    573           if(files != null) {
     571    private void loadClassifiers(File directory) {
     572    File files[] = directory.listFiles();
     573    if(files != null) {
    574574                // Create a progress indicator.
    575                 ParsingProgress progress = new ParsingProgress(get("CDM.ClassifierManager.Parsing.Title"), get("CDM.ClassifierManager.Parsing.Message"), files.length);
    576                 for(int i = 0; i < files.length; i++) {
    577                      // We only want to check Perl Modules.
    578                      if(files[i].getName().endsWith(".pm")) {
    579                           loadClassifier(files[i]);
    580                      }
    581                      progress.inc();
    582                 }
    583                 progress.dispose();
    584                 progress.destroy();
    585                 progress = null;
    586           }
    587     }
    588     /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
     575        ParsingProgress progress = new ParsingProgress(get("CDM.ClassifierManager.Parsing.Title"), get("CDM.ClassifierManager.Parsing.Message"), files.length);
     576        for(int i = 0; i < files.length; i++) {
     577        // We only want to check Perl Modules.
     578        if(files[i].getName().endsWith(".pm")) {
     579            loadClassifier(files[i]);
     580        }
     581        progress.inc();
     582        }
     583        progress.dispose();
     584        progress.destroy();
     585        progress = null;
     586    }
     587    }
     588    /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
    589589      * @param root The <strong>Node</strong> at the root of the DOM model.
    590590      * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model.
    591591      * @see org.greenstone.gatherer.cdm.Argument
    592592      */
    593      private Classifier parse(Node root) {
    594           Classifier classifier = new Classifier();
    595           String node_name = null;
    596           for(Node node = root.getFirstChild(); node != null;
    597                 node = node.getNextSibling()) {
    598                 node_name = node.getNodeName();
    599                 if(node_name.equals("Name")) {
    600                      String name = MSMUtils.getValue(node);
    601                      // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it.
    602                      Classifier existing = getClassifier(name);
    603                      if(existing != null) {
    604                           return existing;
    605                      }
    606                      classifier.setName(name);
     593    private Classifier parse(Node root) {
     594    Classifier classifier = new Classifier();
     595    String node_name = null;
     596    for(Node node = root.getFirstChild(); node != null;
     597        node = node.getNextSibling()) {
     598        node_name = node.getNodeName();
     599        if(node_name.equals("Name")) {
     600        String name = MSMUtils.getValue(node);
     601        // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it.
     602        Classifier existing = getClassifier(name);
     603        if(existing != null) {
     604            return existing;
     605        }
     606        classifier.setName(name);
     607        }
     608        else if(node_name.equals("Desc")) {
     609        classifier.setDesc(MSMUtils.getValue(node));
     610        }
     611                // Parse the multitude of arguments.
     612        else if(node_name.equals("Arguments")) {
     613        for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
     614            node_name = arg.getNodeName();
     615            // An option.
     616            if(node_name.equals("Option")) {
     617            Argument argument = new Argument();
     618            // If its an option we parse the multitude of details an options might have.
     619            for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
     620                node_name = det.getNodeName();
     621                if(node_name.equals("Name")) {
     622                argument.setName(MSMUtils.getValue(det));
     623                }
     624                else if(node_name.equals("Desc")) {
     625                argument.setDesc(MSMUtils.getValue(det));
     626                }
     627                else if(node_name.equals("Type")) {
     628                argument.setType(MSMUtils.getValue(det));
     629                }
     630                else if(node_name.equals("Default")) {
     631                argument.setDefault(MSMUtils.getValue(det));
     632                }
     633                else if(node_name.equals("List")) {
     634                // Two final loops are required to parse lists.
     635                for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) {
     636                    if(value.getNodeName().equals("Value")) {
     637                    String key = null;
     638                    String desc = "";
     639                    for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
     640                        node_name = subvalue.getNodeName();
     641                        if(node_name.equals("Name")) {
     642                        key = MSMUtils.getValue(subvalue);
     643                        }
     644                        else if(node_name.equals("Desc")) {
     645                        desc = MSMUtils.getValue(subvalue);
     646                        }
     647                    }
     648                    if(key != null) {
     649                        argument.addOption(key, desc);
     650                    }
     651                    }
    607652                }
    608                 else if(node_name.equals("Desc")) {
    609                      classifier.setDesc(MSMUtils.getValue(node));
     653                }
     654                else if(node_name.equals("Required")) {
     655                String v = MSMUtils.getValue(det);
     656                ///ystem.err.println("Required = " + v);
     657                if(v.equalsIgnoreCase("yes")) {
     658                    ///ystem.err.println("Setting required to true.");
     659                    argument.setRequired(true);
    610660                }
    611                 // Parse the multitude of arguments.
    612                 else if(node_name.equals("Arguments")) {
    613                      for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
    614                           node_name = arg.getNodeName();
    615                           // An option.
    616                           if(node_name.equals("Option")) {
    617                                 Argument argument = new Argument();
    618                                 // If its an option we parse the multitude of details an options might have.
    619                                 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
    620                                      node_name = det.getNodeName();
    621                                      if(node_name.equals("Name")) {
    622                                           argument.setName(MSMUtils.getValue(det));
    623                                      }
    624                                      else if(node_name.equals("Desc")) {
    625                                           argument.setDesc(MSMUtils.getValue(det));
    626                                      }
    627                                      else if(node_name.equals("Type")) {
    628                                           argument.setType(MSMUtils.getValue(det));
    629                                      }
    630                                      else if(node_name.equals("Default")) {
    631                                           argument.setDefault(MSMUtils.getValue(det));
    632                                      }
    633                                      else if(node_name.equals("List")) {
    634                                           // Two final loops are required to parse lists.
    635                                           for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) {
    636                                                 if(value.getNodeName().equals("Value")) {
    637                                                      String key = null;
    638                                                      String desc = "";
    639                                                      for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
    640                                                           node_name = subvalue.getNodeName();
    641                                                           if(node_name.equals("Name")) {
    642                                                                 key = MSMUtils.getValue(subvalue);
    643                                                           }
    644                                                           else if(node_name.equals("Desc")) {
    645                                                                 desc = MSMUtils.getValue(subvalue);
    646                                                           }
    647                                                      }
    648                                                      if(key != null) {
    649                                                           argument.addOption(key, desc);
    650                                                      }
    651                                                 }
    652                                           }
    653                                      }
    654                                      else if(node_name.equals("Required")) {
    655                                           String v = MSMUtils.getValue(det);
    656                                           ///ystem.err.println("Required = " + v);
    657                                           if(v.equalsIgnoreCase("yes")) {
    658                                                 ///ystem.err.println("Setting required to true.");
    659                                                 argument.setRequired(true);
    660                                           }
    661                                      }
    662                                 }
    663                                 classifier.addArgument(argument);
    664                           }
    665                           // A super classifier class.
    666                           else if(node_name.equals("ClasInfo")) {
    667                                 Classifier super_classifier = parse(arg);
    668                                 classifier.setSuper(super_classifier);
    669                           }
    670                      }
    671                 }
    672           }
    673           if(classifier.getName() != null) {
    674                 addClassifier(classifier);
    675                 return classifier;
    676           }
    677           return null;
    678      }
    679      /** A class which provides controls for assigned and editing classifiers. */
    680      private class Control
    681           extends JPanel {
    682           /** Button for adding classifiers. */
    683           private JButton add = null;
    684           /** Button for configuring the selected classifier. */
    685           private JButton configure = null;
    686           /** Button to remove the selected classifier. */
    687           private JButton remove = null;
    688           /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
    689           private JComboBox classifier = null;
    690           /** A list of assigned classifiers. */
    691           private JList classifier_list = null;
    692           /** The text area containing instructions on the use of this control. */
    693           private JTextArea instructions = null;
    694           /** Constructor.
    695             * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener
    696             * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener
    697             * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener
     661                }
     662            }
     663            classifier.addArgument(argument);
     664            }
     665            // A super classifier class.
     666            else if(node_name.equals("ClasInfo")) {
     667            Classifier super_classifier = parse(arg);
     668            classifier.setSuper(super_classifier);
     669            }
     670        }
     671        }
     672    }
     673    if(classifier.getName() != null) {
     674        addClassifier(classifier);
     675        return classifier;
     676    }
     677    return null;
     678    }
     679    /** A class which provides controls for assigned and editing classifiers. */
     680    private class Control
     681    extends JPanel {
     682    /** Button for adding classifiers. */
     683    private JButton add = null;
     684    /** Button for configuring the selected classifier. */
     685    private JButton configure = null;
     686    /** Button to remove the selected classifier. */
     687    private JButton remove = null;
     688    /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
     689    private JComboBox classifier = null;
     690    /** A list of assigned classifiers. */
     691    private JList classifier_list = null;
     692    /** The text area containing instructions on the use of this control. */
     693    private JTextArea instructions = null;
     694    /** Constructor.
     695     * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener
     696     * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener
     697     * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener
     698     */
     699    public Control() {
     700        Object classifiers[] = reserve.toArray();
     701        ArrayList classifier_model = new ArrayList();
     702        for(int i = 0; i < classifiers.length; i++) {
     703        classifier_model.add(((Classifier)classifiers[i]).getName());
     704        }
     705                // Now we add custom classifiers.
     706        addCustomClassifiers(classifier_model);
     707        Collections.sort(classifier_model);
     708                // Create
     709        add = new JButton(get("Add"));
     710        JPanel button_pane = new JPanel();
     711        JPanel central_pane = new JPanel();
     712        configure = new JButton(get("Configure"));
     713        JPanel header_pane = new JPanel();
     714        instructions = new JTextArea(get("Instructions"));
     715        instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
     716        instructions.setEditable(false);
     717        instructions.setLineWrap(true);
     718        instructions.setRows(5);
     719        instructions.setWrapStyleWord(true);
     720        classifier = new JComboBox(classifier_model.toArray());
     721        classifier.setEditable(true);
     722        JLabel classifier_label = new JLabel(get("Classifier"));
     723        classifier_list = new JList(assigned);
     724        JLabel classifier_list_label = new JLabel(get("Assigned"));
     725        classifier_list_label.setHorizontalAlignment(JLabel.CENTER);
     726        classifier_list_label.setOpaque(true);
     727        JPanel classifier_list_pane = new JPanel();
     728        JPanel classifier_pane = new JPanel();
     729        remove = new JButton(get("Remove"));
     730        JLabel title = new JLabel(get("Title"));
     731        title.setHorizontalAlignment(JLabel.CENTER);
     732        title.setOpaque(true);
     733        JPanel temp = new JPanel(new BorderLayout());
     734                // Listeners
     735        add.addActionListener(new AddListener());
     736        configure.addActionListener(new ConfigureListener());
     737        remove.addActionListener(new RemoveListener());
     738        classifier_list.addMouseListener(new ClickListener());
     739                // Layout
     740        title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
     741        instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
     742        header_pane.setLayout(new BorderLayout());
     743        header_pane.add(title, BorderLayout.NORTH);
     744        header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
     745        classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
     746        classifier_list_pane.setLayout(new BorderLayout());
     747        classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
     748        classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
     749        classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
     750        classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
     751        classifier_pane.setLayout(new GridLayout(1,2));
     752        classifier_pane.add(classifier_label);
     753        classifier_pane.add(classifier);
     754        button_pane.setLayout(new GridLayout(3,1));
     755        button_pane.add(add);
     756        button_pane.add(configure);
     757        button_pane.add(remove);
     758                // Scope these mad bordering skillz.
     759        temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2))));
     760        temp.add(classifier_pane, BorderLayout.NORTH);
     761        temp.add(button_pane, BorderLayout.SOUTH);
     762        central_pane.setLayout(new BorderLayout());
     763        central_pane.add(classifier_list_pane, BorderLayout.CENTER);
     764        central_pane.add(temp, BorderLayout.SOUTH);
     765        setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
     766        setLayout(new BorderLayout());
     767        add(header_pane, BorderLayout.NORTH);
     768        add(central_pane, BorderLayout.CENTER);
     769    }
     770    /** Method which acts like a destructor, tidying up references to persistant objects.
    698771            */
    699           public Control() {
    700                 Object classifiers[] = reserve.toArray();
    701                 ArrayList classifier_model = new ArrayList();
    702                 for(int i = 0; i < classifiers.length; i++) {
    703                      classifier_model.add(((Classifier)classifiers[i]).getName());
    704                 }
    705                 // Now we add custom classifiers.
    706                 addCustomClassifiers(classifier_model);
    707                 Collections.sort(classifier_model);
    708                 // Create
    709                 add = new JButton(get("Add"));
    710                 JPanel button_pane = new JPanel();
    711                 JPanel central_pane = new JPanel();
    712                 configure = new JButton(get("Configure"));
    713                 JPanel header_pane = new JPanel();
    714                 instructions = new JTextArea(get("Instructions"));
    715                 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
    716                 instructions.setEditable(false);
    717                 instructions.setLineWrap(true);
    718                 instructions.setRows(5);
    719                 instructions.setWrapStyleWord(true);
    720                 classifier = new JComboBox(classifier_model.toArray());
    721                 classifier.setEditable(true);
    722                 JLabel classifier_label = new JLabel(get("Classifier"));
    723                 classifier_list = new JList(assigned);
    724                 JLabel classifier_list_label = new JLabel(get("Assigned"));
    725                 classifier_list_label.setHorizontalAlignment(JLabel.CENTER);
    726                 classifier_list_label.setOpaque(true);
    727                 JPanel classifier_list_pane = new JPanel();
    728                 JPanel classifier_pane = new JPanel();
    729                 remove = new JButton(get("Remove"));
    730                 JLabel title = new JLabel(get("Title"));
    731                 title.setHorizontalAlignment(JLabel.CENTER);
    732                 title.setOpaque(true);
    733                 JPanel temp = new JPanel(new BorderLayout());
    734                 // Listeners
    735                 add.addActionListener(new AddListener());
    736                 configure.addActionListener(new ConfigureListener());
    737                 remove.addActionListener(new RemoveListener());
    738                 classifier_list.addMouseListener(new ClickListener());
    739                 // Layout
    740                 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
    741                 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
    742                 header_pane.setLayout(new BorderLayout());
    743                 header_pane.add(title, BorderLayout.NORTH);
    744                 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
    745                 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
    746                 classifier_list_pane.setLayout(new BorderLayout());
    747                 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
    748                 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
    749                 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
    750                 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
    751                 classifier_pane.setLayout(new GridLayout(1,2));
    752                 classifier_pane.add(classifier_label);
    753                 classifier_pane.add(classifier);
    754                 button_pane.setLayout(new GridLayout(3,1));
    755                 button_pane.add(add);
    756                 button_pane.add(configure);
    757                 button_pane.add(remove);
    758                 // Scope these mad bordering skillz.
    759                 temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2))));
    760                 temp.add(classifier_pane, BorderLayout.NORTH);
    761                 temp.add(button_pane, BorderLayout.SOUTH);
    762                 central_pane.setLayout(new BorderLayout());
    763                 central_pane.add(classifier_list_pane, BorderLayout.CENTER);
    764                 central_pane.add(temp, BorderLayout.SOUTH);
    765                 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    766                 setLayout(new BorderLayout());
    767                 add(header_pane, BorderLayout.NORTH);
    768                 add(central_pane, BorderLayout.CENTER);
    769           }
    770           /** Method which acts like a destructor, tidying up references to persistant objects.
     772    public void destroy() {
     773        add = null;
     774        classifier = null;
     775        classifier_list = null;
     776        configure = null;
     777        instructions = null;
     778        remove = null;
     779    }
     780    /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
    771781            */
    772           public void destroy() {
    773                 add = null;
    774                 classifier = null;
    775                 classifier_list = null;
    776                 configure = null;
    777                 instructions = null;
    778                 remove = null;
    779           }
    780           /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
    781             */
    782           public void updateUI() {
    783                 if(instructions != null) {
    784                      instructions.setCaretPosition(0);
    785                 }
    786                 super.updateUI();
    787           }
    788           /** Searches and adds a list of dynamically located CustomClassifiers. Note that the classes must be located under org.greenstone.gatherer.cdm.custom and have accompaning properties files which are used as dictionaries.
     782    public void updateUI() {
     783        if(instructions != null) {
     784        instructions.setCaretPosition(0);
     785        }
     786        super.updateUI();
     787    }
     788    /** Searches and adds a list of dynamically located CustomClassifiers. Note that the classes must be located under org.greenstone.gatherer.cdm.custom and have accompaning properties files which are used as dictionaries.
    789789            * @param classifier_model An <strong>ArrayList</strong> which will be used as the model for the combobox listing all known Classifiers.
    790790            */
    791           private void addCustomClassifiers(ArrayList classifier_model) {
     791    private void addCustomClassifiers(ArrayList classifier_model) {
    792792                //classifier_model.add("CustomAZList");
    793793                // Search for classifiers under the org.greenstone.gatherer.cdm.custom directory.
    794                 File custom_directory = new File(Utility.BASE_DIR + "classes" + File.separator + "org" + File.separator + "greenstone" + File.separator + "gatherer" + File.separator + "cdm" + File.separator + "custom");
    795                 if(custom_directory.exists()) {
    796                      File children[] = custom_directory.listFiles();
    797                      for(int i = 0; i < children.length; i++) {
    798                           String temp = children[i].getName().toLowerCase();
    799                           // There are a whole bunch of conditions about what files are custom classifier main classes.
    800                           if(temp.endsWith(".class") && temp.indexOf("$") == -1) {
    801                                 // Determine the name of this custom classifier.
    802                                 String name = children[i].getName();
    803                                 name = name.substring(0, name.indexOf("."));
    804                                 classifier_model.add(name);
    805                           }
    806                      }
    807                 }
     794        File custom_directory = new File(Utility.BASE_DIR + "classes" + File.separator + "org" + File.separator + "greenstone" + File.separator + "gatherer" + File.separator + "cdm" + File.separator + "custom");
     795        if(custom_directory.exists()) {
     796        File children[] = custom_directory.listFiles();
     797        for(int i = 0; i < children.length; i++) {
     798            String temp = children[i].getName().toLowerCase();
     799            // There are a whole bunch of conditions about what files are custom classifier main classes.
     800            if(temp.endsWith(".class") && temp.indexOf("$") == -1) {
     801            // Determine the name of this custom classifier.
     802            String name = children[i].getName();
     803            name = name.substring(0, name.indexOf("."));
     804            classifier_model.add(name);
     805            }
     806        }
     807        }
    808808                // Search for any other CustomClassifiers within the jar file (if present)
    809                 File jar_file = new File("Gatherer.jar");
    810                 if(jar_file.exists()) {
    811                      try {
    812                           JarFile jar = new JarFile(jar_file);
    813                           for(Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
    814                                 String name = entries.nextElement().toString();
    815                                 if(name.startsWith("org/greenstone/gatherer/cdm/custom/") && name.endsWith(".class") && name.indexOf("$") == -1) {
    816                                     name = name.substring(35, name.length() - 6);
    817                                     if(!classifier_model.contains(name)) {
    818                                           classifier_model.add(name);
    819                                     }
    820                                 }
    821                                 name = null;
    822                           }
    823                           jar = null;
    824                      }
    825                      catch (Exception error) {
    826                           error.printStackTrace();
    827                      }
    828                 }
    829                 jar_file = null;
    830           }
    831           /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
     809        File jar_file = new File("Gatherer.jar");
     810        if(jar_file.exists()) {
     811        try {
     812            JarFile jar = new JarFile(jar_file);
     813            for(Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
     814            String name = entries.nextElement().toString();
     815            if(name.startsWith("org/greenstone/gatherer/cdm/custom/") && name.endsWith(".class") && name.indexOf("$") == -1) {
     816                name = name.substring(35, name.length() - 6);
     817                if(!classifier_model.contains(name)) {
     818                classifier_model.add(name);
     819                }
     820            }
     821            name = null;
     822            }
     823            jar = null;
     824        }
     825        catch (Exception error) {
     826            error.printStackTrace();
     827        }
     828        }
     829        jar_file = null;
     830    }
     831    /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
    832832            */
    833           private class AddListener
    834                 implements ActionListener {
     833    private class AddListener
     834        implements ActionListener {
    835835                /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of our target controls, so that we can add the selected Classifier.
    836836                 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
     
    840840                 * @see org.greenstone.gatherer.cdm.CustomClassifier
    841841                 */
    842                 public void actionPerformed(ActionEvent event) {
    843                      String name = (String)classifier.getSelectedItem();
    844                      Classifier target = getClassifier(name);
    845                      Classifier classifier = null;
    846                      CustomClassifier custom_classifier = null;
    847                      if(target != null) {
    848                           classifier = target.copy();
    849                      }
    850                      else {
    851                           // Try to retrieve custom classifier for name.
    852                           try {
    853                                 Class custom_class = Class.forName("org.greenstone.gatherer.cdm.custom." + name);
    854                                 custom_classifier = (CustomClassifier)custom_class.newInstance();
    855                                 custom_classifier.setGatherer(gatherer);
    856                           }
    857                           catch (Exception error) {
    858                                 gatherer.debug(error, "Error in ClassifierManager.AddListener.actionPerformed(): " + error);
    859                           }
    860                           // And if all else fails create a new classifier.
    861                           if(classifier == null && custom_classifier == null) {
    862                                 classifier = new Classifier(name, "", null);
    863                           }
    864                      }
    865                      if(classifier != null) {
    866                           // Automatically chain to configuration. This ensures required arguments are filled out.
    867                           ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, classifier);
    868                           if(ac.display()) {
    869                                 assignClassifier(classifier);
    870                           }
    871                           ac.destroy();
    872                           ac = null;
    873                      }
    874                      // Custom classifier
    875                      else {
    876                           if(custom_classifier.display(true)) {
    877                                 assignClassifier(custom_classifier);
    878                           }
    879                           custom_classifier.destroy(); // Remove gui prompt or else.
    880                           custom_classifier = null;
    881                      }
    882                 }
    883           }
    884           /** Listens for double clicks apon the list and react as if the configure button was pushed. */
    885           private class ClickListener
    886                 extends MouseAdapter {
     842        public void actionPerformed(ActionEvent event) {
     843        String name = (String)classifier.getSelectedItem();
     844        Classifier target = getClassifier(name);
     845        Classifier classifier = null;
     846        CustomClassifier custom_classifier = null;
     847        if(target != null) {
     848            classifier = target.copy();
     849        }
     850        else {
     851            // Try to retrieve custom classifier for name.
     852            try {
     853            Class custom_class = Class.forName("org.greenstone.gatherer.cdm.custom." + name);
     854            custom_classifier = (CustomClassifier)custom_class.newInstance();
     855            custom_classifier.setGatherer(gatherer);
     856            }
     857            catch (Exception error) {
     858            gatherer.debug(error, "Error in ClassifierManager.AddListener.actionPerformed(): " + error);
     859            }
     860            // And if all else fails create a new classifier.
     861            if(classifier == null && custom_classifier == null) {
     862            classifier = new Classifier(name, "", null);
     863            }
     864        }
     865        if(classifier != null) {
     866            // Automatically chain to configuration. This ensures required arguments are filled out.
     867            ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, classifier);
     868            if(ac.display()) {
     869            assignClassifier(classifier);
     870            }
     871            ac.destroy();
     872            ac = null;
     873        }
     874        // Custom classifier
     875        else {
     876            if(custom_classifier.display(true)) {
     877            assignClassifier(custom_classifier);
     878            }
     879            custom_classifier.destroy(); // Remove gui prompt or else.
     880            custom_classifier = null;
     881        }
     882        }
     883    }
     884    /** Listens for double clicks apon the list and react as if the configure button was pushed. */
     885    private class ClickListener
     886        extends MouseAdapter {
    887887                /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
    888888                 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
    889889                 */
    890                 public void mouseClicked(MouseEvent event) {
    891                      if(event.getClickCount() == 2 ) {
    892                           if(!classifier_list.isSelectionEmpty()) {
    893                                 Object object = classifier_list.getSelectedValue();
    894                                 if(object instanceof Classifier) {
    895                                     ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
    896                                     if(ac.display()) {
    897                                           assigned.refresh();
    898                                     }
    899                                     ac.destroy();
    900                                     ac = null;
    901                                 }
    902                                 else if(object instanceof CustomClassifier) {
    903                                     CustomClassifier cc = (CustomClassifier)object;
    904                                     if(cc.display(true)) {
    905                                           assigned.refresh();
    906                                     }
    907                                     cc.destroy(); // Remove gui prompt or else.
    908                                     cc = null;
    909                                 }
    910                           }
    911                      }
    912                 }
    913           }
    914           /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
     890        public void mouseClicked(MouseEvent event) {
     891        if(event.getClickCount() == 2 ) {
     892            if(!classifier_list.isSelectionEmpty()) {
     893            Object object = classifier_list.getSelectedValue();
     894            if(object instanceof Classifier) {
     895                ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
     896                if(ac.display()) {
     897                assigned.refresh();
     898                }
     899                ac.destroy();
     900                ac = null;
     901            }
     902            else if(object instanceof CustomClassifier) {
     903                CustomClassifier cc = (CustomClassifier)object;
     904                if(cc.display(true)) {
     905                assigned.refresh();
     906                }
     907                cc.destroy(); // Remove gui prompt or else.
     908                cc = null;
     909            }
     910            }
     911        }
     912        }
     913    }
     914    /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
    915915            */
    916           private class ConfigureListener
    917                 implements ActionListener {
     916    private class ConfigureListener
     917        implements ActionListener {
    918918                /** 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.
    919919                 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
     
    922922                 * @see org.greenstone.gatherer.cdm.CustomClassifier
    923923                 */
    924                 public void actionPerformed(ActionEvent event) {
    925                      if(!classifier_list.isSelectionEmpty()) {
    926                           Object object = classifier_list.getSelectedValue();
    927                           if(object instanceof Classifier) {
    928                                 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
    929                                 if(ac.display()) {
    930                                     assigned.refresh();
    931                                 }
    932                                 ac.destroy();
    933                                 ac = null;
    934                           }
    935                           else if(object instanceof CustomClassifier) {
    936                                 CustomClassifier cc = (CustomClassifier)object;
    937                                 if(cc.display(true)) {
    938                                     assigned.refresh();
    939                                 }
    940                                 cc.destroy(); // Remove gui prompt or else.
    941                                 cc = null;
    942                           }
    943                      }
    944                 }
    945           }
    946           /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() method.
     924        public void actionPerformed(ActionEvent event) {
     925        if(!classifier_list.isSelectionEmpty()) {
     926            Object object = classifier_list.getSelectedValue();
     927            if(object instanceof Classifier) {
     928            ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
     929            if(ac.display()) {
     930                assigned.refresh();
     931            }
     932            ac.destroy();
     933            ac = null;
     934            }
     935            else if(object instanceof CustomClassifier) {
     936            CustomClassifier cc = (CustomClassifier)object;
     937            if(cc.display(true)) {
     938                assigned.refresh();
     939            }
     940            cc.destroy(); // Remove gui prompt or else.
     941            cc = null;
     942            }
     943        }
     944        }
     945    }
     946    /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() method.
    947947            */
    948           private class RemoveListener
    949                 implements ActionListener {
     948    private class RemoveListener
     949        implements ActionListener {
    950950                /** 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, so we can remove the selected Classifier.
    951951                 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
     
    953953                 * @see org.greenstone.gatherer.cdm.CustomClassifier
    954954                 */
    955                 public void actionPerformed(ActionEvent event) {
    956                      if(!classifier_list.isSelectionEmpty()) {
    957                           Object object = classifier_list.getSelectedValue();
    958                           if(object instanceof Classifier || object instanceof CustomClassifier) {
    959                                 removeClassifier(object);
    960                           }
    961                      }
    962                 }
    963           }
    964     }
     955        public void actionPerformed(ActionEvent event) {
     956        if(!classifier_list.isSelectionEmpty()) {
     957            Object object = classifier_list.getSelectedValue();
     958            if(object instanceof Classifier || object instanceof CustomClassifier) {
     959            removeClassifier(object);
     960            }
     961        }
     962        }
     963    }
     964    }
    965965}
    966966
Note: See TracChangeset for help on using the changeset viewer.