/**
*#########################################################################
*
* A component of the Greenstone Librarian Interface (GLI) application,
* part of the Greenstone digital library software suite from the New
* Zealand Digital Library Project at the University of Waikato,
* New Zealand.
*
* Author: John Thompson
* Greenstone Project, New Zealand Digital Library
* University of Waikato
* http://www.nzdl.org
*
* Copyright (C) 2004 New Zealand Digital Library, University of Waikato
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*########################################################################
*/
package org.greenstone.gatherer.cdm;
import java.io.*;
import java.util.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.collection.Collection;
import org.greenstone.gatherer.collection.CollectionManager;
import org.greenstone.gatherer.metadata.MetadataElement;
import org.greenstone.gatherer.metadata.MetadataTools;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;
import org.greenstone.gatherer.util.XMLTools;
import org.w3c.dom.*;
/** This class contains all the details about a single argument that can be passed to this plugin, including option lists if the parameters are restricted.
* @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
* @version 2.41 final
*/
public class Argument
implements Comparable, Serializable {
/** An element of the argument type enumeration specifying a combobox control. */
static final public byte ENUM = 0;
/** An element of the argument type enumeration specifying a checkbox control. */
static final public byte FLAG = 1;
/** An element of the argument type enumeration specifying a tree control. */
static final public byte HIERARCHY = 2;
/** An element of the argument type enumeration specifying a spinner control. */
static final public byte INTEGER = 3;
/** An element of the argument type enumeration specifying a language combobox control. */
static final public byte LANGUAGE = 4;
/** An element of the argument type enumeration specifying a metadata combobox control. */
static final public byte METADATA = 5;
/** An element of the argument type enumeration specifying a text field. */
static final public byte STRING = 6;
/** An element of the argument type enumeration specifying a regular expression text field. */
static final public byte REGEXP = 7;
/** An element of the argument type enumeration specifying a metadata set combobox control. */
static final public byte METADATA_SET_NAMESPACE = 8;
/** An element of the argument type enumeration specifying a text field. */
static final public byte URL = 9;
/** An editable combo box */
static final public byte ENUM_STRING = 10;
/////////////////////////////////////////////////////////////////
/** true if this argument should actually be hidden within the GLI. This is important for arguments such as import dir or other location critical arguments. */
private boolean hidden_gli = false;
/** true if this argument is required for the applicable script to work properly, false otherwise. */
private boolean required = false;
/** The type of this argument. Used to be an int, but bytes are cheaper. */
private byte type = STRING;
/** The maximum value an integer based control can have. */
private int maximum = Integer.MAX_VALUE;
/** The minimum value an integer based control can have. */
private int minimum = Integer.MIN_VALUE;
/** Every argument has a detail mode level at which it becomes available to the user to edit.
* @see org.greenstone.gatherer.Configuration
*/
private int mode_level = Configuration.LIBRARIAN_MODE;
/** The DOM element this argument is built around, if any. */
private Element element;
/** If the argument is of type ENUM or ENUM_STRING then this map holds all the various options. Each entry is an <option value> -> <description> mapping. */
private ArrayList option_list = null;
/** A default value for parameter-type arguments. May be a Perl pattern. */
private String default_value = null;
/** The text description of this argument parsed from the pluginfo output. */
private String description = null;
/** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */
private String name = null;
/** The value of the arg, stored for metadata type options */
private String stored_value = null;
/** The plugin that owns this argument, for the purposes of visualising inheritance. */
private String owner = null;
private String display_name = null;
/** Default Constructor. */
public Argument() {
}
/** Another constructor but this one is a little more interesting as it takes a DOM element.
* @param element the Element this argument is based around
*/
public Argument(Element element) {
this.element = element;
}
/** Method to add an element to the option_list.
* @param name the name value of the option as a String
* @param desc the description of this options as a String
*/
public void addOption(String name, String desc) {
if((type == ENUM || type == ENUM_STRING) && name != null) {
if(desc == null) {
desc = "";
}
if(option_list == null) {
option_list = new ArrayList();
}
option_list.add(new ArgumentOption(name, desc));
}
}
/** Method to compare two arguments for ordering.
* @param object the argument we are comparing to, as an Object
* @return an int specifying the argument order, using values as set out in String
* @see org.greenstone.gatherer.cdm.Argument
*/
public int compareTo(Object object) {
if(object instanceof Argument) {
return getName().compareTo(((Argument)object).getName());
}
else {
return toString().compareTo(object.toString());
}
}
/** Create a copy of this argument.
* @return a newly created Argument with the same details as this one
*/
public Argument copy() {
Argument copy = new Argument();
copy.setDefaultValue(default_value);
copy.setDescription(description);
copy.setOptions(option_list);
copy.setOwner(owner);
copy.setName(name);
copy.setDisplayName(display_name);
copy.setRequired(required);
copy.setType(type);
copy.setMinimum(minimum);
copy.setMaximum(maximum);
copy.setModeLevel(mode_level);
copy.setHiddenGLI(hidden_gli);
return copy;
}
/** Method to determine if two arguments are equal.
* @param object the argument to test against, as an Object
* @return true if the arguments names match, false otherwise
*/
public boolean equals(Object object) {
return (compareTo(object) == 0);
}
/** Method to retrieve the value of default_value.
* @return a String containing the default value
*/
public String getDefaultValue() {
return default_value;
}
/** Method to retrieve this arguments description.
* @return a String containing the description
*/
public String getDescription() {
return description;
}
public Element getElement() {
return element;
}
/** Retrieve the upper bound of a range based argument.
* @return the maximum as an int
*/
public int getMaximum() {
return maximum;
}
/** Retrieve the lower bound of a range based argument.
* @return the minimum as an int
*/
public int getMinimum() {
return minimum;
}
/** Retrieves the mode level at which this argument should become available. Any higher levels should also see this argument.
* @return the mode level as an int
*/
public int getModeLevel() {
return mode_level;
}
/** Method to retrieve the value of name.
* @return a String containing the argument name
* @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
*/
public String getName() {
if(name == null && element != null) {
name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
}
return name;
}
public String getDisplayName() {
if(display_name==null)
return "";
return display_name;
}
/** Method to retrieve the option list for this argument.
* @return a HashMap containing <option value> -> <description> entries
*/
public ArrayList getOptions() {
return option_list;
}
/** Retrieve the name of the owner of this argument.
* @return the owners name as a String
*/
public String getOwner() {
return owner;
}
/** Method to determine the type of this argument.
* @return a byte specifying the type
*/
public byte getType() {
return type;
}
/** Method to retrieve the value of value.
* @return the value of value as a String
* @see org.greenstone.gatherer.Gatherer#c_man
* @see org.greenstone.gatherer.collection.CollectionManager#getCollection
*/
public String getValue()
{
// Only assigned arguments have values.
if (element == null) {
return null;
}
if (stored_value != null) {
return stored_value;
}
String value = XMLTools.getValue(element);
if (type == METADATA) {
// We display using metadata display name, but store in the XML using
// full name (canonical name)
stored_value = MetadataTools.convertMetadataElementListNames(value, MetadataTools.TO_DISPLAY_NAMES);
return stored_value;
}
return value;
}
/** Method to determine if this argument has been assigned.
* @return true if it has, false otherwise
* @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
* @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
*/
public boolean isAssigned() {
return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
}
/** Determine if this is a custom argument ie one that has been parsed from the config file but doesn't have a matching entry in the argument library.
* @return true if this argument is a custom, false otherwise
* @see org.greenstone.gatherer.util.StaticStrings#CUSTOM_ATTRIBUTE
* @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
*/
public boolean isCustomArgument() {
return (element != null && element.getAttribute(StaticStrings.CUSTOM_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
}
/** Determine if this argument is hidden in GLI
* @return true if the argument is hidden, false otherwise
*/
public boolean isHiddenGLI() {
return hidden_gli;
}
/** Method to determine of this argument is required for the associated script to work.
* @return true if this argument is required, false otherwise
*/
public boolean isRequired() {
return required;
}
/** Method to allow for the activation of arguments that might never have their setValue() method called.
* @param assigned the desired state as a boolean
* @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
* @see org.greenstone.gatherer.util.StaticStrings#FALSE_STR
* @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
*/
public void setAssigned(boolean assigned) {
if(element != null) {
element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
}
}
/** Sets the value of default_value.
* @param default_value The new value for default_value as a String.
*/
public void setDefaultValue(String default_value) {
this.default_value = default_value;
}
/** Set the value of desc.
* @param description the new value of desc as a String
*/
public void setDescription(String description) {
this.description = description;
}
/** Set the element this argument should be based upon.
* @param element the Element
*/
public void setElement(Element element) {
this.element = element;
}
/** Mark this argument as being hidden in GLI. */
public void setHiddenGLI(boolean hidden) {
this.hidden_gli = hidden;
}
/** Set the upper bound for a range type argument.
* @param maximum the maximum as an int
*/
public void setMaximum(int maximum) {
this.maximum = maximum;
}
/** Set the lower bound for a range type argument.
* @param minimum the minimum as an int
*/
public void setMinimum(int minimum) {
this.minimum = minimum;
}
/** Set the detail mode level where this argument will become available.
* @param mode_level the mode level as an int
*/
public void setModeLevel(int mode_level) {
this.mode_level = mode_level;
}
/** Set the value of name.
* @param name the new value of name as a String
*/
public void setName(String name) {
this.name = name;
}
public void setDisplayName(String name) {
this.display_name = name;
}
/** Sets the value of the options list.
* @param list the new options list as a HashMap
*/
public void setOptions(ArrayList list) {
this.option_list = list;
}
/** Set the owner of this argument.
* @param owner the name of the owner of this argument as a String
*/
public void setOwner(String owner) {
this.owner = owner;
}
/** Set the value of required.
* @param required the new value of required as a boolean
*/
public void setRequired(boolean required) {
this.required = required;
}
/** Set the value of type.
* @param type the new value of type as an byte
*/
public void setType(byte type) {
this.type = type;
}
/** Set the value of type, by matching a type to the given string.
* @param new_type a String which contains the name of a certain argument type
* @see org.greenstone.gatherer.util.StaticStrings#ENUM_STR
* @see org.greenstone.gatherer.util.StaticStrings#FLAG_STR
* @see org.greenstone.gatherer.util.StaticStrings#HIERARCHY_STR
* @see org.greenstone.gatherer.util.StaticStrings#INT_STR
* @see org.greenstone.gatherer.util.StaticStrings#LANGUAGE_STR
* @see org.greenstone.gatherer.util.StaticStrings#METADATA_TYPE_STR
* @see org.greenstone.gatherer.util.StaticStrings#REGEXP_STR
*/
public void setType(String new_type) {
if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STR)) {
this.type = ENUM;
option_list = new ArrayList();
}
else if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STRING_STR)) {
this.type = ENUM_STRING;
option_list = new ArrayList();
}
else if(new_type.equalsIgnoreCase(StaticStrings.FLAG_STR)) {
this.type = FLAG;
}
else if(new_type.equalsIgnoreCase(StaticStrings.HIERARCHY_STR)) {
this.type = HIERARCHY;
}
else if(new_type.equalsIgnoreCase(StaticStrings.INT_STR)) {
this.type = INTEGER;
}
else if(new_type.equalsIgnoreCase(StaticStrings.LANGUAGE_STR)) {
this.type = LANGUAGE;
}
else if(new_type.equalsIgnoreCase(StaticStrings.METADATA_TYPE_STR)) {
this.type = METADATA;
}
else if(new_type.equalsIgnoreCase(StaticStrings.REGEXP_STR)) {
this.type = REGEXP;
}
else {
this.type = STRING;
}
}
/** Method to set the value of this argument.
* @param value the new value for the argument
* @see org.greenstone.gatherer.Gatherer#println
*/
public void setValue(String value) {
if(element != null) {
if (type == METADATA) {
value = MetadataTools.convertMetadataElementListNames(value, MetadataTools.FROM_DISPLAY_NAMES);
stored_value = value;
}
XMLTools.setValue(element, value);
}
else {
DebugStream.println("Argument.setValue(" + value + ") called on a base Argument.");
}
}
/** Set the values vector to the given values. Currently I just assign the new values, whereas I may later want to implement a deep clone.
* @param values an ArrayList of values
* @see org.greenstone.gatherer.Gatherer#println
*/
public void setValues(ArrayList values) {
if(element != null) {
StringBuffer value = new StringBuffer();
int value_length = values.size();
for(int i = 0; i < value_length; i++) {
value.append(values.get(i));
value.append(StaticStrings.COMMA_CHARACTER);
}
value.deleteCharAt(value.length() - 1); // Remove last ','
XMLTools.setValue(element, value.toString());
}
else {
DebugStream.println("Argument.setValues([" + values.size() + " items]) called on a base Argument.");
}
}
/** Method for translating the data of this class into a string.
* @return a String containing a fragment of the total arguments string
* @see org.greenstone.gatherer.Gatherer#c_man
* @see org.greenstone.gatherer.collection.CollectionManager#getCollection
* @see org.greenstone.gatherer.util.StaticStrings#COMMA_CHARACTER
* @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
* @see org.greenstone.gatherer.util.StaticStrings#SPACE_CHARACTER
* @see org.greenstone.gatherer.util.StaticStrings#SPEECH_CHARACTER
*/
public String toString()
{
StringBuffer text = new StringBuffer("-");
if (element == null) {
return text.toString();
}
if (name == null) {
name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
}
text.append(name);
// getValue returns display name for metadata args
String value = getValue();
if (value.length() == 0) {
return text.toString();
}
text.append(StaticStrings.SPACE_CHARACTER);
// If the value contains a space, add speech marks
// (Except for metadata elements, which won't have spaces when written out to collect.cfg)
if (value.indexOf(StaticStrings.SPACE_CHARACTER) != -1 && type != METADATA) {
value = StaticStrings.SPEECH_CHARACTER + value + StaticStrings.SPEECH_CHARACTER;
}
text.append(value);
return text.toString();
}
/** parse the