source: trunk/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java@ 4932

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

Major CDM rewrite so it uses DOM.

  • Property svn:keywords set to Author Date Id Revision
File size: 54.4 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;
28import java.awt.*;
29import java.awt.event.*;
30import java.io.*;
31import java.util.*;
32import javax.swing.*;
33import org.greenstone.gatherer.Gatherer;
34import org.greenstone.gatherer.cdm.CommandTokenizer;
35import org.greenstone.gatherer.msm.MSMUtils;
36import org.greenstone.gatherer.util.DOMTree;
37import org.greenstone.gatherer.util.StaticStrings;
38import org.greenstone.gatherer.util.Utility;
39import org.w3c.dom.*;
40/** This class provides either access to a pseudo-G3 document, or parses a collect.cfg file in such a way as to provide an xml-type view of its content. This later version is useful as it allows the manipulation and free form editing of a legacy collect.cfg file while still allowing the various CDM data managers to base themselves directly on this model (whereas they used to be independant ListModels which clobbered the ordering of unparsed commands).
41 * @author John Thompson, Greenstone Digital Library, University of Waikato
42 * @version 2.3d
43 */
44public class CollectionConfiguration
45 extends StaticStrings {
46
47 static public Document document;
48
49 static public void main(String[] args) {
50 if(args.length >= 1) {
51 File file = new File(args[0]);
52 CollectionConfiguration collect_cfg = new CollectionConfiguration(file);
53 collect_cfg.save(true);
54 collect_cfg.save(false);
55 collect_cfg = null;
56 }
57 else {
58 System.out.println("Usage: CollectionConfiguration <filename>");
59 }
60 }
61
62 /** Find the best insertion position for the given DOM Element. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg PlugIns). Failing a command match it will check against the command order for the best insertion location.
63 * @param element the command Element to be inserted
64 * @return the Element which the given command should be inserted before, or null to append to end of list
65 */
66 static public Node findInsertionPoint(Element target_element) {
67 ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
68 String target_element_name = target_element.getNodeName();
69 Element document_element = document.getDocumentElement();
70 // Try to find commands with the same tag.
71 NodeList matching_elements = document_element.getElementsByTagName(target_element_name);
72 // If we found matching elements, then we have our most likely insertion location, so check within for groupings
73 if(matching_elements.getLength() != 0) {
74 ///ystem.err.println("Found matching elements.");
75 // Only CollectionMeta are grouped.
76 if(target_element_name.equals(COLLECTIONMETADATA_ELEMENT)) {
77 ///ystem.err.println("Dealing with collection metadata");
78 // Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
79 // So if the command to be added is special add it immediately after any other special command
80 if(target_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
81 int index = 0;
82 Element matched_element = (Element) matching_elements.item(index);
83 Element sibling_element = (Element) matched_element.getNextSibling();
84 while(sibling_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
85 index++;
86 matched_element = (Element) matching_elements.item(index);
87 sibling_element = (Element) matched_element.getNextSibling();
88 }
89 if(sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
90 Element newline_element = document.createElement(NEWLINE_ELEMENT);
91 document_element.insertBefore(newline_element, sibling_element);
92 }
93 return sibling_element;
94 }
95 // Otherwise try to find a matching 'name' and add after the last one in that group.
96 else {
97 int index = 0;
98 target_element_name = target_element.getAttribute(NAME_ATTRIBUTE);
99 boolean found = false;
100 // Skip all of the special metadata
101 Element matched_element = (Element) matching_elements.item(index);
102 while(matched_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
103 index++;
104 matched_element = (Element) matching_elements.item(index);
105 }
106 // Begin search
107 while(!found && matched_element != null) {
108 if(matched_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) {
109 found = true;
110 }
111 else {
112 index++;
113 matched_element = (Element) matching_elements.item(index);
114 }
115 }
116 // If we found a match, we need to continue checking until we find the last name match.
117 if(found) {
118 index++;
119 Element previous_sibling = matched_element;
120 Element sibling_element = (Element) matching_elements.item(index);
121 while(sibling_element != null && sibling_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) {
122 previous_sibling = sibling_element;
123 index++;
124 sibling_element = (Element) matching_elements.item(index);
125 }
126 // Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
127 return previous_sibling.getNextSibling();
128 }
129 // If not found we just add after last metadata element
130 else {
131 Element last_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
132 return last_element.getNextSibling();
133 }
134 }
135
136 }
137 else {
138 ///ystem.err.println("Not dealing with collection meta.");
139 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
140 // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
141 Node sibling_element = matched_element.getNextSibling();
142 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
143 Element newline_element = document.createElement(NEWLINE_ELEMENT);
144 document_element.insertBefore(newline_element, sibling_element);
145 }
146 return sibling_element; // Note that this may be null
147 }
148 }
149 ///ystem.err.println("No matching elements found.");
150 // Locate where this command is in the ordering
151 int command_index = -1;
152 for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
153 if(COMMAND_ORDER[i].equals(target_element_name)) {
154 command_index = i;
155 }
156 }
157 ///ystem.err.println("Command index is: " + command_index);
158 // Now move forward, checking for existing elements in each of the preceeding command orders.
159 int preceeding_index = command_index - 1;
160 ///ystem.err.println("Searching before the target command.");
161 while(preceeding_index >= 0) {
162 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[preceeding_index]);
163 // If we've found a match
164 if(matching_elements.getLength() > 0) {
165 // We add after the last element
166 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
167 // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
168 Node sibling_element = matched_element.getNextSibling();
169 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
170 Element newline_element = document.createElement(NEWLINE_ELEMENT);
171 document_element.insertBefore(newline_element, sibling_element);
172 }
173 return sibling_element; // Note that this may be null
174 }
175 preceeding_index--;
176 }
177 // If all that fails, we now move backwards through the commands
178 int susceeding_index = command_index + 1;
179 ///ystem.err.println("Searching after the target command.");
180 while(susceeding_index < COMMAND_ORDER.length) {
181 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[susceeding_index]);
182 // If we've found a match
183 if(matching_elements.getLength() > 0) {
184 // We add before the first element
185 Element matched_element = (Element) matching_elements.item(0);
186 // One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
187 Node sibling_element = matched_element.getPreviousSibling();
188 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
189 Element newline_element = document.createElement(NEWLINE_ELEMENT);
190 document_element.insertBefore(newline_element, sibling_element);
191 }
192 return sibling_element; // Note that this may be null
193 }
194 susceeding_index++;
195 }
196 // Well. Apparently there are no other commands in this collection configuration. So append away...
197 return null;
198 }
199
200 static public String toString(Element command_element, boolean show_extracted_namespace) {
201 String command_element_name = command_element.getNodeName();
202 if(command_element_name.equals(CLASSIFY_ELEMENT)) {
203 return self.classifyToString(command_element, show_extracted_namespace);
204 }
205 else if(command_element_name.equals(FORMAT_ELEMENT)) {
206 return self.formatToString(command_element, show_extracted_namespace);
207 }
208 else if(command_element_name.equals(INDEXES_ELEMENT)) {
209 return self.indexesToString(command_element, show_extracted_namespace);
210 }
211 else if(command_element_name.equals(INDEX_DEFAULT_ELEMENT)) {
212 return self.indexDefaultToString(command_element, show_extracted_namespace);
213 }
214 else if(command_element_name.equals(LANGUAGES_ELEMENT)) {
215 return self.languagesToString(command_element);
216 }
217 else if(command_element_name.equals(LANGUAGE_DEFAULT_ELEMENT)) {
218 return self.languageDefaultToString(command_element);
219 }
220 else if(command_element_name.equals(COLLECTIONMETADATA_ELEMENT)) {
221 return self.metadataToString(command_element);
222 }
223 else if(command_element_name.equals(PLUGIN_ELEMENT)) {
224 return self.pluginToString(command_element, show_extracted_namespace);
225 }
226 //else if(command_element_name.equals(SEARCHTYPE_ELEMENT)) {
227 // return self.searchtypeToString(command_element);
228 //}
229 else if(command_element_name.equals(SUBCOLLECTION_ELEMENT)) {
230 return self.subcollectionToString(command_element, show_extracted_namespace);
231 }
232 else if(command_element_name.equals(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
233 return self.subcollectionDefaultIndexToString(command_element);
234 }
235 else if(command_element_name.equals(SUBCOLLECTION_INDEXES_ELEMENT)) {
236 return self.subcollectionIndexesToString(command_element);
237 }
238 else if(command_element_name.equals(SUPERCOLLECTION_ELEMENT)) {
239 return self.supercollectionToString(command_element);
240 }
241 else if(command_element_name.equals(UNKNOWN_ELEMENT)) {
242 return self.unknownToString(command_element);
243 }
244 return "";
245 }
246
247 /** Parses arguments from a tokenizer and returns a HashMap of mappings. The tricky bit here is that not all entries in the HashMap are name->value pairs, as some arguments are boolean and are turned on by their presence. Arguments are denoted by a '-' prefix.
248 * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
249 * @return a HashMap containing the arguments parsed
250 */
251 static public HashMap parseArguments(CommandTokenizer tokenizer) {
252 HashMap arguments = new HashMap();
253 String name = null;
254 String value = null;
255 while(tokenizer.hasMoreTokens() || name != null) {
256 // First we retrieve a name if we need one.
257 if(name == null) {
258 name = tokenizer.nextToken();
259 }
260 // Now we attempt to retrieve a value
261 if(tokenizer.hasMoreTokens()) {
262 value = tokenizer.nextToken();
263 // Test if the value is actually a name, and if so add the name by itself, then put value into name so that it is parsed correctly during the next loop.
264 if(value.startsWith(StaticStrings.MINUS_CHARACTER)) {
265 arguments.put(name, null);
266 name = value;
267 }
268 // Otherwise we have a typical name->value pair ready to go
269 else {
270 arguments.put(name, value);
271 name = null;
272 }
273 }
274 // Otherwise its a binary flag
275 else {
276 arguments.put(name, null);
277 name = null;
278 }
279 }
280 return arguments;
281 }
282
283 static private ArrayList known_metadata;
284
285 static private CollectionConfiguration self;
286
287 static final private String EXTRACTED_PREFIX = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP;
288 /** Gives the preferred ordering of commands */
289 static final private String[] COMMAND_ORDER = {StaticStrings.COLLECTIONMETADATA_ELEMENT, StaticStrings.SEARCHTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_ELEMENT, StaticStrings.SUBCOLLECTION_ELEMENT, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT, StaticStrings.SUPERCOLLECTION_ELEMENT, StaticStrings.CLASSIFY_ELEMENT, StaticStrings.FORMAT_ELEMENT, StaticStrings.COLLECTIONMETADATA_ELEMENT};
290
291 /** ************************** Public Data Members ***************************/
292
293 /** ************************** Private Data Members ***************************/
294
295 private File collect_config_file;
296
297 /** ************************** Public Methods ***************************/
298
299 public CollectionConfiguration(File collect_config_file) {
300 this.self = this;
301 this.collect_config_file = collect_config_file;
302 // If collect_cfg is xml we can load it straight away
303 String collect_config_name = collect_config_file.getName();
304 if(collect_config_name.equals(COLLECTCONFIGURATION_XML)) {
305 // Parse with Utility but don't use class loader
306 document = Utility.parse(collect_config_file, false);
307 }
308 // Otherwise if this is a legacy collect.cfg file then read in the template and send to magic parser
309 else if(collect_config_name.equals(COLLECT_CFG)) {
310 document = Utility.parse(PSEUDO_COLLECTCONFIGURATION_XML, true);
311 parse(collect_config_file);
312 }
313 }
314
315 /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
316 public void display() {
317 JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false);
318 dialog.setSize(400,400);
319 JPanel content_pane = (JPanel) dialog.getContentPane();
320 final DOMTree tree = new DOMTree(document);
321 JButton refresh_button = new JButton("Refresh Tree");
322 refresh_button.addActionListener(new ActionListener() {
323 public void actionPerformed(ActionEvent event) {
324 tree.setDocument(document);
325 }
326 });
327 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
328 content_pane.setLayout(new BorderLayout());
329 content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
330 content_pane.add(refresh_button, BorderLayout.SOUTH);
331 dialog.show();
332 }
333
334 public Element getDocumentElement() {
335 return document.getDocumentElement();
336 }
337
338 public File getFile() {
339 return collect_config_file;
340 }
341
342 /** Retrieve or create the indexes Element. */
343 public Element getIndexes() {
344 return getOrCreateElementByTagName(INDEXES_ELEMENT);
345 }
346
347 /** Retrieve or create the languages Element. */
348 public Element getLanguages() {
349 return getOrCreateElementByTagName(LANGUAGES_ELEMENT);
350 }
351
352 /** Retrieve or create the subindexes Element. */
353 public Element getSubIndexes() {
354 return getOrCreateElementByTagName(SUBCOLLECTION_INDEXES_ELEMENT);
355 }
356
357 /** Retrieve or create the supercollections Element. */
358 public Element getSuperCollection() {
359 return getOrCreateElementByTagName(SUPERCOLLECTION_ELEMENT);
360 }
361
362 public void save() {
363 save(false);
364 }
365
366 public void save(boolean force_xml) {
367 if(collect_config_file.exists()) {
368 File original_file = new File(collect_config_file.getParentFile(), COLLECT_CFG);
369 File backup_file = new File(collect_config_file.getParentFile(), "collect.bak");
370 if(backup_file.exists()) {
371 backup_file.delete();
372 }
373 if(!original_file.renameTo(backup_file)) {
374 Gatherer.println("Can't rename collect.cfg");
375 }
376 }
377 if(force_xml || collect_config_file.getName().equals(COLLECTCONFIGURATION_XML)) {
378 ///ystem.err.println("Writing XML");
379 Utility.export(document, new File(collect_config_file.getParentFile(), COLLECTCONFIGURATION_XML));
380 }
381 else {
382 ///ystem.err.println("Writing text");
383 try {
384 FileWriter file_writer = new FileWriter(collect_config_file, false);
385 BufferedWriter buffered_writer = new BufferedWriter(file_writer);
386 // In order to write out an old style collect.cfg we have to traverse the model and do several 'cute' tricks to ensure the collect.cfg is valid (for instance while every metadata element has a language attribute, only second or subsequent metadata, for a certain name, needs a language argument - hence the known metadata array. Note that within GLI the language will always be shown, but it doesn't crash and burn like G2 does, te-he).
387 known_metadata = new ArrayList();
388 Element collect_config_element = document.getDocumentElement();
389 NodeList command_elements = collect_config_element.getChildNodes();
390 for(int i = 0; i < command_elements.getLength(); i++) {
391 Node command_node = command_elements.item(i);
392 if(command_node instanceof Element) {
393 Element command_element = (Element) command_node;
394 // The only thing left are NewLine elements
395 if(command_element.getNodeName().equals(NEWLINE_ELEMENT)) {
396 buffered_writer.newLine();
397 }
398 // Anything else we write to file, but only if it has been assigned
399 else if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)){
400 String command = toString(command_element, false);
401 if(command != null && command.length() > 0) {
402 write(buffered_writer, command);
403 buffered_writer.newLine();
404 }
405 }
406 }
407 }
408 buffered_writer.close();
409 known_metadata = null;
410 }
411 catch (Exception exception) {
412 Gatherer.println("Error in CollectionConfiguration.save(boolean): " + exception);
413 Gatherer.printStackTrace(exception);
414 }
415 }
416 }
417
418 /** ************************** Private Methods ***************************/
419
420 private String classifyToString(Element command_element, boolean show_extracted_namespace) {
421 StringBuffer text = new StringBuffer(CLASSIFY_STR);
422 text.append(TAB_CHARACTER);
423 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
424 text.append(SPACE_CHARACTER);
425 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
426 int option_elements_length = option_elements.getLength();
427 for(int j = 0; j < option_elements_length; j++) {
428 Element option_element = (Element) option_elements.item(j);
429 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
430 text.append(StaticStrings.MINUS_CHARACTER);
431 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
432 String value_str = MSMUtils.getValue(option_element);
433 if(value_str.length() > 0) {
434 // If the value happens to be the identifier of an extracted metadata element, then remove the namespace.
435 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) {
436 value_str = value_str.substring(EXTRACTED_PREFIX.length());
437 }
438 text.append(SPACE_CHARACTER);
439 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
440 text.append(value_str);
441 }
442 else {
443 text.append(QUOTE_CHARACTER);
444 text.append(value_str);
445 text.append(QUOTE_CHARACTER);
446 }
447 }
448 value_str = null;
449 if(j < option_elements_length - 1) {
450 text.append(SPACE_CHARACTER);
451 }
452 }
453 option_element = null;
454 }
455 option_elements = null;
456 return text.toString();
457 }
458
459 private String formatToString(Element command_element, boolean show_extracted_namespace) {
460 StringBuffer text = new StringBuffer(FORMAT_STR);
461 text.append(SPACE_CHARACTER);
462 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
463 text.append(SPACE_CHARACTER);
464 String value_str = command_element.getAttribute(VALUE_ATTRIBUTE);
465 if(value_str.length() != 0) {
466 text.append(value_str);
467 }
468 else {
469 value_str = MSMUtils.getValue(command_element);
470 // Remove any references to a namespace for extracted metadata
471 if(!show_extracted_namespace) {
472 value_str.replaceAll(EXTRACTED_PREFIX, "");
473 }
474 text.append(QUOTE_CHARACTER);
475 text.append(value_str);
476 text.append(QUOTE_CHARACTER);
477 }
478 value_str = null;
479 return text.toString();
480 }
481
482 /** Retrieve or create the indexes Element. */
483 private Element getOrCreateElementByTagName(String name) {
484 ///ystem.err.println("Get or create element by tag name: " + name);
485 Element document_element = document.getDocumentElement();
486 NodeList elements = document_element.getElementsByTagName(name);
487 if(elements.getLength() > 0) {
488 ///ystem.err.println("Found element.");
489 document_element = null;
490 return (Element) elements.item(0);
491 }
492 else {
493 ///ystem.err.println("Creating element.");
494 Element element = document.createElement(name);
495 Node target_node = findInsertionPoint(element);
496 if(target_node != null) {
497 document_element.insertBefore(element, target_node);
498 }
499 else {
500 document_element.appendChild(element);
501 }
502 document_element = null;
503 return element;
504 }
505 }
506
507 private String indexesToString(Element command_element, boolean show_extracted_namespace) {
508 StringBuffer text = new StringBuffer(INDEX_STR);
509 text.append(TAB_CHARACTER);
510 text.append(TAB_CHARACTER);
511 NodeList index_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
512 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
513 int index_elements_length = index_elements.getLength();
514 for(int j = 0; j < index_elements_length; j++) {
515 Element index_element = (Element) index_elements.item(j);
516 text.append(index_element.getAttribute(LEVEL_ATTRIBUTE));
517 text.append(StaticStrings.COLON_CHARACTER);
518 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT);
519 int content_elements_length = content_elements.getLength();
520 for(int k = 0; k < content_elements_length; k++) {
521 Element content_element = (Element) content_elements.item(k);
522 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
523 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
524 name_str = name_str.substring(EXTRACTED_PREFIX.length());
525 }
526 text.append(name_str);
527 name_str = null;
528 if(k < content_elements_length - 1) {
529 text.append(StaticStrings.COMMA_CHARACTER);
530 }
531 content_element = null;
532 }
533 if(j < index_elements_length - 1) {
534 text.append(SPACE_CHARACTER);
535 }
536 content_elements = null;
537 index_element = null;
538 }
539 index_elements = null;
540 return text.toString();
541 }
542
543 private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
544 StringBuffer text = new StringBuffer(INDEX_DEFAULT_STR);
545 text.append(TAB_CHARACTER);
546 text.append(command_element.getAttribute(LEVEL_ATTRIBUTE));
547 text.append(StaticStrings.COLON_CHARACTER);
548 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
549 int content_elements_length = content_elements.getLength();
550 for(int j = 0; j < content_elements_length; j++) {
551 Element content_element = (Element) content_elements.item(j);
552 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
553 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
554 name_str = name_str.substring(EXTRACTED_PREFIX.length());
555 }
556 text.append(name_str);
557 name_str = null;
558 if(j < content_elements_length - 1) {
559 text.append(StaticStrings.COMMA_CHARACTER);
560 }
561 content_element = null;
562 }
563 content_elements = null;
564 return text.toString();
565 }
566
567 private String languagesToString(Element command_element) {
568 StringBuffer text = new StringBuffer(LANGUAGES_STR);
569 text.append(TAB_CHARACTER);
570 // Retrieve all the languages and write them out in a space separated list
571 NodeList language_elements = command_element.getElementsByTagName(LANGUAGE_ELEMENT);
572 int language_elements_length = language_elements.getLength();
573 if(language_elements_length == 0) {
574 return null;
575 }
576 for(int j = 0; j < language_elements_length; j++) {
577 Element language_element = (Element) language_elements.item(j);
578 text.append(language_element.getAttribute(NAME_ATTRIBUTE));
579 if(j < language_elements_length - 1) {
580 text.append(SPACE_CHARACTER);
581 }
582 }
583 return text.toString();
584 }
585
586 private String languageDefaultToString(Element command_element) {
587 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR);
588 text.append(TAB_CHARACTER);
589 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
590 return text.toString();
591 }
592
593 static public String metadataToString(Element command_element) {
594 // If there is no value attribute, then we don't write anything
595 String value_str = MSMUtils.getValue(command_element);
596 if(value_str == null || value_str.length() == 0) {
597 return "";
598 }
599 else {
600 StringBuffer text = new StringBuffer("");
601 String name_str = command_element.getAttribute(NAME_ATTRIBUTE);
602 // If the name is one of the special four, we don't write the collectionmeta first. Note the maintainer collectionmeta is singled out for 'prittying' reasons.
603 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
604 text.append(name_str);
605 text.append(TAB_CHARACTER);
606 }
607 else if(name_str.equals(COLLECTIONMETADATA_BETA_STR) || name_str.equals(COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
608 text.append(name_str);
609 text.append(TAB_CHARACTER);
610 text.append(TAB_CHARACTER);
611 }
612 else {
613 text.append(COLLECTIONMETADATA_STR);
614 text.append(TAB_CHARACTER);
615 text.append(name_str);
616 }
617 String language_str = command_element.getAttribute(LANGUAGE_ATTRIBUTE);
618 text.append(SPACE_CHARACTER);
619 // If this is element is in english, and it is the first one found, we don't need to write the language argument.
620 if(!language_str.equals(ENGLISH_LANGUAGE_STR) || known_metadata == null || known_metadata.contains(name_str)) {
621 text.append(LBRACKET_CHARACTER);
622 text.append(LANGUAGE_ARGUMENT);
623 text.append(language_str);
624 text.append(RBRACKET_CHARACTER);
625 text.append(SPACE_CHARACTER);
626 }
627 if(known_metadata != null) {
628 known_metadata.add(name_str);
629 }
630 language_str = null;
631 name_str = null;
632 // We don't wrap the email addresses in quotes, nor any string without spaces
633 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
634 text.append(value_str);
635 }
636 else {
637 text.append(QUOTE_CHARACTER);
638 text.append(value_str);
639 text.append(QUOTE_CHARACTER);
640 }
641 value_str = null;
642 return text.toString();
643 }
644 }
645
646 /** Parse a collect.cfg into a DOM model representation. */
647 private void parse(File collect_config_file) {
648 try {
649 Element collect_cfg_element = document.getDocumentElement();
650 // Read in the file command at a time.
651 FileReader in_reader = new FileReader(collect_config_file);
652 BufferedReader in = new BufferedReader(in_reader);
653 String command_str = null;
654 while((command_str = in.readLine()) != null) {
655 Element command_element = null;
656 // A command may be broken over several lines.
657 command_str = command_str.trim();
658 boolean eof = false;
659 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) {
660 String next_line = in.readLine();
661 if(next_line != null) {
662 next_line = next_line.trim();
663 if(next_line.length() > 0) {
664 // Remove the new line character
665 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
666 // And append the next line, which due to the test above must be non-zero length
667 command_str = command_str + next_line;
668 }
669 next_line = null;
670 }
671 // If we've reached the end of the file theres nothing more we can do
672 else {
673 eof = true;
674 }
675 }
676 // If there is still a new line character, then we remove it and hope for the best
677 if(command_str.endsWith(NEWLINE_CHARACTER)) {
678 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
679 }
680 // Now we've either got a command to parse...
681 if(command_str.length() != 0) {
682 // Start trying to figure out what it is
683 StringTokenizer tokenizer = new StringTokenizer(command_str);
684 String command_type = tokenizer.nextToken().toLowerCase();
685 tokenizer = null;
686 // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created
687 if(command_element == null && command_type.equals(CLASSIFY_STR)) {
688 command_element = parseClassify(command_str);
689 }
690 if(command_element == null && command_type.equals(FORMAT_STR)) {
691 command_element = parseFormat(command_str);
692 }
693 if(command_element == null && command_type.equals(INDEX_STR)) {
694 command_element = parseIndex(command_str);
695 }
696 if(command_element == null && command_type.equals(INDEX_DEFAULT_STR)) {
697 command_element = parseIndexDefault(command_str);
698 }
699 if(command_element == null && command_type.equals(LANGUAGES_STR)) {
700 command_element = parseLanguage(command_str);
701 }
702 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) {
703 command_element = parseLanguageDefault(command_str);
704 }
705 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) {
706 command_element = parseMetadata(command_str);
707 }
708 if(command_element == null && (command_type.equals(COLLECTIONMETADATA_BETA_STR) || command_type.equals(COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals(COLLECTIONMETADATA_CREATOR_STR) || command_type.equals(COLLECTIONMETADATA_MAINTAINER_STR))) {
709 command_element = parseMetadataSpecial(command_str);
710 }
711 if(command_element == null && command_type.equals(PLUGIN_STR)) {
712 command_element = parsePlugIn(command_str);
713 }
714 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) {
715 command_element = parseSubCollection(command_str);
716 }
717 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) {
718 command_element = parseSubCollectionDefaultIndex(command_str);
719 }
720 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) {
721 command_element = parseSubCollectionIndex(command_str);
722 }
723 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) {
724 command_element = parseSuperCollection(command_str);
725 }
726 // Doesn't match any known type
727 command_type = null;
728 if(command_element == null) {
729 // No-one knows what to do with this command, so we create an Unknown command element
730 command_element = document.createElement(UNKNOWN_ELEMENT);
731 MSMUtils.setValue(command_element, command_str);
732 }
733 }
734 // Or an empty line to remember for later
735 else {
736 command_element = document.createElement(NEWLINE_ELEMENT);
737 }
738 // Now command element shouldn't be null so we append it to the collection config DOM
739 collect_cfg_element.appendChild(command_element);
740 }
741 }
742 catch(Exception exception) {
743 Gatherer.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
744 Gatherer.printStackTrace(exception);
745 }
746 }
747
748 private Element parseClassify(String command_str) {
749 Element command_element = null;
750 try {
751 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
752 // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
753 if(tokenizer.countTokens() >= 4) {
754 command_element = document.createElement(CLASSIFY_ELEMENT);
755 // First token is classify
756 tokenizer.nextToken();
757 // The next token is the classifier type
758 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
759 // Now we parse out the remaining arguments into a hashmapping from name to value
760 HashMap arguments = parseArguments(tokenizer);
761 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
762 Iterator names = arguments.keySet().iterator();
763 while(names.hasNext()) {
764 String name = (String) names.next();
765 String value = (String) arguments.get(name); // Can be null
766 // The metadata argument gets added as the content attribute
767 if(name.equals(METADATA_ARGUMENT) && value != null) {
768 // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
769 if(value.indexOf(MSMUtils.NS_SEP) == -1) {
770 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
771 }
772 //command_element.setAttribute(CONTENT_ATTRIBUTE, value);
773 }
774 // Everything else is an Option Element
775 Element option_element = document.createElement(OPTION_ELEMENT);
776 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
777 if(value != null) {
778 MSMUtils.setValue(option_element, value);
779 }
780 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
781 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
782 command_element.appendChild(option_element);
783 option_element = null;
784 name = null;
785 value = null;
786 }
787 names = null;
788 arguments = null;
789 }
790 tokenizer = null;
791 }
792 catch(Exception error) {
793 }
794 return command_element;
795 }
796
797 private Element parseFormat(String command_str) {
798 Element command_element = null;
799 try {
800 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
801 if(tokenizer.countTokens() >= 3) {
802 command_element = document.createElement(FORMAT_ELEMENT);
803 // First token is format
804 tokenizer.nextToken();
805 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
806 String format_value = tokenizer.nextToken();
807 // If the value is true or false we add it as an attribute
808 if(format_value.equalsIgnoreCase(TRUE_STR) || format_value.equalsIgnoreCase(FALSE_STR)) {
809 command_element.setAttribute(VALUE_ATTRIBUTE, format_value.toLowerCase());
810 }
811 // Otherwise it gets added as a text node
812 else {
813 // Strip any speech marks
814 if(format_value.startsWith(QUOTE_CHARACTER) && format_value.endsWith(QUOTE_CHARACTER)) {
815 format_value = format_value.substring(1, format_value.length() - 1);
816 }
817 MSMUtils.setValue(command_element, format_value);
818 }
819 format_value = null;
820 }
821 tokenizer = null;
822 }
823 catch(Exception exception) {
824 }
825 return command_element;
826 }
827
828 private Element parseIndex(String command_str) {
829 Element command_element = null;
830 try {
831 StringTokenizer tokenizer = new StringTokenizer(command_str);
832 tokenizer.nextToken();
833 if(tokenizer.hasMoreTokens()) {
834 command_element = document.createElement(INDEXES_ELEMENT);
835 }
836 while(tokenizer.hasMoreTokens()) {
837 Element index_element = document.createElement(INDEX_ELEMENT);
838 String index_str = tokenizer.nextToken();
839 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
840 String raw_content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
841 StringTokenizer content_tokenizer = new StringTokenizer(raw_content_str, StaticStrings.COMMA_CHARACTER);
842 while(content_tokenizer.hasMoreTokens()) {
843 Element content_element = document.createElement(CONTENT_ELEMENT);
844 String content_str = content_tokenizer.nextToken();
845 // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
846 if(!content_str.equals(StaticStrings.TEXT_STR) && content_str.indexOf(MSMUtils.NS_SEP) == -1) {
847 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
848 }
849 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
850 index_element.appendChild(content_element);
851 content_element = null;
852 }
853 content_tokenizer = null;
854 raw_content_str = null;
855 index_str = null;
856 command_element.appendChild(index_element);
857 index_element = null;
858 }
859 tokenizer = null;
860 }
861 catch (Exception exception) {
862 exception.printStackTrace();
863 }
864 return command_element;
865 }
866
867 private Element parseIndexDefault(String command_str) {
868 Element command_element = null;
869 try {
870 StringTokenizer tokenizer = new StringTokenizer(command_str);
871 if(tokenizer.countTokens() >= 2) {
872 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
873 tokenizer.nextToken();
874 String index_str = tokenizer.nextToken();
875 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
876 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
877 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
878 while(content_tokenizer.hasMoreTokens()) {
879 Element content_element = document.createElement(CONTENT_ELEMENT);
880 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
881 command_element.appendChild(content_element);
882 content_element = null;
883 }
884 content_tokenizer = null;
885 content_str = null;
886 content_str = null;
887 index_str = null;
888 }
889 tokenizer = null;
890 }
891 catch (Exception exception) {
892 }
893 return command_element;
894 }
895
896 private Element parseLanguage(String command_str) {
897 Element command_element = null;
898 try {
899 StringTokenizer tokenizer = new StringTokenizer(command_str);
900 tokenizer.nextToken();
901 if(tokenizer.hasMoreTokens()) {
902 command_element = document.createElement(LANGUAGES_ELEMENT);
903 }
904 while(tokenizer.hasMoreTokens()) {
905 Element language_element = document.createElement(LANGUAGE_ELEMENT);
906 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
907 command_element.appendChild(language_element);
908 language_element = null;
909 }
910 tokenizer = null;
911 }
912 catch (Exception exception) {
913 }
914 return command_element;
915 }
916
917 private Element parseLanguageDefault(String command_str) {
918 Element command_element = null;
919 try {
920 StringTokenizer tokenizer = new StringTokenizer(command_str);
921 if(tokenizer.countTokens() >= 2) {
922 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
923 tokenizer.nextToken();
924 String default_language_str = tokenizer.nextToken();
925 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
926 default_language_str = null;
927 }
928 tokenizer = null;
929 }
930 catch (Exception exception) {
931 }
932 return command_element;
933 }
934
935 private Element parseMetadata(String command_str) {
936 Element command_element = null;
937 try {
938 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
939 if(tokenizer.countTokens() >= 3) {
940 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
941 // First token is command type
942 tokenizer.nextToken();
943 String name_str = tokenizer.nextToken();
944 String value_str = tokenizer.nextToken();
945 String language_str = "en"; // By default
946 // Check if the value string is actually a language string
947 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
948 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
949 value_str = tokenizer.nextToken();
950 }
951 // Remove any speech marks from value
952 if(value_str.startsWith(QUOTE_CHARACTER) && value_str.endsWith(QUOTE_CHARACTER)) {
953 value_str = value_str.substring(1, value_str.length() - 1);
954 }
955 if(value_str != null) {
956 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
957 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
958 MSMUtils.setValue(command_element, value_str);
959 }
960 else {
961 command_element = null;
962 }
963 language_str = null;
964 value_str = null;
965 name_str = null;
966 }
967 tokenizer = null;
968 }
969 catch (Exception exception) {
970 }
971 return command_element;
972 }
973
974 private Element parseMetadataSpecial(String command_str) {
975 Element command_element = null;
976 try {
977 StringTokenizer tokenizer = new StringTokenizer(command_str);
978 if(tokenizer.countTokens() >= 2) {
979 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
980 String name_str = tokenizer.nextToken();
981 String value_str = tokenizer.nextToken();
982 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
983 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
984 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
985 MSMUtils.setValue(command_element, value_str);
986 value_str = null;
987 name_str = null;
988 }
989 tokenizer = null;
990 }
991 catch (Exception exception) {
992 }
993 return command_element;
994 }
995
996 private Element parsePlugIn(String command_str) {
997 Element command_element = null;
998 try {
999 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1000 // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
1001 if(tokenizer.countTokens() >= 2) {
1002 command_element = document.createElement(PLUGIN_ELEMENT);
1003 // First token is plugin
1004 tokenizer.nextToken();
1005 // The next token is the type
1006 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
1007 // Now we parse out the remaining arguments into a hashmapping from name to value
1008 HashMap arguments = parseArguments(tokenizer);
1009 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1010 Iterator names = arguments.keySet().iterator();
1011 while(names.hasNext()) {
1012 String name = (String) names.next();
1013 String value = (String) arguments.get(name); // Can be null
1014 Element option_element = document.createElement(OPTION_ELEMENT);
1015 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1016 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1017 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1018 if(value != null) {
1019 if(name.equals(METADATA_ARGUMENT)) {
1020 // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
1021 if(value.indexOf(MSMUtils.NS_SEP) == -1) {
1022 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
1023 }
1024 }
1025 MSMUtils.setValue(option_element, value);
1026 }
1027 command_element.appendChild(option_element);
1028 option_element = null;
1029 name = null;
1030 value = null;
1031 }
1032 names = null;
1033 arguments = null;
1034 }
1035 tokenizer = null;
1036 }
1037 catch(Exception exception) {
1038 }
1039 return command_element;
1040 }
1041
1042 private Element parseSubCollection(String command_str) {
1043 Element command_element = null;
1044 try {
1045 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1046 if(tokenizer.countTokens() >= 3) {
1047 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1048 // First token is command type
1049 tokenizer.nextToken();
1050 // Then subcollection identifier
1051 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1052 // Then finally the pattern used to build the subcollection partition
1053 String full_pattern_str = tokenizer.nextToken();
1054 // To make life easier I'm going to parse this up now.
1055 boolean exclusion = (full_pattern_str.substring(1, 2).equals(EXCLAIMATION_CHARACTER));
1056 // Set inclusion/exclusion flag, remove any exclaimation mark and the speech marks
1057 if(exclusion) {
1058 full_pattern_str = full_pattern_str.substring(2, full_pattern_str.length() - 1);
1059 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1060 }
1061 else {
1062 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length() - 1);
1063 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1064 }
1065 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1066 if(pattern_tokenizer.countTokens() >= 2) {
1067 String content_str = pattern_tokenizer.nextToken();
1068 // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
1069 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(MSMUtils.NS_SEP) == -1) {
1070 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
1071 }
1072 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1073 MSMUtils.setValue(command_element, pattern_tokenizer.nextToken());
1074 if(pattern_tokenizer.hasMoreTokens()) {
1075 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1076 }
1077 }
1078 pattern_tokenizer = null;
1079 }
1080 }
1081 catch(Exception exception) {
1082 exception.printStackTrace();
1083 }
1084 return command_element;
1085 }
1086
1087 private Element parseSubCollectionDefaultIndex(String command_str) {
1088 Element command_element = null;
1089 try {
1090 StringTokenizer tokenizer = new StringTokenizer(command_str);
1091 if(tokenizer.countTokens() == 2) {
1092 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1093 tokenizer.nextToken();
1094 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1095 String content_str = tokenizer.nextToken();
1096 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1097 while(content_tokenizer.hasMoreTokens()) {
1098 Element content_element = document.createElement(CONTENT_ELEMENT);
1099 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1100 command_element.appendChild(content_element);
1101 content_element = null;
1102 }
1103 content_tokenizer = null;
1104 content_str = null;
1105 }
1106 tokenizer = null;
1107 }
1108 catch(Exception exception) {
1109 }
1110 return command_element;
1111 }
1112
1113 private Element parseSubCollectionIndex(String command_str) {
1114 Element command_element = null;
1115 try {
1116 StringTokenizer tokenizer = new StringTokenizer(command_str);
1117 tokenizer.nextToken();
1118 if(tokenizer.hasMoreTokens()) {
1119 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1120 }
1121 while(tokenizer.hasMoreTokens()) {
1122 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1123 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1124 String content_str = tokenizer.nextToken();
1125 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1126 while(content_tokenizer.hasMoreTokens()) {
1127 Element content_element = document.createElement(CONTENT_ELEMENT);
1128 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1129 subcollectionindex_element.appendChild(content_element);
1130 content_element = null;
1131 }
1132 content_tokenizer = null;
1133 content_str = null;
1134 command_element.appendChild(subcollectionindex_element);
1135 subcollectionindex_element = null;
1136 }
1137 tokenizer = null;
1138 }
1139 catch (Exception exception) {
1140 }
1141 return command_element;
1142 }
1143
1144 private Element parseSuperCollection(String command_str) {
1145 Element command_element = null;
1146 try {
1147 StringTokenizer tokenizer = new StringTokenizer(command_str);
1148 if(tokenizer.countTokens() >= 3) {
1149 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1150 tokenizer.nextToken();
1151 while(tokenizer.hasMoreTokens()) {
1152 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1153 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1154 command_element.appendChild(collection_element);
1155 collection_element = null;
1156 }
1157 }
1158 tokenizer = null;
1159 }
1160 catch(Exception exception) {
1161 }
1162 return command_element;
1163 }
1164
1165 private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1166 StringBuffer text = new StringBuffer();
1167 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1168 text.append(PLUGIN_STR);
1169 text.append(TAB_CHARACTER);
1170 text.append(TAB_CHARACTER);
1171 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1172 // Retrieve, and output, the arguments
1173 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1174 int option_elements_length = option_elements.getLength();
1175 if(option_elements_length > 0) {
1176 text.append(SPACE_CHARACTER);
1177 for(int j = 0; j < option_elements_length; j++) {
1178 Element option_element = (Element) option_elements.item(j);
1179 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1180 text.append(StaticStrings.MINUS_CHARACTER);
1181 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1182 String value_str = MSMUtils.getValue(option_element);
1183 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) {
1184 value_str = value_str.substring(EXTRACTED_PREFIX.length());
1185 }
1186 if(value_str.length() > 0) {
1187 text.append(SPACE_CHARACTER);
1188 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1189 text.append(value_str);
1190 }
1191 else {
1192 text.append(QUOTE_CHARACTER);
1193 text.append(value_str);
1194 text.append(QUOTE_CHARACTER);
1195 }
1196 }
1197 value_str = null;
1198 if(j < option_elements_length - 1) {
1199 text.append(SPACE_CHARACTER);
1200 }
1201 }
1202 option_element = null;
1203 }
1204 }
1205 option_elements = null;
1206 }
1207 return text.toString();
1208 }
1209
1210 private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1211 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1212 text.append(SPACE_CHARACTER);
1213 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1214 text.append(SPACE_CHARACTER);
1215 text.append(TAB_CHARACTER);
1216 text.append(QUOTE_CHARACTER);
1217 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1218 text.append(EXCLAIMATION_CHARACTER);
1219 }
1220 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1221 if(!show_extracted_namespace && content_str.startsWith(EXTRACTED_PREFIX)) {
1222 content_str = content_str.substring(EXTRACTED_PREFIX.length());
1223 }
1224 text.append(content_str);
1225 content_str = null;
1226 text.append(SEPARATOR_CHARACTER);
1227 text.append(MSMUtils.getValue(command_element));
1228 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1229 if(options_str.length() > 0) {
1230 text.append(SEPARATOR_CHARACTER);
1231 text.append(options_str);
1232 }
1233 options_str = null;
1234 text.append(QUOTE_CHARACTER);
1235 return text.toString();
1236 }
1237
1238 private String subcollectionDefaultIndexToString(Element command_element) {
1239 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1240 text.append(TAB_CHARACTER);
1241 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1242 int content_elements_length = content_elements.getLength();
1243 for(int j = 0; j < content_elements_length; j++) {
1244 Element content_element = (Element) content_elements.item(j);
1245 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1246 if(j < content_elements_length - 1) {
1247 text.append(StaticStrings.COMMA_CHARACTER);
1248 }
1249 }
1250 return text.toString();
1251 }
1252
1253 private String subcollectionIndexesToString(Element command_element) {
1254 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1255 text.append(TAB_CHARACTER);
1256 // Retrieve all of the subcollection index partitions
1257 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1258 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1259 if(subcollectionindex_elements_length == 0) {
1260 return null;
1261 }
1262 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1263 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1264 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1265 int content_elements_length = content_elements.getLength();
1266 for(int k = 0; k < content_elements_length; k++) {
1267 Element content_element = (Element) content_elements.item(k);
1268 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1269 if(k < content_elements_length - 1) {
1270 text.append(StaticStrings.COMMA_CHARACTER);
1271 }
1272 }
1273 if(j < subcollectionindex_elements_length - 1) {
1274 text.append(SPACE_CHARACTER);
1275 }
1276 }
1277 return text.toString();
1278 }
1279
1280 private String supercollectionToString(Element command_element) {
1281 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1282 int content_elements_length = content_elements.getLength();
1283 if(content_elements_length > 1) {
1284 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1285 text.append(TAB_CHARACTER);
1286 for(int j = 0; j < content_elements_length; j++) {
1287 Element content_element = (Element) content_elements.item(j);
1288 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1289 if(j < content_elements_length - 1) {
1290 text.append(SPACE_CHARACTER);
1291 }
1292 }
1293 return text.toString();
1294 }
1295 return null;
1296 }
1297
1298 private String unknownToString(Element command_element) {
1299 return MSMUtils.getValue(command_element);
1300 }
1301
1302 /** Write the text to the buffer. This is used so we don't have to worry about storing intermediate String values just so we can calaulate length and offset.
1303 * @param writer the BufferedWriter to which the str will be written
1304 * @param str the String to be written
1305 */
1306 private void write(BufferedWriter writer, String str)
1307 throws IOException {
1308 writer.write(str, 0, str.length());
1309 }
1310}
Note: See TracBrowser for help on using the repository browser.