source: trunk/gli/src/org/greenstone/gatherer/cdm/Plugin.java@ 9302

Last change on this file since 9302 was 9302, checked in by mdewsnip, 19 years ago

Fix to the nasty bug where plugin options are not remembered.

  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 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
29import java.io.*;
30import java.util.*;
31import org.greenstone.gatherer.DebugStream;
32import org.greenstone.gatherer.util.StaticStrings;
33import org.w3c.dom.*;
34
35/** This class is responsible for storing information from a parsed pluginfo call in such a way that it allows easy access to parsed details for the purposes of user design and specification of plugins. */
36public class Plugin
37 extends ArrayList
38 implements ArgumentContainer, Comparable, DOMProxyListEntry, Serializable {
39 /** The DOM Element this assigned Plugin is modelled on. */
40 private Element element;
41 private boolean does_explode_metadata_databases = false; // Only for Base
42 private boolean is_abstract = false; // Only for Base
43 /** The parent Plugin this one inherits from, if any. */
44 private Plugin super_plugin; // Only for Base
45 private String description; // Only for Base
46 private String name; // Only for Base
47
48 /** Constructor used in DOMProxyListModel initializations, and Library Level. Used for Base plugins (those in the list of available plugins, not ones that are in the DOMProxyList)
49 */
50 public Plugin() {
51 }
52
53 /** Constructor used for the plugins that are in the DOMProxyList */
54 // Every time the list of plugins in the assigned plugins box changes, (eg plugin added or removed, not when plugin configured), the plugins seem to be regenerated, using the element from the old plugin. All known args get added to the element the first time this happens - we need to add them to the arguments list in the order they are found in the base plugins though, not this order.
55 public Plugin(Element element, Plugin base_plugin) {
56 super();
57 this.element = element;
58 this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
59 //DebugStream.println("Establishing Plugin: " + name);
60 // Parse in any argument options for this plugin, keeping a list of the ones found
61 HashMap known_arguments = new HashMap();
62 NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
63 int option_elements_length = option_elements.getLength();
64 for(int i = 0; i < option_elements_length; i++) {
65 Element option_element = (Element) option_elements.item(i);
66 Argument argument = new Argument(option_element);
67 //DebugStream.println("Rebuilding existing argument: " + argument.getName());
68 known_arguments.put(argument.getName(), argument);
69 if (argument.isAssigned() || base_plugin == null) {
70 // if the arg is assigned, the current plugin now becomes its owner, and we add it to the front of the ArrayList of args. But otherwise, it will retain its old owner, and we will add it in the correct place from the base plugin
71 argument.setOwner(name);
72 add(argument);
73 }
74 }
75 // If a base plugin was given
76 if(base_plugin != null) {
77 //DebugStream.println("Based on previous plugin.");
78 // Copy the details, and add a reference to whatever base_plugins super plugin is. ??
79 description = base_plugin.getDescription();
80 // Now search through the 'dummy' arguments belonging to the base plugin. 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 plugin, copy them and add them, but without a value.
81 ArrayList all_arguments = base_plugin.getArguments(true, true);
82 int argument_count = all_arguments.size();
83 for(int j = 0; j < argument_count; j++) {
84 Argument base_argument = (Argument) all_arguments.get(j);
85 String base_argument_name = base_argument.getName();
86 //DebugStream.println("Library indicates this plugin should have an argument: " + base_argument_name);
87 Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
88 // Found an existing argument. Complete its details
89 if(existing_argument != null) {
90 //DebugStream.println("Found existing argument. Filling out details.");
91 existing_argument.setCustomArgument(false);
92 existing_argument.setDefaultValue(base_argument.getDefaultValue());
93 existing_argument.setDescription(base_argument.getDescription());
94 existing_argument.setOptions(base_argument.getOptions());
95 existing_argument.setRequired(base_argument.isRequired());
96 existing_argument.setType(base_argument.getType());
97 existing_argument.setMinimum(base_argument.getMinimum());
98 existing_argument.setMaximum(base_argument.getMaximum());
99 if (!existing_argument.isAssigned()) {
100 // here we give it back its original owner and add it to the list. If it is assigned, these two things were done already
101 existing_argument.setOwner(base_argument.getOwner());
102 add(existing_argument);
103 }
104
105 }
106 // 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.
107 else {
108 //DebugStream.println("No such argument. Adding new, unassigned, argument.");
109 // The trick thing is that we have to create a new element in the DOM as well.
110 Argument new_argument = base_argument.copy();
111 Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
112 argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
113 argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
114 argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.FALSE_STR);
115 // All done. Add it.
116 // if we are not in the first collection opened, then this
117 /// will belong to a different document, so need to import
118 // it.
119 Node new_element = element.getOwnerDocument().importNode(argument_element, true);
120 new_argument.setElement((Element) new_element);
121 element.appendChild(new_element);
122 add(new_argument);
123 }
124 }
125 }
126 }
127
128 /** Method to add an argument to this base plugin. Only adds the argument if it isn't already present, and only if this is a base plugin (ie not based on DOM).
129 * @param argument the Argument to add
130 */
131 public void addArgument(Argument argument) {
132 if(element == null && !contains(argument)) {
133 add(argument);
134 argument.setOwner(name);
135 }
136 }
137
138 /** Method to compare two plugins for ordering.
139 * @param object The plugin we are comparing to, as an <strong>Object</strong>.
140 * @return An <i>int</i> specifying the plugin order, using values as set out in <strong>String</strong>.
141 * @see java.lang.String#compareTo
142 */
143 public int compareTo(Object object) {
144 if(object instanceof Plugin) {
145 return name.compareTo(((Plugin)object).getName());
146 }
147 return -1;
148 }
149
150 /** The assigned plugin constructor.
151 * @param element the DOM Element this plugin is based upon
152 */
153 public DOMProxyListEntry create(Element element) {
154 String plugin_name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
155 // Determine the base plugin from the plugin name
156 Plugin base_plugin = CollectionDesignManager.plugin_manager.getBasePlugin(plugin_name);
157 Plugin plugin = new Plugin(element, base_plugin);
158 base_plugin = null;
159 plugin_name = null;
160 return plugin;
161 }
162
163
164 /** Checks whether the plugin this instance is based on processes metadata databases that can be exploded. */
165 public boolean doesExplodeMetadataDatabases()
166 {
167 Plugin base_plugin = CollectionDesignManager.plugin_manager.getBasePlugin(getName());
168 if (base_plugin == null) {
169 return false;
170 }
171 return base_plugin.does_explode_metadata_databases;
172 }
173
174
175 /** Checks whether this plugin instance will process the specified file (given its process_exp). */
176 public boolean doesProcessFile(File file)
177 {
178 // Check the filename against the plugin's process_exp value
179 ArrayList arguments = getArguments(true, true);
180 for (int i = 0; i < arguments.size(); i++) {
181 Argument argument = (Argument) arguments.get(i);
182 if (argument.getName().equals("process_exp")) {
183 // Try the assigned value first, for when the user has manually set the value
184 String regular_expression = argument.getValue();
185 if (regular_expression == null || regular_expression.equals("")) {
186 // Not set, so use the default value
187 regular_expression = argument.getDefaultValue();
188 if (regular_expression.equals("")) {
189 continue;
190 }
191 }
192
193 // The $ at the end doesn't seem to work in Java, so need to add ".*" at the start
194 if (regular_expression.startsWith("(?i)")) {
195 // Don't mess up case-insensitive matching though
196 regular_expression = "(?i)" + ".*" + regular_expression.substring("(?i)".length());
197 }
198 else {
199 regular_expression = ".*" + regular_expression;
200 }
201
202 // If the filename matches the regular expression, this plugin will deal with the file in some way
203 if (file.getName().matches(regular_expression)) {
204 return true;
205 }
206 }
207 }
208
209 // This plugin will (probably) not deal with the specified file
210 return false;
211 }
212
213
214 /** Method to determine if two plugins are equal.
215 * @param object The plugin to test against, as an <strong>Object</strong>.
216 * @return <i>true</i> if the plugin names match, <i>false</i> otherwise.
217 */
218 public boolean equals(Object object) {
219 return (compareTo(object) == 0);
220 }
221
222 /** Method to retrieve an argument by its name.
223 * @param name The name of the argument as a <strong>String</strong>.
224 * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
225 */
226 public Argument getArgument(String name) {
227 // The name given may still include the '-'
228 if(name.startsWith("-")) {
229 name = name.substring(1);
230 }
231 ArrayList arguments = getArguments(true, true);
232 for(int i = 0; i < arguments.size(); i++) {
233 Argument argument = (Argument)arguments.get(i);
234 if(argument.getName().equals(name)) {
235 return argument;
236 }
237 }
238 return null;
239 }
240
241 /** Retrieve all of the arguments available to this base plugin, including its super plugins arguments. Some complexity is added by allowing the caller to choose whether they want normal arguments, custom arguments, or both.
242 * @return an ArrayList of all of the arguments, starting with those for this plugin and ending with the arguments for basplug or similiar root plugin
243 */
244 public ArrayList getArguments(boolean include_normal, boolean include_custom) {
245 ArrayList arguments = new ArrayList();
246 if(include_normal && include_custom) {
247 arguments.addAll(this);
248 }
249 else {
250 int size = size();
251 for(int i = 0; i < size; i++) {
252 Argument argument = (Argument) get(i);
253 if(argument.isCustomArgument()) {
254 if(include_custom && !arguments.contains(argument)) {
255 arguments.add(argument);
256 }
257 }
258 else {
259 if(include_normal && !arguments.contains(argument)) {
260 arguments.add(argument);
261 }
262 }
263 argument = null;
264 }
265 }
266 if(super_plugin != null) {
267 ArrayList remainder = super_plugin.getArguments(include_normal, include_custom);
268 remainder.removeAll(arguments);
269 arguments.addAll(remainder);
270 }
271 return arguments;
272 }
273
274 /** Method to retrieve a plugins custom argument information. Custom arguments are defined to be those that have not got matching arguments in the base reference plugin from the library. Of course if there is no base plugin then all arguments are considered to be custom.
275 * @return the custom arguments as a String
276 */
277 public String getCustom() {
278 StringBuffer custom_text = new StringBuffer();
279 // Retrieve all of the arguments, and append any that are custom into one long string
280 ArrayList arguments = getArguments(false, true);
281 int arguments_size = arguments.size();
282 boolean first = true;
283 for(int i = 0; i < arguments_size; i++) {
284 Argument argument = (Argument) arguments.get(i);
285 if(argument.isAssigned()) {
286 if(!first) {
287 custom_text.append(" ");
288 }
289 custom_text.append(argument.toString());
290 first = false;
291 }
292 }
293 return custom_text.toString();
294 }
295
296 public String getDescription() {
297 return description;
298 }
299
300 public Element getElement() {
301 return element;
302 }
303
304 /** Method to retrieve a plugins name.
305 * @return A <strong>String</strong> containing the plugins name.
306 */
307 public String getName() {
308 if(name == null && element != null) {
309 name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
310 }
311 return name;
312 }
313
314 public boolean isAbstract() {
315 return is_abstract;
316 }
317
318 public boolean isAssigned() {
319 return (element != null && !element.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.FALSE_STR));
320 }
321
322 public boolean isSeparator() {
323 return (element != null && element.getAttribute(StaticStrings.SEPARATOR_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
324 }
325
326 public void setAssigned(boolean assigned) {
327 if(element != null) {
328 element.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (assigned ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR));
329 }
330 }
331
332 /** 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!).
333 * @param custom_str the custom arguments all splodged together in one String
334 */
335 public void setCustom(String custom_str) {
336 HashMap raw_arguments = CollectionConfiguration.parseArguments(new CommandTokenizer(custom_str));
337 ArrayList custom_arguments = getArguments(false, true);
338 int size = custom_arguments.size();
339 for(int i = 0; i < size; i++) {
340 Argument argument = (Argument) custom_arguments.get(i);
341 String original_argument_name = StaticStrings.MINUS_CHARACTER + argument.getName();
342 if(raw_arguments.containsKey(original_argument_name)) {
343 // Set as assigned
344 argument.setAssigned(true);
345 String argument_value = (String)raw_arguments.remove(original_argument_name);
346 if(argument_value != null) {
347 argument.setValue(argument_value);
348 argument_value = null;
349 }
350 }
351 // We've removed it from our custom statement, so unassign
352 else {
353 argument.setAssigned(false);
354 }
355 argument = null;
356 }
357 // Any left over, add to the plugin
358 Iterator argument_names = raw_arguments.keySet().iterator();
359 while(argument_names.hasNext()) {
360 String argument_name = (String) argument_names.next();
361 String argument_value = (String) raw_arguments.get(argument_name);
362 // The tricky thing is that we have to create a new element in the DOM as well.
363 Element argument_element = CollectionDesignManager.collect_config.document.createElement(StaticStrings.OPTION_ELEMENT);
364 argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, argument_name.substring(1));
365 argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
366 argument_element.setAttribute(StaticStrings.CUSTOM_ATTRIBUTE, StaticStrings.TRUE_STR);
367 Argument argument = new Argument(argument_element);
368 argument_name = null;
369 if(argument_value != null) {
370 argument.setValue(argument_value);
371 argument_value = null;
372 }
373 // All done. Add it.
374 element.appendChild(argument_element);
375 add(argument);
376 argument_element = null;
377 }
378 raw_arguments = null;
379 }
380
381 /** Method to set the value of desc.
382 * @param description The new value of desc as a <strong>String</strong>.
383 */
384 public void setDescription(String description) {
385 this.description = description;
386 }
387
388 public void setDoesExplodeMetadataDatabases(boolean does_explode_metadata_databases) {
389 this.does_explode_metadata_databases = does_explode_metadata_databases;
390 }
391
392 public void setElement(Element element) {
393 this.element = element;
394 }
395
396 public void setIsAbstract(boolean is_abstract) {
397 this.is_abstract = is_abstract;
398 }
399
400 /** Method to set the value of name.
401 * @param name The new value of name as a <strong>String</strong>.
402 */
403 public void setName(String name) {
404 this.name = name;
405 }
406
407 /** Method to set the value of the super_plugin.
408 * @param super_plugin The new value of super_plugin as a <strong>Plugin</strong>, or <i>null</i> if this class has no inheritance.
409 */
410 public void setSuper(Plugin super_plugin) {
411 this.super_plugin = super_plugin;
412 }
413
414 /** Method to print out this plugin as it would appear as a command within the collection configuration file.
415 * @return A <strong>String</strong> containing a single plugin command.
416 */
417 public String toString() {
418 if(element != null) {
419 if(name == null) {
420 name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
421 }
422 StringBuffer text = new StringBuffer(StaticStrings.PLUGIN_STR);
423 text.append(" ");
424 text.append(name);
425 text.append(" ");
426 ArrayList arguments = getArguments(true, true);
427 int arguments_size = arguments.size();
428 for(int i = 0; i < arguments_size; i++) {
429 Argument argument = (Argument)arguments.get(i);
430 if(argument.isAssigned()) {
431 text.append(argument.toString());
432 text.append(" ");
433 }
434 argument = null;
435 }
436 return text.substring(0, text.length() - 1);
437 }
438 // Basic Plugin
439 else {
440 return name;
441 }
442 }
443}
Note: See TracBrowser for help on using the repository browser.