source: trunk/gli/src/org/greenstone/gatherer/cdm/Classifier.java@ 5590

Last change on this file since 5590 was 5590, checked in by mdewsnip, 21 years ago

Could it be I've finished adding tooltips?? Why yes, very nearly... and a big "hallelulah" for that.

  • Property svn:keywords set to Author Date Id Revision
File size: 16.9 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29/**************************************************************************************
30 * Written: 01/05/02
31 * Revised: 16/08/02 Optimized and Commented.
32 * 11/07/03 DOM support
33 **************************************************************************************/
34import java.io.*;
35import java.util.*;
36import org.greenstone.gatherer.Gatherer;
37import org.greenstone.gatherer.cdm.Argument;
38import org.greenstone.gatherer.cdm.ArgumentContainer;
39import org.greenstone.gatherer.cdm.CollectionConfiguration;
40import org.greenstone.gatherer.cdm.CollectionDesignManager;
41import org.greenstone.gatherer.cdm.DOMProxyListEntry;
42import org.greenstone.gatherer.util.StaticStrings;
43import org.greenstone.gatherer.util.Utility;
44import org.w3c.dom.*;
45
46/** 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.
47 * @author John Thompson, Greenstone Digital Library, University of Waikato
48 * @version 2.3
49 */
50public class Classifier
51 extends ArrayList
52 implements ArgumentContainer, Comparable, DOMProxyListEntry, Serializable {
53
54 static final public String CLASSIFIER_PREFIX = "CL";
55
56 private boolean is_abstract = false;
57
58 /** A reference to the classifier that this one inherits from. */
59 private Classifier super_classifier = null;
60 /** The element this classifier is based upon. */
61 private Element element;
62 /** A description of this classifier. */
63 private String description = null;
64 /** The name of the classifier as it would appear in the collect.cfg file. */
65 private String name = null;
66 /** 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.) */
67 private String old_position_string = null;
68
69 /** Constructor used only in DOMProxyListModel initializations.
70 */
71 public Classifier() {
72 }
73
74 public Classifier(Element element, Classifier base_classifier) {
75 super();
76 this.element = element;
77 this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
78 ///atherer.println("Establishing Classifier: " + name);
79 // Parse in any argument options for this classifier, keeping a list of the ones found
80 HashMap known_arguments = new HashMap();
81 NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
82 int option_elements_length = option_elements.getLength();
83 for(int i = 0; i < option_elements_length; i++) {
84 Element option_element = (Element) option_elements.item(i);
85 Argument argument = new Argument(option_element);
86 ///atherer.println("Rebuilding existing argument: " + argument.getName());
87 argument.setOwner(name);
88 add(argument);
89 known_arguments.put(argument.getName(), argument);
90 }
91 // If a base classifier was given
92 if(base_classifier != null) {
93 // Copy the details, and add a reference to whatever base_classifiers super classifier is.
94 description = base_classifier.getDescription();
95 // 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.
96 ArrayList all_arguments = base_classifier.getArguments(true, true);
97 int argument_count = all_arguments.size();
98 for(int j = 0; j < argument_count; j++) {
99 Argument base_argument = (Argument) all_arguments.get(j);
100 String base_argument_name = base_argument.getName();
101 ///atherer.println("Library indicates this classifier should have an argument: " + base_argument_name);
102 Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
103 // Found an existing argument. Complete its details
104 if(existing_argument != null) {
105 ///atherer.println("Found existing argument. Filling out details.");
106 existing_argument.setCustomArgument(false);
107 existing_argument.setDefaultValue(base_argument.getDefaultValue());
108 existing_argument.setDescription(base_argument.getDescription());
109 existing_argument.setOptions(base_argument.getOptions());
110 existing_argument.setRequired(base_argument.isRequired());
111 existing_argument.setType(base_argument.getType());
112 }
113 // 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.
114 else {
115 ///atherer.println("No such argument. Adding new, unassigned, argument.");
116 // The trick thing is that we have to create a new element in the DOM as well.
117 Argument new_argument = base_argument.copy();
118 new_argument.setOwner(name);
119 Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
120 argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
121 argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
122 argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.FALSE_STR);
123 new_argument.setElement(argument_element);
124 // All done. Add it.
125 element.appendChild(argument_element);
126 add(new_argument);
127 }
128 }
129 }
130 old_position_string = getPositionString();
131 }
132
133 /** Constructor.
134 * @param name The name of this classifier as a <strong>String</strong>.
135 * @param desc A description of this classifier as a <strong>String</strong>.
136 * @param super_classifier The super class of this classifier, as a <strong>Classifier</strong>.
137 */
138 public Classifier(String name, String description, Classifier super_classifier) {
139 super();
140 this.description = description;
141 this.name = name;
142 this.super_classifier = super_classifier;
143 }
144
145 /** Method to add an argument to this classifier. Only adds the argument if it isn't already present.
146 * @param argument The <strong>Argument</strong> to add.
147 */
148 public void addArgument(Argument argument) {
149 if(element == null && !contains(argument)) {
150 add(argument);
151 argument.setOwner(name);
152 }
153 }
154
155 /** Method to compare two classifiers for ordering.
156 * @param object The classifier we are comparing to, as an <strong>Object</strong>.
157 * @return An <i>int</i> specifying the classifier order, using values as set out in String.
158 * @see java.lang.String#compareTo
159 */
160 public int compareTo(Object object) {
161 if(object == null) {
162 return -1;
163 }
164 return toString().compareTo(object.toString());
165 }
166
167 /** The assigned classifier constructor.
168 * @param element the DOM Element this classifier is based upon
169 * @param base_classifier the Classifier from the stored library showing details about this classifier, may be null
170 */
171 public DOMProxyListEntry create(Element element) {
172 String classifier_name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
173 // Determine the base classifier from the classifier name
174 Classifier base_classifier = CollectionDesignManager.classifier_manager.getBaseClassifier(classifier_name);
175 Classifier classifier = new Classifier(element, base_classifier);
176 base_classifier = null;
177 classifier_name = null;
178 return classifier;
179 }
180
181 /** Method to determine if two classifiers are equal.
182 * @param object The classifier to test against, as an <strong>Object</strong>.
183 * @return <i>true</i> if the classifier names match, <i>false</i> otherwise.
184 */
185 public boolean equals(Object object) {
186 return (compareTo(object) == 0);
187 }
188
189 /** Method to retrieve an argument by its name.
190 * @param name The name of the argument as a <strong>String</strong>.
191 * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
192 */
193 public Argument getArgument(String name) {
194 // The name given may still include the '-'
195 if(name.startsWith("-")) {
196 name = name.substring(1);
197 }
198 ArrayList arguments = getArguments(true, true);
199 for(int i = 0; i < arguments.size(); i++) {
200 Argument argument = (Argument)arguments.get(i);
201 if(argument.getName().equals(name)) {
202 return argument;
203 }
204 }
205 return null;
206 }
207
208 /** 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.
209 * @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
210 */
211 public ArrayList getArguments(boolean include_normal, boolean include_custom) {
212 ArrayList arguments = new ArrayList();
213 if(include_normal && include_custom) {
214 arguments.addAll(this);
215 }
216 else {
217 int size = size();
218 for(int i = 0; i < size; i++) {
219 Argument argument = (Argument) get(i);
220 if(argument.isCustomArgument()) {
221 if(include_custom && !arguments.contains(argument)) {
222 arguments.add(argument);
223 }
224 }
225 else {
226 if(include_normal && !arguments.contains(argument)) {
227 arguments.add(argument);
228 }
229 }
230 argument = null;
231 }
232 }
233 if(super_classifier != null) {
234 ArrayList remainder = super_classifier.getArguments(include_normal, include_custom);
235 remainder.removeAll(arguments);
236 arguments.addAll(remainder);
237 }
238 return arguments;
239 }
240
241 /** 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.
242 * @return the custom arguments as a String
243 */
244 public String getCustom() {
245 StringBuffer custom_text = new StringBuffer();
246 // Retrieve all of the arguments, and append any that are custom into one long string
247 ArrayList arguments = getArguments(false, true);
248 int arguments_size = arguments.size();
249 boolean first = true;
250 for(int i = 0; i < arguments_size; i++) {
251 Argument argument = (Argument) arguments.get(i);
252 if(argument.isAssigned()) {
253 if(!first) {
254 custom_text.append(" ");
255 }
256 custom_text.append(argument.toString());
257 first = false;
258 }
259 }
260 return custom_text.toString();
261 }
262
263 public String getDescription() {
264 return description;
265 }
266
267 public Element getElement() {
268 return element;
269 }
270
271 /** Method to retrieve a classifiers name.
272 * @return A <strong>String</strong> containing the classifiers name.
273 */
274 public String getName() {
275 if(name == null && element != null) {
276 name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
277 }
278 return name;
279 }
280
281 public String getOldPositionString() {
282 return old_position_string;
283 }
284
285 /** Generate the string showing this classifiers position. */
286 public String getPositionString() {
287 String position_string = CLASSIFIER_PREFIX;
288 if(element != null) {
289 // Determine our place in the collect.cfg file
290 int position_int = CollectionDesignManager.classifier_manager.indexOf(this) + 1;
291 if(position_int != -1) {
292 position_string = position_string + position_int;
293 }
294 }
295 return position_string;
296 }
297
298 public boolean isAbstract() {
299 return is_abstract;
300 }
301
302 public boolean isAssigned() {
303 return (element != null && !element.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.FALSE_STR));
304 }
305
306 public void setAssigned(boolean assigned) {
307 if(element != null) {
308 element.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (assigned ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR));
309 }
310 }
311
312 /** 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!).
313 * @param custom_str the custom arguments all splodged together in one String
314 */
315 public void setCustom(String custom_str) {
316 HashMap raw_arguments = CollectionConfiguration.parseArguments(new CommandTokenizer(custom_str));
317 ArrayList custom_arguments = getArguments(false, true);
318 int size = custom_arguments.size();
319 for(int i = 0; i < size; i++) {
320 Argument argument = (Argument) custom_arguments.get(i);
321 String original_argument_name = StaticStrings.MINUS_CHARACTER + argument.getName();
322 if(raw_arguments.containsKey(original_argument_name)) {
323 // Set as assigned
324 argument.setAssigned(true);
325 String argument_value = (String)raw_arguments.remove(original_argument_name);
326 if(argument_value != null) {
327 argument.setValue(argument_value);
328 argument_value = null;
329 }
330 }
331 // We've removed it from our custom statement, so unassign
332 else {
333 argument.setAssigned(false);
334 }
335 argument = null;
336 }
337 // Any left over, add to the classifier
338 Iterator argument_names = raw_arguments.keySet().iterator();
339 while(argument_names.hasNext()) {
340 String argument_name = (String) argument_names.next();
341 String argument_value = (String) raw_arguments.get(argument_name);
342 // The tricky thing is that we have to create a new element in the DOM as well.
343 Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
344 argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, argument_name.substring(1));
345 argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
346 argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.TRUE_STR);
347 Argument argument = new Argument(argument_element);
348 argument_name = null;
349 if(argument_value != null) {
350 argument.setValue(argument_value);
351 argument_value = null;
352 }
353 // All done. Add it.
354 element.appendChild(argument_element);
355 add(argument);
356 argument_element = null;
357 }
358 raw_arguments = null;
359 }
360
361 /** Method to set the value of desc.
362 * @param desc The new value of desc as a <strong>String</strong>.
363 */
364 public void setDescription(String desc) {
365 this.description = description;
366 }
367
368 public void setElement(Element element) {
369 this.element = element;
370 }
371
372 public void setIsAbstract(boolean is_abstract) {
373 this.is_abstract = is_abstract;
374 }
375
376 /** Method to set the value of name.
377 * @param name The new value of name as a <strong>String</strong>.
378 */
379 public void setName(String name) {
380 this.name = name;
381 }
382
383 /** Method to set the value of the super_classifier.
384 * @param super_classifier The new value of super_classifier as a <strong>Classifier</strong>, or <i>null</i> if this class has no inheritance.
385 */
386 public void setSuper(Classifier super_classifier) {
387 this.super_classifier = super_classifier;
388 }
389
390 /** Method to print out this classifier as it would appear to the user in the interface
391 * @return A <strong>String</strong> containing a single classifier command.
392 */
393 public String toString() {
394 if(element != null) {
395 if(name == null) {
396 name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
397 }
398 StringBuffer text = new StringBuffer(StaticStrings.CLASSIFY_STR);
399 text.append(" ");
400 text.append(name);
401 text.append(" ");
402 ArrayList arguments = getArguments(true, true);
403 int arguments_size = arguments.size();
404 for(int i = 0; i < arguments_size; i++) {
405 Argument argument = (Argument)arguments.get(i);
406 if(argument.isAssigned()) {
407 text.append(argument.toString());
408 text.append(" ");
409 }
410 }
411 return text.substring(0, text.length() - 1);
412 }
413 else {
414 return name;
415 }
416 }
417}
Note: See TracBrowser for help on using the repository browser.