source: gli/trunk/src/org/greenstone/gatherer/cdm/Argument.java@ 20439

Last change on this file since 20439 was 20439, checked in by kjdon, 15 years ago

Argument now controls the conversion between metadata display name and proper name for arguments. The underlying XML holds the proper name eg dc.Subject, while the toString and getValue methods show the display name eg dc.Subject and Keywords

  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Greenstone Librarian Interface (GLI) application,
5 * part of the Greenstone digital library software suite from the New
6 * Zealand Digital Library Project at the University of Waikato,
7 * New Zealand.
8 *
9 * Author: John Thompson
10 * Greenstone Project, New Zealand Digital Library
11 * University of Waikato
12 * http://www.nzdl.org
13 *
14 * Copyright (C) 2004 New Zealand Digital Library, University of Waikato
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *########################################################################
30 */
31
32package org.greenstone.gatherer.cdm;
33
34import java.io.*;
35import java.util.*;
36import org.greenstone.gatherer.Configuration;
37import org.greenstone.gatherer.DebugStream;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.collection.Collection;
40import org.greenstone.gatherer.collection.CollectionManager;
41import org.greenstone.gatherer.metadata.MetadataElement;
42import org.greenstone.gatherer.metadata.MetadataTools;
43import org.greenstone.gatherer.util.StaticStrings;
44import org.greenstone.gatherer.util.Utility;
45import org.greenstone.gatherer.util.XMLTools;
46import org.w3c.dom.*;
47
48/** 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.
49 * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
50 * @version 2.41 final
51 */
52public class Argument
53 implements Comparable, Serializable {
54 /** An element of the argument type enumeration specifying a combobox control. */
55 static final public byte ENUM = 0;
56 /** An element of the argument type enumeration specifying a checkbox control. */
57 static final public byte FLAG = 1;
58 /** An element of the argument type enumeration specifying a tree control. */
59 static final public byte HIERARCHY = 2;
60 /** An element of the argument type enumeration specifying a spinner control. */
61 static final public byte INTEGER = 3;
62 /** An element of the argument type enumeration specifying a language combobox control. */
63 static final public byte LANGUAGE = 4;
64 /** An element of the argument type enumeration specifying a list control. */
65 static final public byte METADATA = 5;
66 /** An element of the argument type enumeration specifying a metadata combobox control. */
67 static final public byte METADATUM = 6;
68 /** An element of the argument type enumeration specifying a text field. */
69 static final public byte STRING = 7;
70 /** An element of the argument type enumeration specifying a regular expression text field. */
71 static final public byte REGEXP = 8;
72 /** An element of the argument type enumeration specifying a metadata set combobox control. */
73 static final public byte METADATA_SET_NAMESPACE = 9;
74 /** An element of the argument type enumeration specifying a text field. */
75 static final public byte URL = 10;
76 /** An editable combo box */
77 static final public byte ENUM_STRING = 11;
78
79 /////////////////////////////////////////////////////////////////
80
81 /** 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. */
82 private boolean hidden_gli = false;
83 /** <i>true</i> if this argument is required for the applicable script to work properly, <i>false</i> otherwise. */
84 private boolean required = false;
85 /** The type of this argument. Used to be an int, but bytes are cheaper. */
86 private byte type = STRING;
87 /** The maximum value an integer based control can have. */
88 private int maximum = Integer.MAX_VALUE;
89 /** The minimum value an integer based control can have. */
90 private int minimum = Integer.MIN_VALUE;
91 /** Every argument has a detail mode level at which it becomes available to the user to edit.
92 * @see org.greenstone.gatherer.Configuration
93 */
94 private int mode_level = Configuration.LIBRARIAN_MODE;
95 /** The DOM element this argument is built around, if any. */
96 private Element element;
97 /** If the argument is of type ENUM or ENUM_STRING then this map holds all the various options. Each entry is an &lt;option value&gt; -&gt; &lt;description&gt; mapping. */
98 private ArrayList option_list = null;
99 /** A default value for parameter-type arguments. May be a Perl pattern. */
100 private String default_value = null;
101 /** The text description of this argument parsed from the pluginfo output. */
102 private String description = null;
103 /** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */
104 private String name = null;
105 /** The value of the arg, stored for metadata type options */
106 private String stored_value = null;
107 /** The plugin that owns this argument, for the purposes of visualising inheritance. */
108 private String owner = null;
109
110 private String display_name = null;
111
112 /** Default Constructor. */
113 public Argument() {
114 }
115
116 /** Another constructor but this one is a little more interesting as it takes a DOM element.
117 * @param element the Element this argument is based around
118 */
119 public Argument(Element element) {
120 this.element = element;
121 }
122
123 /** Method to add an element to the option_list.
124 * @param name the name value of the option as a String
125 * @param desc the description of this options as a String
126 */
127 public void addOption(String name, String desc) {
128 if((type == ENUM || type == ENUM_STRING) && name != null) {
129 if(desc == null) {
130 desc = "";
131 }
132 if(option_list == null) {
133 option_list = new ArrayList();
134 }
135 option_list.add(new ArgumentOption(name, desc));
136 }
137 }
138
139 /** Method to compare two arguments for ordering.
140 * @param object the argument we are comparing to, as an Object
141 * @return an int specifying the argument order, using values as set out in String
142 * @see org.greenstone.gatherer.cdm.Argument
143 */
144 public int compareTo(Object object) {
145 if(object instanceof Argument) {
146 return getName().compareTo(((Argument)object).getName());
147 }
148 else {
149 return toString().compareTo(object.toString());
150 }
151 }
152
153 /** Create a copy of this argument.
154 * @return a newly created Argument with the same details as this one
155 */
156 public Argument copy() {
157 Argument copy = new Argument();
158 copy.setDefaultValue(default_value);
159 copy.setDescription(description);
160 copy.setOptions(option_list);
161 copy.setOwner(owner);
162 copy.setName(name);
163 copy.setDisplayName(display_name);
164 copy.setRequired(required);
165 copy.setType(type);
166 copy.setMinimum(minimum);
167 copy.setMaximum(maximum);
168 copy.setModeLevel(mode_level);
169 copy.setHiddenGLI(hidden_gli);
170 return copy;
171 }
172
173 /** Method to determine if two arguments are equal.
174 * @param object the argument to test against, as an Object
175 * @return true if the arguments names match, false otherwise
176 */
177 public boolean equals(Object object) {
178 return (compareTo(object) == 0);
179 }
180
181 /** Method to retrieve the value of default_value.
182 * @return a String containing the default value
183 */
184 public String getDefaultValue() {
185 return default_value;
186 }
187
188 /** Method to retrieve this arguments description.
189 * @return a String containing the description
190 */
191 public String getDescription() {
192 return description;
193 }
194
195 public Element getElement() {
196 return element;
197 }
198 /** Retrieve the upper bound of a range based argument.
199 * @return the maximum as an int
200 */
201 public int getMaximum() {
202 return maximum;
203 }
204
205 /** Retrieve the lower bound of a range based argument.
206 * @return the minimum as an int
207 */
208 public int getMinimum() {
209 return minimum;
210 }
211
212 /** Retrieves the mode level at which this argument should become available. Any higher levels should also see this argument.
213 * @return the mode level as an int
214 */
215 public int getModeLevel() {
216 return mode_level;
217 }
218
219 /** Method to retrieve the value of name.
220 * @return a String containing the argument name
221 * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
222 */
223 public String getName() {
224 if(name == null && element != null) {
225 name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
226 }
227 return name;
228 }
229
230 public String getDisplayName() {
231 if(display_name==null)
232 return "";
233 return display_name;
234 }
235
236 /** Method to retrieve the option list for this argument.
237 * @return a HashMap containing &lt;option value&gt; -&gt; &lt;description&gt; entries
238 */
239 public ArrayList getOptions() {
240 return option_list;
241 }
242
243 /** Retrieve the name of the owner of this argument.
244 * @return the owners name as a String
245 */
246 public String getOwner() {
247 return owner;
248 }
249
250 /** Method to determine the type of this argument.
251 * @return a byte specifying the type
252 */
253 public byte getType() {
254 return type;
255 }
256
257 /** Method to retrieve the value of value.
258 * @return the value of value as a String
259 * @see org.greenstone.gatherer.Gatherer#c_man
260 * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
261 */
262 public String getValue()
263 {
264 // Only assigned arguments have values.
265 if (element == null) {
266 return null;
267 }
268 if (stored_value != null) {
269 return stored_value;
270 }
271 String value = XMLTools.getValue(element);
272 if (type == METADATA) {
273 // We display using metadata display name, but store in the XML using
274 // full name (canonical name)
275 stored_value = MetadataTools.convertMetadataElementListNames(value, MetadataTools.TO_DISPLAY_NAMES);
276 return stored_value;
277 }
278 return value;
279 }
280
281
282 /** Method to determine if this argument has been assigned.
283 * @return true if it has, false otherwise
284 * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
285 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
286 */
287 public boolean isAssigned() {
288 return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
289 }
290
291 /** 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.
292 * @return true if this argument is a custom, false otherwise
293 * @see org.greenstone.gatherer.util.StaticStrings#CUSTOM_ATTRIBUTE
294 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
295 */
296 public boolean isCustomArgument() {
297 return (element != null && element.getAttribute(StaticStrings.CUSTOM_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
298 }
299
300 /** Determine if this argument is hidden in GLI
301 * @return true if the argument is hidden, false otherwise
302 */
303 public boolean isHiddenGLI() {
304 return hidden_gli;
305 }
306
307 /** Method to determine of this argument is required for the associated script to work.
308 * @return true if this argument is required, false otherwise
309 */
310 public boolean isRequired() {
311 return required;
312 }
313
314 /** Method to allow for the activation of arguments that might never have their setValue() method called.
315 * @param assigned the desired state as a boolean
316 * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
317 * @see org.greenstone.gatherer.util.StaticStrings#FALSE_STR
318 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
319 */
320 public void setAssigned(boolean assigned) {
321 if(element != null) {
322 element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
323 }
324 }
325
326 /** Sets the value of default_value.
327 * @param default_value The new value for default_value as a <strong>String</strong>.
328 */
329 public void setDefaultValue(String default_value) {
330 this.default_value = default_value;
331 }
332
333 /** Set the value of desc.
334 * @param description the new value of desc as a String
335 */
336 public void setDescription(String description) {
337 this.description = description;
338 }
339
340 /** Set the element this argument should be based upon.
341 * @param element the Element
342 */
343 public void setElement(Element element) {
344 this.element = element;
345 }
346
347 /** Mark this argument as being hidden in GLI. */
348 public void setHiddenGLI(boolean hidden) {
349 this.hidden_gli = hidden;
350 }
351
352 /** Set the upper bound for a range type argument.
353 * @param maximum the maximum as an int
354 */
355 public void setMaximum(int maximum) {
356 this.maximum = maximum;
357 }
358
359 /** Set the lower bound for a range type argument.
360 * @param minimum the minimum as an int
361 */
362 public void setMinimum(int minimum) {
363 this.minimum = minimum;
364 }
365
366 /** Set the detail mode level where this argument will become available.
367 * @param mode_level the mode level as an int
368 */
369 public void setModeLevel(int mode_level) {
370 this.mode_level = mode_level;
371 }
372
373 /** Set the value of name.
374 * @param name the new value of name as a String
375 */
376 public void setName(String name) {
377 this.name = name;
378 }
379
380 public void setDisplayName(String name) {
381 this.display_name = name;
382 }
383
384 /** Sets the value of the options list.
385 * @param list the new options list as a HashMap
386 */
387 public void setOptions(ArrayList list) {
388 this.option_list = list;
389 }
390
391 /** Set the owner of this argument.
392 * @param owner the name of the owner of this argument as a String
393 */
394 public void setOwner(String owner) {
395 this.owner = owner;
396 }
397
398 /** Set the value of required.
399 * @param required the new value of required as a boolean
400 */
401 public void setRequired(boolean required) {
402 this.required = required;
403 }
404
405 /** Set the value of type.
406 * @param type the new value of type as an byte
407 */
408 public void setType(byte type) {
409 this.type = type;
410 }
411
412 /** Set the value of type, by matching a type to the given string.
413 * @param new_type a String which contains the name of a certain argument type
414 * @see org.greenstone.gatherer.util.StaticStrings#ENUM_STR
415 * @see org.greenstone.gatherer.util.StaticStrings#FLAG_STR
416 * @see org.greenstone.gatherer.util.StaticStrings#HIERARCHY_STR
417 * @see org.greenstone.gatherer.util.StaticStrings#INT_STR
418 * @see org.greenstone.gatherer.util.StaticStrings#LANGUAGE_STR
419 * @see org.greenstone.gatherer.util.StaticStrings#METADATA_TYPE_STR
420 * @see org.greenstone.gatherer.util.StaticStrings#METADATUM_TYPE_STR
421 * @see org.greenstone.gatherer.util.StaticStrings#REGEXP_STR
422 */
423 public void setType(String new_type) {
424 if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STR)) {
425 this.type = ENUM;
426 option_list = new ArrayList();
427 }
428 else if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STRING_STR)) {
429 this.type = ENUM_STRING;
430 option_list = new ArrayList();
431 }
432 else if(new_type.equalsIgnoreCase(StaticStrings.FLAG_STR)) {
433 this.type = FLAG;
434 }
435 else if(new_type.equalsIgnoreCase(StaticStrings.HIERARCHY_STR)) {
436 this.type = HIERARCHY;
437 }
438 else if(new_type.equalsIgnoreCase(StaticStrings.INT_STR)) {
439 this.type = INTEGER;
440 }
441 else if(new_type.equalsIgnoreCase(StaticStrings.LANGUAGE_STR)) {
442 this.type = LANGUAGE;
443 }
444 else if(new_type.equalsIgnoreCase(StaticStrings.METADATA_TYPE_STR)) {
445 this.type = METADATA;
446 }
447 else if(new_type.equalsIgnoreCase(StaticStrings.METADATUM_TYPE_STR)) {
448 this.type = METADATUM;
449 }
450 else if(new_type.equalsIgnoreCase(StaticStrings.REGEXP_STR)) {
451 this.type = REGEXP;
452 }
453 else {
454 this.type = STRING;
455 }
456 }
457
458 /** Method to set the value of this argument.
459 * @param value the new value for the argument
460 * @see org.greenstone.gatherer.Gatherer#println
461 */
462 public void setValue(String value) {
463 if(element != null) {
464 if (type == METADATA) {
465 value = MetadataTools.convertMetadataElementListNames(value, MetadataTools.FROM_DISPLAY_NAMES);
466 stored_value = value;
467 }
468 XMLTools.setValue(element, value);
469 }
470 else {
471 DebugStream.println("Argument.setValue(" + value + ") called on a base Argument.");
472 }
473 }
474
475 /** 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.
476 * @param values an ArrayList of values
477 * @see org.greenstone.gatherer.Gatherer#println
478 */
479 public void setValues(ArrayList values) {
480 if(element != null) {
481 StringBuffer value = new StringBuffer();
482 int value_length = values.size();
483 for(int i = 0; i < value_length; i++) {
484 value.append(values.get(i));
485 value.append(StaticStrings.COMMA_CHARACTER);
486 }
487 value.deleteCharAt(value.length() - 1); // Remove last ','
488 XMLTools.setValue(element, value.toString());
489 }
490 else {
491 DebugStream.println("Argument.setValues([" + values.size() + " items]) called on a base Argument.");
492 }
493 }
494
495 /** Method for translating the data of this class into a string.
496 * @return a String containing a fragment of the total arguments string
497 * @see org.greenstone.gatherer.Gatherer#c_man
498 * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
499 * @see org.greenstone.gatherer.util.StaticStrings#COMMA_CHARACTER
500 * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
501 * @see org.greenstone.gatherer.util.StaticStrings#SPACE_CHARACTER
502 * @see org.greenstone.gatherer.util.StaticStrings#SPEECH_CHARACTER
503 */
504 public String toString()
505 {
506 StringBuffer text = new StringBuffer("-");
507
508 if (element == null) {
509 return text.toString();
510 }
511
512 if (name == null) {
513 name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
514 }
515 text.append(name);
516
517 String value = getValue(); //XMLTools.getValue(element);
518 if (value.length() == 0) {
519 return text.toString();
520 }
521
522 text.append(StaticStrings.SPACE_CHARACTER);
523
524 // // Handle metadata elements specially
525 // if (type == METADATA || type == METADATUM) {
526 // // Tokenize the string
527 // StringTokenizer tokenizer = new StringTokenizer(value, ",");
528 // while (tokenizer.hasMoreTokens()) {
529 // String token = tokenizer.nextToken();
530
531 // MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
532 // if (metadata_element != null) {
533 // text.append(metadata_element.getFullName());
534 // }
535 // else {
536 // text.append(token);
537 // }
538
539 // if (tokenizer.hasMoreTokens()) {
540 // text.append(StaticStrings.COMMA_CHARACTER);
541 // }
542 // }
543 // return text.toString();
544 // }
545
546 // If the value contains a space, add speech marks
547 // (Except for metadata elements, which won't have spaces when written out to collect.cfg)
548 if (value.indexOf(StaticStrings.SPACE_CHARACTER) != -1 && !(type == METADATUM || type == METADATA)) {
549 value = StaticStrings.SPEECH_CHARACTER + value + StaticStrings.SPEECH_CHARACTER;
550 }
551
552 text.append(value);
553 return text.toString();
554 }
555
556 /** parse the <Option> XML from eg import.pl -xml or pluginfo.pl -xml */
557 public void parseXML(Element option) {
558
559 for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) {
560 String node_name = node.getNodeName();
561 if(node_name.equals("Name")) {
562 setName(XMLTools.getValue(node));
563 }
564 else if(node_name.equals("DisplayName")) {
565 setDisplayName(XMLTools.getValue(node));
566 }
567 else if(node_name.equals("Desc")) {
568 setDescription(XMLTools.getValue(node));
569 }
570 else if(node_name.equals("Type")) {
571 setType(XMLTools.getValue(node));
572 }
573 else if(node_name.equals("Default")) {
574 setDefaultValue(XMLTools.getValue(node));
575 }
576 else if(node_name.equals("Required")) {
577 String v = XMLTools.getValue(node);
578 if(v != null && v.equals("yes")) {
579 setRequired(true);
580 }
581 }
582 else if(node_name.equals("List")) {
583 // Two final loops are required to parse lists.
584 for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) {
585 if(value.getNodeName().equals("Value")) {
586 String key = null;
587 String desc = "";
588 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
589 node_name = subvalue.getNodeName();
590 if(node_name.equals("Name")) {
591 key = XMLTools.getValue(subvalue);
592 }
593 else if(node_name.equals("Desc")) {
594 desc = XMLTools.getValue(subvalue);
595 }
596 }
597 if(key != null) {
598 addOption(key, desc);
599 }
600 }
601 }
602 }
603 else if(node_name.equals("Range")) {
604 String range_raw = XMLTools.getValue(node);
605 int index = -1;
606 if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) {
607 if(index > 0) {
608 try {
609 String first_number = range_raw.substring(0, index);
610 setMinimum(Integer.parseInt(first_number));
611 first_number = null;
612 }
613 catch(Exception exception) {
614 }
615 }
616
617 if(index + 1 < range_raw.length()) {
618 try {
619 String second_number = range_raw.substring(index + 1);
620 setMaximum(Integer.parseInt(second_number));
621 second_number = null;
622 }
623 catch(Exception exception) {
624 }
625 }
626 }
627 // Else it wasn't a valid range anyway, so ignore it
628 }
629 else if(node_name.equals("HiddenGLI")) {
630 setHiddenGLI(true);
631 }
632 else if(node_name.equals("ModeGLI")) {
633 String mode_level_str = XMLTools.getValue(node);
634 try {
635 int mode_level = Integer.parseInt(mode_level_str);
636 setModeLevel(mode_level);
637 }
638 catch(Exception exception) {
639 DebugStream.println("Exception in Argument.parseXML() - Unexpected but non-fatal");
640 DebugStream.printStackTrace(exception);
641 }
642 }
643
644 } // for each option
645
646 } // parseXML
647
648 public class ArgumentOption
649 implements Comparable {
650 public String name;
651 public String description;
652 private String text; // cached version
653
654 public ArgumentOption(String name, String desc) {
655 this.name = name;
656 this.description = desc;
657 }
658
659 public int compareTo(Object obj) {
660 return toString().compareTo(obj.toString());
661 }
662
663 public boolean equals(Object obj) {
664 return (obj != null && compareTo(obj) == 0);
665 }
666
667 public String toString() {
668 return name + " "+ StaticStrings.MINUS_CHARACTER + " "+ description;
669 }
670
671 public String getToolTip() {
672 return Utility.formatHTMLWidth(name+": "+description, 80);
673 }
674 }
675}
Note: See TracBrowser for help on using the repository browser.