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

Last change on this file since 5564 was 5209, checked in by jmt12, 21 years ago

Fix 203B120 and 147

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