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/Classifier.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 
    43 /* GPL_HEADER */
    4427package org.greenstone.gatherer.cdm;
    4528/**************************************************************************************
    46  * Title:        Gatherer
    47  * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
    48  * Company:      The University of Waikato
    4929 * Written:      01/05/02
    5030 * Revised:      16/08/02 Optimized and Commented.
     31 *               11/07/03 DOM support
    5132 **************************************************************************************/
    52 import java.io.Serializable;
    53 import java.util.ArrayList;
     33import java.io.*;
     34import java.util.*;
    5435import org.greenstone.gatherer.cdm.Argument;
    5536import org.greenstone.gatherer.cdm.ArgumentContainer;
    56 import org.greenstone.gatherer.cdm.CustomClassifier;
    57 import org.greenstone.gatherer.cdm.Format;
     37import org.greenstone.gatherer.cdm.CollectionConfiguration;
     38import org.greenstone.gatherer.cdm.CollectionDesignManager;
     39import org.greenstone.gatherer.cdm.DOMProxyListEntry;
     40import org.greenstone.gatherer.util.StaticStrings;
     41import org.greenstone.gatherer.util.Utility;
     42import org.w3c.dom.*;
    5843/** This class is responsible for storing information from a parsed classinfo.pl call in such a way that it allows easy access to parsed details for the purposes of user design and specification of classifiers.
    5944 * @author John Thompson, Greenstone Digital Library, University of Waikato
    6045 * @version 2.3
    6146 */
    62 // ####################################################################################
    63 // Optimization                          Saving
    64 // ####################################################################################
    65 // Vector -> ArrayList (x8)              + Processor
    66 // ####################################################################################
    6747public class Classifier
    6848    extends ArrayList
    69     implements ArgumentContainer, Comparable, Serializable {
     49    implements ArgumentContainer, Comparable, DOMProxyListEntry, Serializable {
     50
     51    static final public String CLASSIFIER_PREFIX = "CL";
     52
    7053    /** A reference to the classifier that this one inherits from. */
    7154    private Classifier super_classifier = null;
    72     /** A reference to the manager of this classifier. Only available once the classifiers been assigned, always <i>null</i> for classifiers in reserve. */
    73     private ClassifierManager manager = null;
    74     /** Custom arguments (ie those unparsable from classinfo.pl) provided to this class. */
    75     private String custom = null;
     55    /** The element this classifier is based upon. */
     56    private Element element;
    7657    /** A description of this classifier. */
    77     private String desc = null;
     58    private String description = null;
    7859    /** The name of the classifier as it would appear in the collect.cfg file. */
    7960    private String name = null;
    80     /** A list of format commands that are dependant on this classifier. */
    81     private ArrayList dependant_formats = null;
    82     /** Default Constructor.
     61    /** This string is filled out the first time this classifier is created, and remains unchanged there-after. It is used to match up with Format commands that may not yet have been instantiated (and thus only have offline references along the lines of 'CL1' to figure out what Classifier they want.) */
     62    private String old_position_string = null;
     63
     64    /** Constructor used only in DOMProxyListModel initializations.
    8365     */
    8466    public Classifier() {
     67    }
     68
     69    public Classifier(Element element, Classifier base_classifier) {
    8570    super();
    86     dependant_formats = new ArrayList();
    87     }
     71    this.element = element;
     72    this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
     73    ///atherer.println("Establishing Classifier: " + name);
     74    // Parse in any argument options for this classifier, keeping a list of the ones found
     75    HashMap known_arguments = new HashMap();
     76    NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
     77    int option_elements_length = option_elements.getLength();
     78    for(int i = 0; i < option_elements_length; i++) {
     79        Element option_element = (Element) option_elements.item(i);
     80        Argument argument = new Argument(option_element);
     81        ///atherer.println("Rebuilding existing argument: " + argument.getName());
     82        argument.setOwner(name);
     83        add(argument);
     84        known_arguments.put(argument.getName(), argument);
     85    }
     86    // If a base classifier was given
     87    if(base_classifier != null) {
     88        // Copy the details, and add a reference to whatever base_classifiers super classifier is.
     89        description = base_classifier.getDescription();
     90        // Now search through the 'dummy' arguments belonging to the base classifier. For each found, if it is already assigned, fill out further details such as type. If any are found that are not already assigned for this classifier, copy them and add them, but without a value.
     91        ArrayList all_arguments = base_classifier.getArguments(true, true);
     92        int argument_count = all_arguments.size();
     93        for(int j = 0; j < argument_count; j++) {
     94        Argument base_argument = (Argument) all_arguments.get(j);
     95        String base_argument_name = base_argument.getName();
     96        ///atherer.println("Library indicates this classifier should have an argument: " + base_argument_name);
     97        Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
     98        // Found an existing argument. Complete its details
     99        if(existing_argument != null) {
     100            ///atherer.println("Found existing argument. Filling out details.");
     101            existing_argument.setCustomArgument(false);
     102            existing_argument.setDefaultValue(base_argument.getDefaultValue());
     103            existing_argument.setDescription(base_argument.getDescription());
     104            existing_argument.setOptions(base_argument.getOptions());
     105            existing_argument.setRequired(base_argument.isRequired());
     106            existing_argument.setType(base_argument.getType());
     107        }
     108        // No existing argument. Copy base_argument and add it, but do not set its assigned flag. That should be set the first time its changed by the user.
     109        else {
     110            ///atherer.println("No such argument. Adding new, unassigned, argument.");
     111            // The trick thing is that we have to create a new element in the DOM as well.
     112            Argument new_argument = base_argument.copy();
     113            Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
     114            argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
     115            argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
     116            argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.FALSE_STR);
     117            new_argument.setElement(argument_element);
     118            // All done. Add it.
     119            element.appendChild(argument_element);
     120            add(new_argument);
     121        }
     122        }
     123    }
     124    old_position_string = getPositionString();
     125    }
     126
    88127    /** Constructor.
    89128      * @param name The name of this classifier as a <strong>String</strong>.
     
    91130      * @param super_classifier The super class of this classifier, as a <strong>Classifier</strong>.
    92131      */
    93     public Classifier(String name, String desc, Classifier super_classifier) {
    94     this();
    95     this.desc = desc;
     132    public Classifier(String name, String description, Classifier super_classifier) {
     133    super();
     134    this.description = description;
    96135    this.name = name;
    97136    this.super_classifier = super_classifier;
    98137    }
     138
    99139    /** Method to add an argument to this classifier. Only adds the argument if it isn't already present.
    100140      * @param argument The <strong>Argument</strong> to add.
    101141      */
    102142    public void addArgument(Argument argument) {
    103     if(!contains(argument)) {
     143    if(element == null && !contains(argument)) {
    104144        add(argument);
    105145        argument.setOwner(name);
    106146    }
    107147    }
    108     /** Method to register a dependant format with this classifier. If the classifier changes, this format also needs to be updated.
    109       * @param format A <strong>Format</strong> which is dependant on this classifier.
    110       */
    111     public void addDependantFormat(Format format) {
    112     dependant_formats.add(format);
    113     }
     148
    114149    /** Method to compare two classifiers for ordering.
    115150      * @param object The classifier we are comparing to, as an <strong>Object</strong>.
     
    118153      */
    119154    public int compareTo(Object object) {
    120     if(object instanceof Classifier) {
    121         Classifier classifier = (Classifier) object;
    122         return name.compareTo(classifier.getName());
    123     }
    124     return name.compareTo(object.toString());
    125     }
    126     /** This method produces a deep copy of this classifier. Note that this also creates a new copy of each of the super classes of classifiers as well. This is the way it should be, as each assigned classifier may have different values for the higher classifiers (such as BasPlug).
    127       * @return A newly created <strong>Classifier</strong> with the same details and Arguments as this one.
    128       * @see org.greenstone.gatherer.cdm.Argument
    129       */
    130     public Classifier copy() {
    131     Classifier copy = null;
    132     if(super_classifier == null) {
    133         copy = new Classifier(name, desc, null);
    134     }
    135     else {
    136         copy = new Classifier(name, desc, super_classifier.copy());
    137     }
    138     for(int i = 0; i < size(); i++) {
    139         copy.addArgument(((Argument)get(i)).copy());
    140     }
    141     return copy;
    142     }
     155    if(object == null) {
     156        return -1;
     157    }
     158    return toString().compareTo(object.toString());
     159    }
     160
     161    /** The assigned classifier constructor.
     162     * @param element the DOM Element this classifier is based upon
     163     * @param base_classifier the Classifier from the stored library showing details about this classifier, may be null
     164     */
     165    public DOMProxyListEntry create(Element element) {
     166    String classifier_name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
     167    // Determine the base classifier from the classifier name
     168    Classifier base_classifier = CollectionDesignManager.classifier_manager.getBaseClassifier(classifier_name);
     169    Classifier classifier = new Classifier(element, base_classifier);
     170    base_classifier = null;
     171    classifier_name = null;
     172    return classifier;
     173    }
     174
    143175    /** Method to determine if two classifiers are equal.
    144       * @param object The classifier to test against, as an <strong>Object</strong>.
    145       * @return <i>true</i> if the classifier names match, <i>false</i> otherwise.
    146       * @see org.greenstone.gatherer.cdm.CustomClassifier
    147       */
     176     * @param object The classifier to test against, as an <strong>Object</strong>.
     177     * @return <i>true</i> if the classifier names match, <i>false</i> otherwise.
     178     * @see org.greenstone.gatherer.cdm.CustomClassifier
     179     */
    148180    public boolean equals(Object object) {
    149     if(object instanceof CustomClassifier) {
    150         CustomClassifier classifier = (CustomClassifier) object;
    151         return (toString().equalsIgnoreCase(classifier.getCommand()));
    152     }
    153     else {
    154         return(toString().equalsIgnoreCase(object.toString()));
    155     }
    156     }
     181    return (compareTo(object) == 0);
     182    }
     183
    157184    /** Method to retrieve an argument by its name.
    158       * @param name The name of the argument as a <strong>String</strong>.
    159       * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
    160       */
     185     * @param name The name of the argument as a <strong>String</strong>.
     186     * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
     187     */
    161188    public Argument getArgument(String name) {
    162189    // The name given may still include the '-'
     
    164191        name = name.substring(1);
    165192    }
    166     ArrayList arguments = getArguments();
     193    ArrayList arguments = getArguments(true, true);
    167194    for(int i = 0; i < arguments.size(); i++) {
    168195        Argument argument = (Argument)arguments.get(i);
     
    173200    return null;
    174201    }
    175     /** Method to retrieve all of the arguments available to a classifier, including both specific and general ones.
    176       * @return A <strong>Hashtable</strong> of arguments, with &lt;name&gt; -&gt; &lt;argument&gt; entries.
    177       */
    178     public ArrayList getArguments() {
    179     ArrayList all_arguments = new ArrayList(this);
     202
     203     /** Retrieve all of the arguments available to this base classifier, including its super classifiers arguments. Some complexity is added by allowing the caller to choose whether they want normal arguments, custom arguments, or both.
     204     * @return an ArrayList of all of the arguments, starting with those for this classifier and ending with the arguments for basplug or similiar root classifier
     205     */
     206    public ArrayList getArguments(boolean include_normal, boolean include_custom) {
     207    ArrayList arguments = new ArrayList();
     208    if(include_normal && include_custom) {
     209        arguments.addAll(this);
     210    }
     211    else {
     212        int size = size();
     213        for(int i = 0; i < size; i++) {
     214        Argument argument = (Argument) get(i);
     215        if(argument.isCustomArgument()) {
     216            if(include_custom && !arguments.contains(argument)) {
     217            arguments.add(argument);
     218            }
     219        }
     220        else {
     221            if(include_normal && !arguments.contains(argument)) {
     222            arguments.add(argument);
     223            }
     224        }
     225        argument = null;
     226        }
     227    }
    180228    if(super_classifier != null) {
    181         ArrayList super_arguments = super_classifier.getArguments();
    182         for(int i = 0; i < super_arguments.size(); i++) {
    183         Object argument = super_arguments.get(i);
    184         if(!all_arguments.contains(argument)) {
    185             all_arguments.add(argument);
    186         }
    187         }
    188     }
    189     return all_arguments;
    190     }
    191     /** Method to retrieve a classifiers custom argument information.
    192       * @return The custom arguments as a <strong>String</strong>.
    193       */
     229        ArrayList remainder = super_classifier.getArguments(include_normal, include_custom);
     230        remainder.removeAll(arguments);
     231        arguments.addAll(remainder);
     232    }
     233    return arguments;
     234    }
     235
     236    /** Method to retrieve a classifiers custom argument information. Custom arguments are defined to be those that have not got matching arguments in the base reference classifier from the library. Of course if there is no base classifier then all arguments are considered to be custom.
     237     * @return the custom arguments as a String
     238     */
    194239    public String getCustom() {
    195     return custom;
    196     }
     240    StringBuffer custom_text = new StringBuffer();
     241    // Retrieve all of the arguments, and append any that are custom into one long string
     242    ArrayList arguments = getArguments(false, true);
     243    int arguments_size = arguments.size();
     244    boolean first = true;
     245    for(int i = 0; i < arguments_size; i++) {
     246        Argument argument = (Argument) arguments.get(i);
     247        if(argument.isAssigned()) {
     248        if(!first) {
     249            custom_text.append(" ");
     250        }
     251        custom_text.append(argument.toString());
     252        first = false;
     253        }
     254    }
     255    return custom_text.toString();
     256    }
     257
     258    public String getDescription() {
     259    return description;
     260    }
     261
     262    public Element getElement() {
     263    return element;
     264    }
     265
    197266    /** Method to retrieve a classifiers name.
    198       * @return A <strong>String</strong> containing the classifiers name.
    199       */
     267     * @return A <strong>String</strong> containing the classifiers name.
     268     */
    200269    public String getName() {
     270    if(name == null && element != null) {
     271        name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
     272    }
    201273    return name;
    202274    }
    203     /** Method to retrieve the position of this classifier as a special keyword or the form "CL#" where # is the classifiers order in the set of classifiers. Note that if this is called for a Classifier that has never been assigned a position of 'Search' is returned, as this is the only case where we will try to write a Classifier that does not have a manager.
    204       * @return A <strong>String</strong> containing the special position keyword.
    205       * @see org.greenstone.gatherer.cdm.ClassifierManager
    206       */
     275
     276    public String getOldPositionString() {
     277    return old_position_string;
     278    }
     279
     280    /** Generate the string showing this classifiers position. */
    207281    public String getPositionString() {
    208     if(manager == null) {
    209         return "Search";
    210     }
    211     return "CL" + (manager.indexOf(this) + 1);
    212     }
    213     /** Method to set the value of custom.
    214       * @param custom The new value of custom as a <strong>String</strong>.
    215       */
    216     public void setCustom(String custom) {
    217     this.custom = custom;
    218     }
    219     /** Method to set the value of desc.
    220       * @param desc The new value of desc as a <strong>String</strong>.
    221       */
    222     public void setDesc(String desc) {
    223     this.desc = desc;
    224     }
    225     /** Method to set the value of manager.
    226       * @param manager The new manager as a <strong>ClassifierManager</strong>.
    227       */
    228     public void setManager(ClassifierManager manager) {
    229     this.manager = manager;
    230     }
    231     /** Method to set the value of name.
    232       * @param name The new value of name as a <strong>String</strong>.
    233       */
     282    String position_string = CLASSIFIER_PREFIX;
     283    if(element != null) {
     284        // Determine our place in the collect.cfg file
     285        int position_int = CollectionDesignManager.classifier_manager.indexOf(this) + 1;
     286        if(position_int != -1) {
     287        position_string = position_string + position_int;
     288        }
     289    }
     290    return position_string;
     291    }
     292
     293    public boolean isAssigned() {
     294    return (element != null && !element.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.FALSE_STR));
     295    }
     296
     297    public void setAssigned(boolean assigned) {
     298    if(element != null) {
     299        element.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (assigned ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR));
     300    }
     301    }
     302
     303    /** Set the custom arguments. This turns out to be quite tricky. We must parse in the string, searching for arguments (for that we use a handy method in CollectionConfiguration). Next, for each argument, we check if we already know about it. If so we update its value, otherwise we create a new argument and assign it (must assign!).
     304     * @param custom_str the custom arguments all splodged together in one String
     305     */
     306    public void setCustom(String custom_str) {
     307    HashMap raw_arguments = CollectionConfiguration.parseArguments(new CommandTokenizer(custom_str));
     308    ArrayList custom_arguments = getArguments(false, true);
     309    int size = custom_arguments.size();
     310    for(int i = 0; i < size; i++) {
     311        Argument argument = (Argument) custom_arguments.get(i);
     312        String original_argument_name = StaticStrings.MINUS_CHARACTER + argument.getName();
     313        if(raw_arguments.containsKey(original_argument_name)) {
     314        // Set as assigned
     315        argument.setAssigned(true);
     316        String argument_value = (String)raw_arguments.remove(original_argument_name);
     317        if(argument_value != null) {
     318            argument.setValue(argument_value);
     319            argument_value = null;
     320        }
     321        }
     322        // We've removed it from our custom statement, so unassign
     323        else {
     324        argument.setAssigned(false);
     325        }
     326        argument = null;
     327    }
     328    // Any left over, add to the classifier
     329    Iterator argument_names = raw_arguments.keySet().iterator();
     330    while(argument_names.hasNext()) {
     331        String argument_name = (String) argument_names.next();
     332        String argument_value = (String) raw_arguments.get(argument_name);
     333        // The tricky thing is that we have to create a new element in the DOM as well.
     334        Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
     335        argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, argument_name.substring(1));
     336        argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
     337        argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.TRUE_STR);
     338        Argument argument = new Argument(argument_element);
     339        argument_name = null;
     340        if(argument_value != null) {
     341        argument.setValue(argument_value);
     342        argument_value = null;
     343        }
     344        // All done. Add it.
     345        element.appendChild(argument_element);
     346        add(argument);
     347        argument_element = null;
     348    }
     349    raw_arguments = null;
     350    }
     351
     352    /** Method to set the value of desc.
     353     * @param desc The new value of desc as a <strong>String</strong>.
     354     */
     355    public void setDescription(String desc) {
     356    this.description = description;
     357    }
     358
     359    public void setElement(Element element) {
     360    this.element = element;
     361    }
     362
     363    /** Method to set the value of name.
     364     * @param name The new value of name as a <strong>String</strong>.
     365     */
    234366    public void setName(String name) {
    235367    this.name = name;
    236368    }
     369
    237370    /** Method to set the value of the super_classifier.
    238       * @param super_classifier The new value of super_classifier as a <strong>Classifier</strong>, or <i>null</i> if this class has no inheritance.
    239       */
     371     * @param super_classifier The new value of super_classifier as a <strong>Classifier</strong>, or <i>null</i> if this class has no inheritance.
     372     */
    240373    public void setSuper(Classifier super_classifier) {
    241374    this.super_classifier = super_classifier;
    242375    }
     376
    243377    /** Method to print out this classifier as it would appear to the user in the interface
    244378      * @return A <strong>String</strong> containing a single classifier command.
    245379      */
    246380    public String toString() {
    247     StringBuffer text = new StringBuffer("classify ");
    248     text.append(name);
    249     text.append(" ");
    250     ArrayList arguments = getArguments();
    251     for(int i = 0; i < arguments.size(); i++) {
    252         Argument argument = (Argument)arguments.get(i);
    253         if(argument.isAssigned()) {
    254         text.append(argument.toString());
    255         text.append(" ");
    256         }
    257     }
    258     if(custom != null) {
    259         text.append(custom);
    260     }
    261     return text.toString();
    262     }
    263     /** Method to print out this classifier as it would appear as a command within the collection configuration file.
    264       * @return A <strong>String</strong> containing a single classifier command.
    265       */
    266     public String toStringConfig() {
    267     StringBuffer text = new StringBuffer("classify ");
    268     text.append(name);
    269     text.append(" ");
    270     ArrayList arguments = getArguments();
    271     for(int i = 0; i < arguments.size(); i++) {
    272         Argument argument = (Argument)arguments.get(i);
    273         if(argument.isAssigned()) {
    274         text.append(argument.toStringConfig());
    275         text.append(" ");
    276         }
    277     }
    278     if(custom != null) {
    279         text.append(custom);
    280     }
    281     return text.toString();
     381    if(element != null) {
     382        if(name == null) {
     383        name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
     384        }
     385        StringBuffer text = new StringBuffer(StaticStrings.CLASSIFY_STR);
     386        text.append(" ");
     387        text.append(name);
     388        text.append(" ");
     389        ArrayList arguments = getArguments(true, true);
     390        int arguments_size = arguments.size();
     391        for(int i = 0; i < arguments_size; i++) {
     392        Argument argument = (Argument)arguments.get(i);
     393        if(argument.isAssigned()) {
     394            text.append(argument.toString());
     395            text.append(" ");
     396        }
     397        }
     398        return text.substring(0, text.length() - 1);
     399    }
     400    else {
     401        return name;
     402    }
    282403    }
    283404}
    284 
    285 
Note: See TracChangeset for help on using the changeset viewer.