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

Last change on this file since 8055 was 8015, checked in by mdewsnip, 20 years ago

Moved clear() and setValue() functions from MSMUtils into XMLTools. Moved NS_SEP string from MSMUtils into StaticStrings.

  • Property svn:keywords set to Author Date Id Revision
File size: 77.7 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.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.util.*;
33import javax.swing.*;
34import org.greenstone.gatherer.Gatherer;
35import org.greenstone.gatherer.cdm.CommandTokenizer;
36import org.greenstone.gatherer.gui.GLIButton;
37import org.greenstone.gatherer.util.DOMTree;
38import org.greenstone.gatherer.util.Codec;
39import org.greenstone.gatherer.util.StaticStrings;
40import org.greenstone.gatherer.util.Utility;
41import org.greenstone.gatherer.util.XMLTools;
42import org.w3c.dom.*;
43
44/** 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).
45 * @author John Thompson, Greenstone Digital Library, University of Waikato
46 * @version 2.3d
47 */
48public class CollectionConfiguration
49 extends StaticStrings {
50
51 static final public String ENCODING = "UTF-8";
52
53 static public Document document;
54
55 static public void main(String[] args) {
56 if(args.length >= 1) {
57 File file = new File(args[0]);
58 CollectionConfiguration collect_cfg = new CollectionConfiguration(file);
59 collect_cfg.save(true);
60 collect_cfg.save(false);
61 collect_cfg = null;
62 }
63 else {
64 System.out.println("Usage: CollectionConfiguration <filename>");
65 }
66 }
67
68 /** 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.
69 * @param target_element the command Element to be inserted
70 * @return the Element which the given command should be inserted before, or null to append to end of list
71 */
72 static public Node findInsertionPoint(Element target_element) {
73 ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
74 String target_element_name = target_element.getNodeName();
75 Element document_element = document.getDocumentElement();
76 // Try to find commands with the same tag.
77 NodeList matching_elements = document_element.getElementsByTagName(target_element_name);
78 // If we found matching elements, then we have our most likely insertion location, so check within for groupings
79 if(matching_elements.getLength() != 0) {
80 ///ystem.err.println("Found matching elements.");
81 // Only CollectionMeta are grouped.
82 if(target_element_name.equals(COLLECTIONMETADATA_ELEMENT)) {
83 ///ystem.err.println("Dealing with collection metadata");
84 // 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.
85 // So if the command to be added is special add it immediately after any other special command
86 if(target_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
87 int index = 0;
88 Element matched_element = (Element) matching_elements.item(index);
89 Element sibling_element = (Element) matched_element.getNextSibling();
90 while(sibling_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
91 index++;
92 matched_element = (Element) matching_elements.item(index);
93 sibling_element = (Element) matched_element.getNextSibling();
94 }
95 if(sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
96 Element newline_element = document.createElement(NEWLINE_ELEMENT);
97 document_element.insertBefore(newline_element, sibling_element);
98 }
99 return sibling_element;
100 }
101 // Otherwise try to find a matching 'name' and add after the last one in that group.
102 else {
103 int index = 0;
104 target_element_name = target_element.getAttribute(NAME_ATTRIBUTE);
105 boolean found = false;
106 // Skip all of the special metadata
107 Element matched_element = (Element) matching_elements.item(index);
108 while(matched_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) {
109 index++;
110 matched_element = (Element) matching_elements.item(index);
111 }
112 // Begin search
113 while(!found && matched_element != null) {
114 if(matched_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) {
115 found = true;
116 }
117 else {
118 index++;
119 matched_element = (Element) matching_elements.item(index);
120 }
121 }
122 // If we found a match, we need to continue checking until we find the last name match.
123 if(found) {
124 index++;
125 Element previous_sibling = matched_element;
126 Element sibling_element = (Element) matching_elements.item(index);
127 while(sibling_element != null && sibling_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) {
128 previous_sibling = sibling_element;
129 index++;
130 sibling_element = (Element) matching_elements.item(index);
131 }
132 // 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!
133 return previous_sibling.getNextSibling();
134 }
135 // If not found we just add after last metadata element
136 else {
137 Element last_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
138 return last_element.getNextSibling();
139 }
140 }
141
142 }
143 else {
144 ///ystem.err.println("Not dealing with collection meta.");
145 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
146 // 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)
147 Node sibling_element = matched_element.getNextSibling();
148 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
149 Element newline_element = document.createElement(NEWLINE_ELEMENT);
150 document_element.insertBefore(newline_element, sibling_element);
151 }
152 return sibling_element; // Note that this may be null
153 }
154 }
155 ///ystem.err.println("No matching elements found.");
156 // Locate where this command is in the ordering
157 int command_index = -1;
158 for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
159 if(COMMAND_ORDER[i].equals(target_element_name)) {
160 command_index = i;
161 }
162 }
163 ///ystem.err.println("Command index is: " + command_index);
164 // Now move forward, checking for existing elements in each of the preceeding command orders.
165 int preceeding_index = command_index - 1;
166 ///ystem.err.println("Searching before the target command.");
167 while(preceeding_index >= 0) {
168 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[preceeding_index]);
169 // If we've found a match
170 if(matching_elements.getLength() > 0) {
171 // We add after the last element
172 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
173 // 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)
174 Node sibling_element = matched_element.getNextSibling();
175 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
176 Element newline_element = document.createElement(NEWLINE_ELEMENT);
177 document_element.insertBefore(newline_element, sibling_element);
178 }
179 return sibling_element; // Note that this may be null
180 }
181 preceeding_index--;
182 }
183 // If all that fails, we now move backwards through the commands
184 int susceeding_index = command_index + 1;
185 ///ystem.err.println("Searching after the target command.");
186 while(susceeding_index < COMMAND_ORDER.length) {
187 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[susceeding_index]);
188 // If we've found a match
189 if(matching_elements.getLength() > 0) {
190 // We add before the first element
191 Element matched_element = (Element) matching_elements.item(0);
192 // 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)
193 Node sibling_element = matched_element.getPreviousSibling();
194 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
195 Element newline_element = document.createElement(NEWLINE_ELEMENT);
196 document_element.insertBefore(newline_element, sibling_element);
197 }
198 return sibling_element; // Note that this may be null
199 }
200 susceeding_index++;
201 }
202 // Well. Apparently there are no other commands in this collection configuration. So append away...
203 return null;
204 }
205
206 static public String toString(Element command_element, boolean show_extracted_namespace) {
207 String command_element_name = command_element.getNodeName();
208 if(command_element_name.equals(CLASSIFY_ELEMENT)) {
209 return self.classifyToString(command_element, show_extracted_namespace);
210 }
211 else if(command_element_name.equals(FORMAT_ELEMENT)) {
212 return self.formatToString(command_element, show_extracted_namespace);
213 }
214 else if(command_element_name.equals(INDEXES_ELEMENT)) {
215 return self.indexesToString(command_element, show_extracted_namespace);
216 }
217 else if(command_element_name.equals(INDEX_DEFAULT_ELEMENT)) {
218 return self.indexDefaultToString(command_element, show_extracted_namespace);
219 }
220 else if(command_element_name.equals(LANGUAGES_ELEMENT)) {
221 return self.languagesToString(command_element);
222 }
223 else if(command_element_name.equals(LANGUAGE_DEFAULT_ELEMENT)) {
224 return self.languageDefaultToString(command_element);
225 }
226 else if(command_element_name.equals(LEVELS_ELEMENT)) {
227 return self.levelsToString(command_element);
228 }
229 else if(command_element_name.equals(COLLECTIONMETADATA_ELEMENT)) {
230 return self.metadataToString(command_element, show_extracted_namespace);
231 }
232 else if(command_element_name.equals(COLLECTIONMETADATA_CREATOR_ELEMENT)) {
233 return self.metadataToString(command_element, show_extracted_namespace);
234 }
235 else if(command_element_name.equals(COLLECTIONMETADATA_MAINTAINER_ELEMENT)) {
236 return self.metadataToString(command_element, show_extracted_namespace);
237 }
238 else if(command_element_name.equals(COLLECTIONMETADATA_PUBLIC_ELEMENT)) {
239 return self.metadataToString(command_element, show_extracted_namespace);
240 }
241 // else if(command_element_name.equals(COLLECTIONMETADATA_BETA_ELEMENT)) {
242 // return self.metadataToString(command_element, show_extracted_namespace);
243 // }
244 else if(command_element_name.equals(PLUGIN_ELEMENT)) {
245 return self.pluginToString(command_element, show_extracted_namespace);
246 }
247 else if(command_element_name.equals(SEARCHTYPE_ELEMENT)) {
248 return self.searchtypeToString(command_element);
249 }
250 else if(command_element_name.equals(SUBCOLLECTION_ELEMENT)) {
251 return self.subcollectionToString(command_element, show_extracted_namespace);
252 }
253 else if(command_element_name.equals(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
254 return self.subcollectionDefaultIndexToString(command_element);
255 }
256 else if(command_element_name.equals(SUBCOLLECTION_INDEXES_ELEMENT)) {
257 return self.subcollectionIndexesToString(command_element);
258 }
259 else if(command_element_name.equals(SUPERCOLLECTION_ELEMENT)) {
260 return self.supercollectionToString(command_element);
261 }
262 else if(command_element_name.equals(UNKNOWN_ELEMENT)) {
263 return self.unknownToString(command_element);
264 }
265 return "";
266 }
267
268 /** 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.
269 * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
270 * @return a HashMap containing the arguments parsed
271 */
272 static public HashMap parseArguments(CommandTokenizer tokenizer) {
273 HashMap arguments = new HashMap();
274 String name = null;
275 String value = null;
276 while(tokenizer.hasMoreTokens() || name != null) {
277 // First we retrieve a name if we need one.
278 if(name == null) {
279 name = tokenizer.nextToken();
280 }
281 // Now we attempt to retrieve a value
282 if(tokenizer.hasMoreTokens()) {
283 value = tokenizer.nextToken();
284 // 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.
285 if(value.startsWith(StaticStrings.MINUS_CHARACTER)) {
286 arguments.put(name, null);
287 name = value;
288 }
289 // Otherwise we have a typical name->value pair ready to go
290 else {
291 arguments.put(name, value);
292 name = null;
293 }
294 }
295 // Otherwise its a binary flag
296 else {
297 arguments.put(name, null);
298 name = null;
299 }
300 }
301 return arguments;
302 }
303
304 static private ArrayList known_metadata;
305
306 static private CollectionConfiguration self;
307
308 /** Gives the preferred ordering of commands */
309 static final private String[] COMMAND_ORDER = {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, /* StaticStrings.COLLECTIONMETADATA_BETA_ELEMENT, */ StaticStrings.SEARCHTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.LEVELS_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};
310
311 /** ************************** Public Data Members ***************************/
312
313 /** ************************** Private Data Members ***************************/
314
315 /** Is the configuration file currently being read in one of the infamous G2.39 ones. */
316 private boolean is_twopointthreenine = false;
317 private File collect_config_file;
318
319 /** ************************** Public Methods ***************************/
320
321 public CollectionConfiguration(File collect_config_file) {
322 this.self = this;
323 this.collect_config_file = collect_config_file;
324 // If collect_cfg is xml we can load it straight away
325 String collect_config_name = collect_config_file.getName();
326 if(collect_config_name.equals(COLLECTCONFIGURATION_XML)) {
327 // Parse with Utility but don't use class loader
328 document = Utility.parse(collect_config_file, false);
329 }
330 // Otherwise if this is a legacy collect.cfg file then read in the template and send to magic parser
331 else if(collect_config_name.equals(COLLECT_CFG)) {
332 document = Utility.parse(PSEUDO_COLLECTCONFIGURATION_XML, true);
333 parse(collect_config_file);
334 }
335 }
336
337 /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
338 public void display() {
339 JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false);
340 dialog.setSize(400,400);
341 JPanel content_pane = (JPanel) dialog.getContentPane();
342 final DOMTree tree = new DOMTree(document);
343 JButton refresh_button = new GLIButton("Refresh Tree");
344 refresh_button.setMnemonic(KeyEvent.VK_R);
345 refresh_button.addActionListener(new ActionListener() {
346 public void actionPerformed(ActionEvent event) {
347 tree.setDocument(document);
348 }
349 });
350 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
351 content_pane.setLayout(new BorderLayout());
352 content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
353 content_pane.add(refresh_button, BorderLayout.SOUTH);
354 dialog.show();
355 }
356
357// public Element getBeta() {
358// Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_BETA_ELEMENT, null, null);
359// element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_BETA_STR);
360// element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
361// return element;
362// }
363
364 public Element getCreator() {
365 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
366 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_CREATOR_STR);
367 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
368 return element;
369 }
370
371 public Element getDocumentElement() {
372 return document.getDocumentElement();
373 }
374
375 public File getFile() {
376 return collect_config_file;
377 }
378
379 /** Retrieve or create the languages Element. */
380 public Element getLanguages() {
381 return getOrCreateElementByTagName(LANGUAGES_ELEMENT, null, null);
382 }
383
384 public Element getLevels() {
385 return getOrCreateElementByTagName(LEVELS_ELEMENT, null, null);
386 }
387
388 public Element getMaintainer() {
389 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
390 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_MAINTAINER_STR);
391 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
392 return element;
393 }
394
395 /** Retrieve or create the indexes Element. Note that this method behaves differently from the other getBlah methods, in that it also has to keep in mind that indexes come in two flavours, MG and MGPP. */
396 public Element getMGIndexes() {
397 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, FALSE_STR);
398 }
399
400 public Element getMGPPIndexes() {
401 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, TRUE_STR);
402 }
403
404 public Element getPublic() {
405 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
406 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_PUBLIC_STR);
407 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
408 return element;
409 }
410
411 /** Retrieve or create the searchtype element. */
412 public Element getSearchType() {
413 ///ystem.err.println("Get or create element by tag name: " + name);
414 Element document_element = document.getDocumentElement();
415 NodeList elements = document_element.getElementsByTagName(SEARCHTYPE_ELEMENT);
416 int elements_length = elements.getLength();
417 if(elements_length > 0) {
418 document_element = null;
419 return (Element) elements.item(0);
420 }
421 // Create the element
422 Element element = document.createElement(SEARCHTYPE_ELEMENT);
423 Node target_node = findInsertionPoint(element);
424 if(target_node != null) {
425 document_element.insertBefore(element, target_node);
426 }
427 else {
428 document_element.appendChild(element);
429 }
430 document_element = null;
431 // Append a default search type node - form
432 Element a_searchtype_element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CONTENT_ELEMENT);
433 a_searchtype_element.setAttribute(CollectionConfiguration.NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[0]);
434 element.appendChild(a_searchtype_element);
435 return element;
436 }
437
438 /** Retrieve or create the subindexes Element. */
439 public Element getSubIndexes() {
440 return getOrCreateElementByTagName(SUBCOLLECTION_INDEXES_ELEMENT, null, null);
441 }
442
443 /** Retrieve or create the supercollections Element. */
444 public Element getSuperCollection() {
445 return getOrCreateElementByTagName(SUPERCOLLECTION_ELEMENT, null, null);
446 }
447
448 public boolean ready() {
449 return document != null;
450 }
451
452 public void save() {
453 save(false);
454 }
455
456 public void save(boolean force_xml) {
457 if(collect_config_file.exists()) {
458 File original_file = new File(collect_config_file.getParentFile(), COLLECT_CFG);
459 File backup_file = new File(collect_config_file.getParentFile(), "collect.bak");
460 if(backup_file.exists()) {
461 backup_file.delete();
462 }
463 if(!original_file.renameTo(backup_file)) {
464 Gatherer.println("Can't rename collect.cfg");
465 }
466 }
467 if(force_xml || collect_config_file.getName().equals(COLLECTCONFIGURATION_XML)) {
468 ///ystem.err.println("Writing XML");
469 Utility.export(document, new File(collect_config_file.getParentFile(), COLLECTCONFIGURATION_XML));
470 }
471 else {
472 ///ystem.err.println("Writing text");
473 try {
474 OutputStream ostream = new FileOutputStream(collect_config_file);
475 Writer file_writer = new OutputStreamWriter(ostream, ENCODING);
476 //FileWriter file_writer = new FileWriter(collect_config_file, false);
477 BufferedWriter buffered_writer = new BufferedWriter(file_writer);
478 // 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).
479 // is this still true?? now we are writing all metadata with a lang tag. can we get rid of known_metadata??
480 // Yes we can. Lets see..
481 // known_metadata = new ArrayList(); 'blamo'
482 Element collect_config_element = document.getDocumentElement();
483 NodeList command_elements = collect_config_element.getChildNodes();
484 boolean just_wrote_newline = false; // Prevent two or more newlines in a row
485 for(int i = 0; i < command_elements.getLength(); i++) {
486 Node command_node = command_elements.item(i);
487 if(command_node instanceof Element) {
488 Element command_element = (Element) command_node;
489 // The only thing left are NewLine elements
490 if(command_element.getNodeName().equals(NEWLINE_ELEMENT) && !just_wrote_newline) {
491 buffered_writer.newLine();
492 just_wrote_newline = true;
493 }
494 // Anything else we write to file, but only if it has been assigned, the exception being the Indexes element which just get commented if unassigned (a side effect of MG && MGPP compatibility)
495 else if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR) || command_element.getNodeName().equals(INDEXES_ELEMENT) || command_element.getNodeName().equals(INDEX_DEFAULT_ELEMENT) || command_element.getNodeName().equals(LEVELS_ELEMENT)){
496 String command;
497 // format statements we write out with ex. still present
498 if (command_element.getNodeName().equals(FORMAT_ELEMENT)) {
499 command = toString(command_element, true);
500 } else {
501 command = toString(command_element, false);
502 }
503 if(command != null && command.length() > 0) {
504 write(buffered_writer, command);
505 buffered_writer.newLine();
506 just_wrote_newline = false;
507 }
508 }
509 }
510 }
511 buffered_writer.close();
512 // known_metadata = null; 'poof'
513 }
514 catch (Exception exception) {
515 Gatherer.println("Error in CollectionConfiguration.save(boolean): " + exception);
516 Gatherer.printStackTrace(exception);
517 }
518 }
519 }
520
521 /** ************************** Private Methods ***************************/
522
523 private String classifyToString(Element command_element, boolean show_extracted_namespace)
524 {
525 StringBuffer text = new StringBuffer(CLASSIFY_STR);
526 text.append(TAB_CHARACTER);
527 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
528 text.append(SPACE_CHARACTER);
529 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
530 int option_elements_length = option_elements.getLength();
531 for(int j = 0; j < option_elements_length; j++) {
532 Element option_element = (Element) option_elements.item(j);
533 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
534 text.append(StaticStrings.MINUS_CHARACTER);
535 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
536 String value_str = XMLTools.getValue(option_element);
537
538 // Remove the extracted metadata namespaces if required
539 if (!show_extracted_namespace && value_str.length() > 0) {
540 StringTokenizer string_tokenizer = new StringTokenizer(value_str, ",");
541 value_str = "";
542 while (string_tokenizer.hasMoreElements()) {
543 String token = (String) string_tokenizer.nextElement();
544 if (token.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
545 token = token.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
546 }
547
548 if (!value_str.equals("")) {
549 value_str = value_str + ",";
550 }
551 value_str = value_str + token;
552 }
553 }
554
555 text.append(SPACE_CHARACTER);
556 if (value_str.indexOf(SPACE_CHARACTER) == -1) {
557 text.append(value_str);
558 }
559 else {
560 text.append(SPEECH_CHARACTER);
561 text.append(value_str);
562 text.append(SPEECH_CHARACTER);
563 }
564 value_str = null;
565 if(j < option_elements_length - 1) {
566 text.append(SPACE_CHARACTER);
567 }
568 }
569 option_element = null;
570 }
571 option_elements = null;
572 return text.toString();
573 }
574
575 private String formatToString(Element command_element, boolean show_extracted_namespace) {
576 StringBuffer text = new StringBuffer(FORMAT_STR);
577 text.append(SPACE_CHARACTER);
578 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
579 text.append(SPACE_CHARACTER);
580 String value_str = command_element.getAttribute(VALUE_ATTRIBUTE);
581 if(value_str.length() != 0) {
582 text.append(value_str);
583 }
584 else {
585 // Remember to encode format string to Greenstone specification
586 value_str = Codec.transform(XMLTools.getValue(command_element), Codec.DOM_TO_GREENSTONE);
587 // Remove any references to a namespace for extracted metadata
588 if (!show_extracted_namespace) {
589 String match_string = "\\[" + Utility.EXTRACTED_METADATA_NAMESPACE + "\\.";
590 value_str = value_str.replaceAll(match_string, "[");
591 }
592
593 text.append(SPEECH_CHARACTER);
594 text.append(value_str);
595 text.append(SPEECH_CHARACTER);
596 }
597 value_str = null;
598 return text.toString();
599 }
600
601 /** Retrieve or create the indexes Element. */
602 private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value) {
603 Element document_element = document.getDocumentElement();
604 NodeList elements = document_element.getElementsByTagName(name);
605 int elements_length = elements.getLength();
606 if(elements_length > 0) {
607 if(conditional_attribute == null) {
608 document_element = null;
609 return (Element) elements.item(0);
610 }
611 else {
612 for(int i = 0; i < elements_length; i++) {
613 Element element = (Element) elements.item(i);
614 if(element.getAttribute(conditional_attribute).equals(required_value)) {
615 document_element = null;
616 return element;
617 }
618 element = null;
619 }
620 }
621 }
622 // Create the element
623 Element element = document.createElement(name);
624 // If there was a property set it
625 if(conditional_attribute != null) {
626 element.setAttribute(conditional_attribute, required_value);
627 }
628 Node target_node = findInsertionPoint(element);
629 if(target_node != null) {
630 document_element.insertBefore(element, target_node);
631 }
632 else {
633 document_element.appendChild(element);
634 }
635 document_element = null;
636 return element;
637 }
638
639 private String indexesToString(Element command_element, boolean show_extracted_namespace) {
640 boolean comment_only = false;
641 StringBuffer text = new StringBuffer("");
642 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
643 text.append("#");
644 comment_only = true;
645 }
646 text.append(INDEX_STR);
647 text.append(TAB_CHARACTER);
648 if(!comment_only) {
649 text.append(TAB_CHARACTER);
650 }
651 NodeList index_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
652 if (index_elements.getLength() == 0) { // no indexes
653 return "";
654 }
655 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
656 int index_elements_length = index_elements.getLength();
657 for(int j = 0; j < index_elements_length; j++) {
658 Element index_element = (Element) index_elements.item(j);
659 String level_str = index_element.getAttribute(LEVEL_ATTRIBUTE);
660 if(level_str.length() > 0) {
661 text.append(level_str);
662 text.append(StaticStrings.COLON_CHARACTER);
663 }
664 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT);
665 int content_elements_length = content_elements.getLength();
666 // Don't output anything if no indexes are set
667 if(content_elements_length == 0) {
668 return null;
669 }
670 for(int k = 0; k < content_elements_length; k++) {
671 Element content_element = (Element) content_elements.item(k);
672 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
673 if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
674 name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
675 }
676 text.append(name_str);
677 name_str = null;
678 if(k < content_elements_length - 1) {
679 text.append(StaticStrings.COMMA_CHARACTER);
680 }
681 content_element = null;
682 }
683 if(j < index_elements_length - 1) {
684 text.append(SPACE_CHARACTER);
685 }
686 content_elements = null;
687 index_element = null;
688 }
689 index_elements = null;
690 return text.toString();
691 }
692
693 private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
694 StringBuffer text = new StringBuffer("");
695 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
696 text.append("#");
697 }
698 text.append(INDEX_DEFAULT_STR);
699 text.append(TAB_CHARACTER);
700 text.append(command_element.getAttribute(LEVEL_ATTRIBUTE));
701 text.append(StaticStrings.COLON_CHARACTER);
702 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
703 int content_elements_length = content_elements.getLength();
704 for(int j = 0; j < content_elements_length; j++) {
705 Element content_element = (Element) content_elements.item(j);
706 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
707 if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
708 name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
709 }
710 text.append(name_str);
711 name_str = null;
712 if(j < content_elements_length - 1) {
713 text.append(StaticStrings.COMMA_CHARACTER);
714 }
715 content_element = null;
716 }
717 content_elements = null;
718 return text.toString();
719 }
720
721 private String languagesToString(Element command_element) {
722 StringBuffer text = new StringBuffer(LANGUAGES_STR);
723 text.append(TAB_CHARACTER);
724 // Retrieve all the languages and write them out in a space separated list
725 NodeList language_elements = command_element.getElementsByTagName(LANGUAGE_ELEMENT);
726 int language_elements_length = language_elements.getLength();
727 if(language_elements_length == 0) {
728 return null;
729 }
730 for(int j = 0; j < language_elements_length; j++) {
731 Element language_element = (Element) language_elements.item(j);
732 text.append(language_element.getAttribute(NAME_ATTRIBUTE));
733 if(j < language_elements_length - 1) {
734 text.append(SPACE_CHARACTER);
735 }
736 }
737 return text.toString();
738 }
739
740 private String languageDefaultToString(Element command_element) {
741 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR);
742 text.append(TAB_CHARACTER);
743 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
744 return text.toString();
745 }
746
747 private String levelsToString(Element command_element) {
748 StringBuffer text = new StringBuffer("");
749 if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
750 text.append("#");
751 }
752 text.append(LEVELS_STR);
753 text.append(TAB_CHARACTER);
754 text.append(TAB_CHARACTER);
755 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
756 int content_elements_length = content_elements.getLength();
757 // Don't output anything if no levels are set.
758 if(content_elements_length == 0) {
759 return null;
760 }
761 for(int i = 0; i < content_elements_length; i++) {
762 Element content_element = (Element) content_elements.item(i);
763 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
764 text.append(SPACE_CHARACTER);
765 }
766 return text.substring(0, text.length() - 1);
767 }
768
769 static public String metadataToString(Element command_element, boolean text_value) {
770 boolean special = false;
771 // If there is no value attribute, then we don't write anything
772 StringBuffer text = new StringBuffer("");
773 String name_str = command_element.getAttribute(NAME_ATTRIBUTE);
774 // 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.
775 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
776 text.append(name_str);
777 text.append(TAB_CHARACTER);
778 special = true;
779 }
780 else if (/* name_str.equals(COLLECTIONMETADATA_BETA_STR) || */ name_str.equals(COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
781 text.append(name_str);
782 text.append(TAB_CHARACTER);
783 text.append(TAB_CHARACTER);
784 special = true;
785 }
786 else {
787 text.append(COLLECTIONMETADATA_STR);
788 text.append(TAB_CHARACTER);
789 text.append(name_str);
790 text.append(SPACE_CHARACTER);
791 String language_str = command_element.getAttribute(LANGUAGE_ATTRIBUTE);
792 // If this is element is in english, and it is the first one found, we don't need to write the language argument.
793 //if(!language_str.equals(ENGLISH_LANGUAGE_STR) || known_metadata == null || known_metadata.contains(name_str)) {
794 // changed so that we always write the language string
795 text.append(LBRACKET_CHARACTER);
796 text.append(LANGUAGE_ARGUMENT);
797 text.append(language_str);
798 text.append(RBRACKET_CHARACTER);
799 text.append(SPACE_CHARACTER);
800 //}
801 if(known_metadata != null) {
802 known_metadata.add(name_str);
803 }
804 language_str = null;
805 }
806 name_str = null;
807
808 String value_str = XMLTools.getValue(command_element);
809 // The value string we retrieved will be encoded for xml, so we now decode it - to text if text_value set. This parameter was originally show_extracted_namespace, but sincethis is only true for 'toString()' commands from within the CDM, its good enough to determine if this toString() will be used to display on screen, or write to collect.cfg
810 if(text_value == CollectionMeta.TEXT) {
811 value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT);
812 }
813 else {
814 value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE);
815 }
816
817 // We don't wrap the email addresses in quotes, nor the other special metadata
818 if(special) {
819 text.append(value_str);
820 }
821 else {
822 text.append(SPEECH_CHARACTER);
823 text.append(value_str);
824 text.append(SPEECH_CHARACTER);
825 }
826 value_str = null;
827 return text.toString();
828 }
829
830 /** Parse a collect.cfg into a DOM model representation. */
831 private void parse(File collect_config_file) {
832 try {
833 ArrayList acquired_collectionmeta_names = null;
834 ArrayList obsolete_collectionmeta_names = null;
835 HashMap changed_collectionmeta_names = null;
836
837 // Life is made oh-so-more tricky by the existance of G2.39 config files. There are two ways to handle them:
838 // 1. Notice that the file is G2.39 from the start, then as I parse it magic it into G2.4 standard
839 // 2. Extend the parsing method to handle reading in G2.39, then afterwards go through the DOM changing it to G2.4 as appropriate.
840 // As far as I can tell the second option is twice as much work, so I'll try option 1. The problem here is that I have to determine if the 'buildtype' command is somewhere in the collect.cfg file, which means I'm going to have to read the file twice - once seaching for 'buildtype' and the second time to parse it.
841
842 // Search for 'buildtype mgpp'
843 InputStream input_stream_one = new FileInputStream(collect_config_file);
844 Reader reader_one = new InputStreamReader(input_stream_one, ENCODING);
845 BufferedReader buffered_reader_one = new BufferedReader(reader_one);
846 String search_line_str = null;
847 while(!is_twopointthreenine && (search_line_str = buffered_reader_one.readLine()) != null) {
848 if(search_line_str.toLowerCase().indexOf(BUILDTYPE_STR) != -1) {
849 is_twopointthreenine = true;
850 acquired_collectionmeta_names = new ArrayList();
851 changed_collectionmeta_names = new HashMap();
852 obsolete_collectionmeta_names = new ArrayList();
853 }
854 }
855 buffered_reader_one.close();
856 reader_one.close();
857 input_stream_one.close();
858 buffered_reader_one = null;
859 reader_one = null;
860 input_stream_one = null;
861
862 Element collect_cfg_element = document.getDocumentElement();
863 // Read in the file one command at a time.
864 InputStream istream = new FileInputStream(collect_config_file);
865 Reader in_reader = new InputStreamReader(istream, ENCODING);
866 BufferedReader in = new BufferedReader(in_reader);
867 String command_str = null;
868 while((command_str = in.readLine()) != null) {
869 boolean append_element = true;
870 Element command_element = null;
871 // A command may be broken over several lines.
872 command_str = command_str.trim();
873 boolean eof = false;
874 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) {
875 String next_line = in.readLine();
876 if(next_line != null) {
877 next_line = next_line.trim();
878 if(next_line.length() > 0) {
879 // Remove the new line character
880 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
881 // And append the next line, which due to the test above must be non-zero length
882 command_str = command_str + next_line;
883 }
884 next_line = null;
885 }
886 // If we've reached the end of the file theres nothing more we can do
887 else {
888 eof = true;
889 }
890 }
891 // If there is still a new line character, then we remove it and hope for the best
892 if(command_str.endsWith(NEWLINE_CHARACTER)) {
893 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
894 }
895 // Now we've either got a command to parse...
896 if(command_str.length() != 0) {
897 // Start trying to figure out what it is
898 //StringTokenizer tokenizer = new StringTokenizer(command_str);
899 // Instead of a standard string tokenizer I'm going to use the new version of CommandTokenizer, which is not only smart enough to correctly notice speech marks and correctly parse them out, but now also takes the input stream so it can rebuild tokens that stretch over several lines.
900 CommandTokenizer tokenizer = new CommandTokenizer(command_str, in);
901 String command_type = tokenizer.nextToken().toLowerCase();
902 // 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
903 if(command_element == null && command_type.equals(BUILDTYPE_STR)) {
904 Gatherer.println("G2.39 Buildtype command detected. Ignoring.");
905 command_element = document.createElement(UNKNOWN_ELEMENT);
906 append_element = false;
907 }
908 if(command_element == null && command_type.equals(CLASSIFY_STR)) {
909 command_element = parseClassify(command_str);
910 }
911 if(command_element == null && command_type.equals(FORMAT_STR)) {
912 command_element = parseFormat(tokenizer); // Revised to handle multiple lines
913 }
914 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) {
915 // If this was a G2.39 config file then we manipulate the command string a bit before we submit it to the parser. We start by adding allfields as the first index. We then space separate the remaining indexes, and remove duplicates when encountered. Of course before we do any of that we record the various space separated indexes so that we can remove the collection meta assigned to them.
916 if(is_twopointthreenine) {
917 Gatherer.println("G2.39 Index command detected. Modifying.");
918 Gatherer.println("Before: " + command_str);
919 StringBuffer new_command_str = new StringBuffer(command_type);
920 new_command_str.append(SPACE_CHARACTER);
921 new_command_str.append(ALLFIELDS_STR);
922 new_command_str.append(SPACE_CHARACTER);
923 ArrayList known_indexes = new ArrayList();
924 while(tokenizer.hasMoreTokens()) {
925 String old_index_str = tokenizer.nextToken();
926 // If this index is a combination of sources, then we need to remove the old collectionmeta, split up the compound index, then request new metadata be added for each part
927 if(old_index_str.indexOf(COMMA_CHARACTER) != -1) {
928 obsolete_collectionmeta_names.add(STOP_CHARACTER + old_index_str);
929 StringTokenizer string_tokenizer = new StringTokenizer(old_index_str, COMMA_CHARACTER);
930 while(string_tokenizer.hasMoreTokens()) {
931 String index_fragment_str = string_tokenizer.nextToken();
932 if(!known_indexes.contains(index_fragment_str)) {
933 known_indexes.add(index_fragment_str);
934 new_command_str.append(index_fragment_str);
935 new_command_str.append(SPACE_CHARACTER);
936 acquired_collectionmeta_names.add(STOP_CHARACTER + index_fragment_str);
937 }
938 index_fragment_str = null;
939 }
940 string_tokenizer = null;
941 }
942 // However if this was just a single index then a little choir of angels sing haleluja because we don't have to do -anything-. Nothing at all. Zip. Well no changes anyway. I obviously had to write this comment, and you can probably see, assuming you are not blind, that there are several lines of code below doing something, which is of course not nothing but something. And if we assume you are blind then you probably can't see the code, but then you probably didn't not see it doing the not nothing I said it would above.
943 else {
944 if(!known_indexes.contains(old_index_str)) {
945 known_indexes.add(old_index_str);
946 new_command_str.append(old_index_str);
947 new_command_str.append(SPACE_CHARACTER);
948 }
949 else {
950 // Use the collectionmeta for the single index instead of generating a default one
951 acquired_collectionmeta_names.remove(STOP_CHARACTER + old_index_str);
952 }
953 }
954 old_index_str = null;
955 }
956 known_indexes = null;
957 command_str = new_command_str.toString();
958 new_command_str = null;
959 Gatherer.println("After: " + command_str);
960 }
961 command_element = parseIndex(command_str);
962 }
963 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) {
964
965 command_element = parseIndexDefault(command_str);
966 // If this was a G2.39 config file then we squelch the default index (no such thing in G2.4)
967 if(is_twopointthreenine) {
968 Gatherer.println("G2.39 Default Index command detected. Ignoring.");
969 append_element = false;
970 }
971 }
972 if(command_element == null && command_type.equals(LANGUAGES_STR)) {
973 command_element = parseLanguage(command_str);
974 }
975 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) {
976 command_element = parseLanguageDefault(command_str);
977 }
978 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) {
979 // Again if this is G2.39 we have to do a tiny bit of magic to the levels command. We need to add document level, and change the remainder to lower case.
980 if(is_twopointthreenine) {
981 Gatherer.println("G2.39 Levels command detected. Modifying.");
982 Gatherer.println("Before: " + command_str);
983 StringBuffer new_command_str = new StringBuffer(command_type);
984 new_command_str.append(SPACE_CHARACTER);
985 new_command_str.append(DOCUMENT_STR);
986 while(tokenizer.hasMoreTokens()) {
987 String token = tokenizer.nextToken();
988 // Generate a lower case version
989 String token_lc = token.toLowerCase();
990 // If they are still the same then it is all good baby, otherwise we have to remember to transform their collectionmeta as well
991 if(!token.equals(token_lc)) {
992 changed_collectionmeta_names.put(STOP_CHARACTER + token, STOP_CHARACTER + token_lc);
993 }
994 new_command_str.append(SPACE_CHARACTER);
995 new_command_str.append(token_lc);
996 token_lc = null;
997 token = null;
998 }
999 command_str = new_command_str.toString();
1000 new_command_str = null;
1001 Gatherer.println("After: " + command_str);
1002 }
1003 command_element = parseLevels(command_str);
1004 }
1005 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) {
1006 command_element = parseMetadata(tokenizer); // Revised to handle multiple lines
1007 }
1008 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))) {
1009 command_element = parseMetadataSpecial(command_str);
1010 }
1011 if(command_element == null && command_type.equals(PLUGIN_STR)) {
1012 command_element = parsePlugIn(command_str);
1013 }
1014 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) {
1015 command_element = parseSearchType(command_str);
1016 }
1017 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) {
1018 command_element = parseSubCollection(command_str);
1019 }
1020 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) {
1021 command_element = parseSubCollectionDefaultIndex(command_str);
1022 }
1023 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) {
1024 command_element = parseSubCollectionIndex(command_str);
1025 }
1026 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) {
1027 command_element = parseSuperCollection(command_str);
1028 }
1029 // Doesn't match any known type
1030 command_type = null;
1031 if(command_element == null) {
1032 // No-one knows what to do with this command, so we create an Unknown command element
1033 command_element = document.createElement(UNKNOWN_ELEMENT);
1034 XMLTools.setValue(command_element, command_str);
1035 }
1036 }
1037 // Or an empty line to remember for later
1038 else {
1039 command_element = document.createElement(NEWLINE_ELEMENT);
1040 }
1041 // Now command element shouldn't be null so we append it to the collection config DOM, but only if we haven't been told not to add it
1042 if(append_element) {
1043 collect_cfg_element.appendChild(command_element);
1044 }
1045 }
1046
1047 // We have completed parsing the collect configuration file. Now, if we are dealing with the G2.39 nightmare scenario, it's time to add the SearchType command and modify the collectionmeta commands as necessary.
1048 if(is_twopointthreenine) {
1049 Element search_type_element = getSearchType();
1050 search_type_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1051 while(search_type_element.hasChildNodes()) {
1052 search_type_element.removeChild(search_type_element.getFirstChild());
1053 }
1054 Element plain_search_type_element = document.createElement(CONTENT_ELEMENT);
1055 plain_search_type_element.setAttribute(NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[1]);
1056 search_type_element.appendChild(plain_search_type_element);
1057 plain_search_type_element = null;
1058 Element form_search_type_element = document.createElement(CONTENT_ELEMENT);
1059 form_search_type_element.setAttribute(NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[0]);
1060 search_type_element.appendChild(form_search_type_element);
1061 form_search_type_element = null;
1062 search_type_element = null;
1063
1064 // Search through the existing collectionmeta
1065 Element document_element = document.getDocumentElement();
1066 NodeList collectionmeta_elements = document_element.getElementsByTagName(COLLECTIONMETADATA_ELEMENT);
1067 Gatherer.println("There are " + obsolete_collectionmeta_names.size() + " collectionmeta to remove.");
1068 Gatherer.println("There are " + changed_collectionmeta_names.size() + " collectionmeta to change.");
1069 for(int z = collectionmeta_elements.getLength(); z > 0; z--) {
1070 Element collectionmeta_element = (Element) collectionmeta_elements.item(z - 1);
1071 String name = collectionmeta_element.getAttribute(NAME_ATTRIBUTE);
1072 Gatherer.println("Checking " + name);
1073 // Remove any obsolete metadata
1074 if(obsolete_collectionmeta_names.contains(name)) {
1075 Gatherer.println("G2.39 CollectMeta detected. Removing: " + name);
1076 document_element.removeChild(collectionmeta_element);
1077 }
1078 // We may have been asked to change the index name to lower case
1079 else if(changed_collectionmeta_names.containsKey(name)) {
1080 String new_name = (String) changed_collectionmeta_names.get(name);
1081 Gatherer.println("G2.39 CollectMeta detected. Changing: " + name + " -> " + new_name);
1082 collectionmeta_element.setAttribute(NAME_ATTRIBUTE, new_name);
1083 new_name = null;
1084 }
1085 name = null;
1086 }
1087
1088 // Finally add any newly acquired collectionmeta. This general defaults to the collectionmeta name less the full stop
1089 Gatherer.println("There are " + acquired_collectionmeta_names.size() + " collectionmeta to add.");
1090 for(int y = 0; y < acquired_collectionmeta_names.size(); y++) {
1091 String name = (String) acquired_collectionmeta_names.get(y);
1092 String value = name.substring(1);
1093 Gatherer.println("G2.39 CollectMeta missing. Adding: " + name + " [l=" + Gatherer.config.getLanguage() + "] \"" + value + "\"");
1094 Element element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1095 element.setAttribute(NAME_ATTRIBUTE, name);
1096 element.setAttribute(LANGUAGE_ATTRIBUTE, Gatherer.config.getLanguage());
1097 element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1098 XMLTools.setValue(element, value);
1099 document_element.appendChild(element);
1100 element = null;
1101 value = null;
1102 name = null;
1103 }
1104
1105 document_element = null;
1106 }
1107 }
1108 catch(Exception exception) {
1109 Gatherer.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
1110 Gatherer.printStackTrace(exception);
1111 }
1112 }
1113
1114 private Element parseClassify(String command_str) {
1115 Element command_element = null;
1116 try {
1117 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1118 // 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).
1119 if(tokenizer.countTokens() >= 2) { // Must support "classify Phind" (no args)
1120 command_element = document.createElement(CLASSIFY_ELEMENT);
1121 // First token is classify
1122 tokenizer.nextToken();
1123 // The next token is the classifier type
1124 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
1125 // Now we parse out the remaining arguments into a hashmapping from name to value
1126 HashMap arguments = parseArguments(tokenizer);
1127 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1128 Iterator names = arguments.keySet().iterator();
1129 while(names.hasNext()) {
1130 String name = (String) names.next();
1131 String value = (String) arguments.get(name); // Can be null
1132 // The metadata argument gets added as the content attribute
1133 if (name.equals(METADATA_ARGUMENT) && value != null) {
1134 // Add the extracted namespace onto un-namespaced metadata names
1135 StringTokenizer string_tokenizer = new StringTokenizer(value, ",");
1136 value = "";
1137 while (string_tokenizer.hasMoreElements()) {
1138 String token = (String) string_tokenizer.nextElement();
1139 if (token.indexOf(StaticStrings.NS_SEP) == -1) {
1140 token = StaticStrings.EXTRACTED_NAMESPACE + token;
1141 }
1142
1143 if (!value.equals("")) {
1144 value = value + ",";
1145 }
1146 value = value + token;
1147 }
1148 }
1149 // Everything else is an Option Element
1150 Element option_element = document.createElement(OPTION_ELEMENT);
1151 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1152 if(value != null) {
1153 // Remove any speech marks appended in strings containing whitespace
1154 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1155 value = value.substring(1, value.length() - 1);
1156 }
1157 XMLTools.setValue(option_element, value);
1158 }
1159 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1160 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1161 command_element.appendChild(option_element);
1162 option_element = null;
1163 name = null;
1164 value = null;
1165 }
1166 names = null;
1167 arguments = null;
1168 }
1169 tokenizer = null;
1170 }
1171 catch(Exception error) {
1172 }
1173 return command_element;
1174 }
1175
1176 private Element parseFormat(CommandTokenizer tokenizer) {
1177 Element command_element = null;
1178 try {
1179 command_element = document.createElement(FORMAT_ELEMENT);
1180 String name_str = tokenizer.nextToken();
1181 String value_str = tokenizer.nextToken();
1182 if(name_str != null && value_str != null) {
1183 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1184 // If the value is true or false we add it as an attribute
1185 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
1186 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
1187 }
1188 // Otherwise it gets added as a text node
1189 else {
1190 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1191 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1192 XMLTools.setValue(command_element, value_str);
1193 }
1194 }
1195 else {
1196 command_element = null;
1197 }
1198 name_str = null;
1199 value_str = null;
1200 }
1201 catch (Exception exception) {
1202 Gatherer.printStackTrace(exception);
1203 command_element = null;
1204 }
1205 return command_element;
1206 }
1207
1208 private Element parseIndex(String command_str) {
1209 Element command_element = null;
1210 try {
1211 StringTokenizer tokenizer = new StringTokenizer(command_str);
1212 String command = tokenizer.nextToken();
1213 command_element = document.createElement(INDEXES_ELEMENT);
1214 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1215 command = null;
1216 if(!tokenizer.hasMoreTokens()) {
1217
1218 // there are no indexes
1219 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1220 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1221 tokenizer = null;
1222 return command_element;
1223 }
1224
1225 while(tokenizer.hasMoreTokens()) {
1226 Element index_element = document.createElement(INDEX_ELEMENT);
1227 String index_str = tokenizer.nextToken();
1228 // There are two types of index we have to consider. Old G2.38 and earlier use level:source tuplets while G2.39+ have just a single, non-comma separated list where order is important.
1229 boolean old_index;
1230 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1231 old_index = true;
1232 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1233 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1234 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1235 }
1236 else {
1237 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1238 old_index = false;
1239 }
1240 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1241 while(content_tokenizer.hasMoreTokens()) {
1242 Element content_element = document.createElement(CONTENT_ELEMENT);
1243 String content_str = content_tokenizer.nextToken();
1244 // 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.
1245 if(content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1246 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1247 // Our special strings are OK.
1248 }
1249 else {
1250 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1251 }
1252 }
1253 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1254 index_element.appendChild(content_element);
1255 content_element = null;
1256 }
1257 content_tokenizer = null;
1258 index_str = null;
1259 command_element.appendChild(index_element);
1260 index_element = null;
1261 }
1262 tokenizer = null;
1263 }
1264 catch (Exception exception) {
1265 exception.printStackTrace();
1266 }
1267 return command_element;
1268 }
1269
1270 private Element parseIndexDefault(String command_str) {
1271 Element command_element = null;
1272 try {
1273 StringTokenizer tokenizer = new StringTokenizer(command_str);
1274 if(tokenizer.countTokens() >= 2) {
1275 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1276 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1277 String index_str = tokenizer.nextToken();
1278 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1279 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1280 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1281 while(content_tokenizer.hasMoreTokens()) {
1282 Element content_element = document.createElement(CONTENT_ELEMENT);
1283 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1284 command_element.appendChild(content_element);
1285 content_element = null;
1286 }
1287 content_tokenizer = null;
1288 content_str = null;
1289 content_str = null;
1290 index_str = null;
1291 }
1292 tokenizer = null;
1293 }
1294 catch (Exception exception) {
1295 }
1296 return command_element;
1297 }
1298
1299 private Element parseLanguage(String command_str) {
1300 Element command_element = null;
1301 try {
1302 StringTokenizer tokenizer = new StringTokenizer(command_str);
1303 tokenizer.nextToken();
1304 if(tokenizer.hasMoreTokens()) {
1305 command_element = document.createElement(LANGUAGES_ELEMENT);
1306 while(tokenizer.hasMoreTokens()) {
1307 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1308 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1309 command_element.appendChild(language_element);
1310 language_element = null;
1311 }
1312 }
1313 tokenizer = null;
1314 }
1315 catch (Exception exception) {
1316 }
1317 return command_element;
1318 }
1319
1320 private Element parseLanguageDefault(String command_str) {
1321 Element command_element = null;
1322 try {
1323 StringTokenizer tokenizer = new StringTokenizer(command_str);
1324 if(tokenizer.countTokens() >= 2) {
1325 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1326 tokenizer.nextToken();
1327 String default_language_str = tokenizer.nextToken();
1328 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1329 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1330 default_language_str = null;
1331 }
1332 tokenizer = null;
1333 }
1334 catch (Exception exception) {
1335 }
1336 return command_element;
1337 }
1338
1339 private Element parseLevels(String command_str) {
1340 Element command_element = null;
1341 try {
1342 StringTokenizer tokenizer = new StringTokenizer(command_str);
1343 // First token is command type (levels)
1344 String command = tokenizer.nextToken();
1345 if(tokenizer.hasMoreTokens()) {
1346 command_element = document.createElement(LEVELS_ELEMENT);
1347 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1348 while(tokenizer.hasMoreTokens()) {
1349 Element level_element = document.createElement(CONTENT_ELEMENT);
1350 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1351 command_element.appendChild(level_element);
1352 level_element = null;
1353 }
1354 }
1355 command = null;
1356 }
1357 catch(Exception exception) {
1358 }
1359 return command_element;
1360 }
1361
1362 private Element parseMetadata(CommandTokenizer tokenizer) {
1363 Element command_element = null;
1364 try {
1365 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1366 String name_str = tokenizer.nextToken();
1367 String value_str = tokenizer.nextToken();
1368 if(name_str != null && value_str != null) {
1369 String language_str = Gatherer.config.getLanguage();
1370 // Check if the value string is actually a language string
1371 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1372 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1373 value_str = tokenizer.nextToken();
1374 }
1375 if(value_str != null) {
1376 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1377 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1378 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1379 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1380 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1381 XMLTools.setValue(command_element, value_str);
1382 }
1383 else {
1384 command_element = null;
1385 }
1386 language_str = null;
1387 }
1388 else {
1389 command_element = null;
1390 }
1391 name_str = null;
1392 value_str = null;
1393 }
1394 catch (Exception exception) {
1395 Gatherer.printStackTrace(exception);
1396 command_element = null;
1397 }
1398 return command_element;
1399 }
1400
1401 private Element parseMetadataSpecial(String command_str) {
1402 Element command_element = null;
1403 try {
1404 StringTokenizer tokenizer = new StringTokenizer(command_str);
1405 if(tokenizer.countTokens() >= 2) {
1406 String name_str = tokenizer.nextToken();
1407 String value_str = tokenizer.nextToken();
1408 // if(name_str.equals(COLLECTIONMETADATA_BETA_STR)) {
1409 // command_element = document.createElement(COLLECTIONMETADATA_BETA_ELEMENT);
1410 // }
1411 if (name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1412 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1413 }
1414 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1415 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1416 }
1417 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1418 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1419 }
1420 if(command_element != null) {
1421 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1422 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1423 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1424 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1425 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1426 value_str = value_str.substring(1, value_str.length() - 1);
1427 }
1428 XMLTools.setValue(command_element, value_str);
1429 }
1430 value_str = null;
1431 name_str = null;
1432 }
1433 tokenizer = null;
1434 }
1435 catch (Exception exception) {
1436 }
1437 return command_element;
1438 }
1439
1440 private Element parsePlugIn(String command_str) {
1441 Element command_element = null;
1442 boolean use_metadata_files = false;
1443 try {
1444 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1445 // 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).
1446 if(tokenizer.countTokens() >= 2) {
1447 command_element = document.createElement(PLUGIN_ELEMENT);
1448 // First token is plugin
1449 tokenizer.nextToken();
1450 // The next token is the type
1451 String type = tokenizer.nextToken();
1452 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1453 // Now we parse out the remaining arguments into a hashmapping from name to value
1454 HashMap arguments = parseArguments(tokenizer);
1455 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1456 Iterator names = arguments.keySet().iterator();
1457 while(names.hasNext()) {
1458 String name = (String) names.next();
1459 String value = (String) arguments.get(name); // Can be null
1460 Element option_element = document.createElement(OPTION_ELEMENT);
1461 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1462 use_metadata_files = true;
1463 }
1464 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1465 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1466 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1467 if(value != null) {
1468 // Remove any speech marks appended in strings containing whitespace
1469 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1470 value = value.substring(1, value.length() - 1);
1471 }
1472 if(name.equals(METADATA_ARGUMENT)) {
1473 // 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.
1474 if(value.indexOf(StaticStrings.NS_SEP) == -1) {
1475 value = StaticStrings.EXTRACTED_NAMESPACE + value;
1476 }
1477 }
1478 XMLTools.setValue(option_element, value);
1479 }
1480 command_element.appendChild(option_element);
1481 option_element = null;
1482 name = null;
1483 value = null;
1484 }
1485
1486 // We must have some RecPlug options: use_metadata_files, and show_progress
1487 if (type.equals(RECPLUG_STR)) {
1488 if (!use_metadata_files) {
1489 Element option_element = document.createElement(OPTION_ELEMENT);
1490 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1491 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1492 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1493 command_element.appendChild(option_element);
1494 option_element = null;
1495 }
1496 }
1497 type = null;
1498 names = null;
1499 arguments = null;
1500 }
1501 tokenizer = null;
1502 }
1503 catch(Exception exception) {
1504 }
1505 return command_element;
1506 }
1507
1508 private Element parseSearchType(String command_str) {
1509 Element command_element = null;
1510 try {
1511 StringTokenizer tokenizer = new StringTokenizer(command_str);
1512 // First token is command type (levels)
1513 tokenizer.nextToken();
1514 if(tokenizer.hasMoreTokens()) {
1515 command_element = document.createElement(SEARCHTYPE_ELEMENT);
1516 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1517 while(tokenizer.hasMoreTokens()) {
1518 Element search_element = document.createElement(CONTENT_ELEMENT);
1519 search_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1520 command_element.appendChild(search_element);
1521 search_element = null;
1522 }
1523 }
1524 }
1525 catch(Exception exception) {
1526 }
1527 return command_element;
1528 }
1529
1530 private Element parseSubCollection(String command_str) {
1531 Element command_element = null;
1532 try {
1533 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1534 if(tokenizer.countTokens() >= 3) {
1535 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1536 // First token is command type
1537 tokenizer.nextToken();
1538 // Then subcollection identifier
1539 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1540 // Then finally the pattern used to build the subcollection partition
1541 String full_pattern_str = tokenizer.nextToken();
1542 // To make life easier I'm going to parse this up now.
1543 boolean exclusion = (full_pattern_str.substring(1, 2).equals(EXCLAMATION_CHARACTER));
1544 // Set inclusion/exclusion flag, remove any exclaimation mark and the speech marks
1545 if(exclusion) {
1546 full_pattern_str = full_pattern_str.substring(2, full_pattern_str.length() - 1);
1547 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1548 }
1549 else {
1550 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length() - 1);
1551 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1552 }
1553 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1554 if(pattern_tokenizer.countTokens() >= 2) {
1555 String content_str = pattern_tokenizer.nextToken();
1556 // 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.
1557 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1558 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1559 }
1560 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1561 XMLTools.setValue(command_element, pattern_tokenizer.nextToken());
1562 if(pattern_tokenizer.hasMoreTokens()) {
1563 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1564 }
1565 }
1566 pattern_tokenizer = null;
1567 }
1568 }
1569 catch(Exception exception) {
1570 exception.printStackTrace();
1571 }
1572 return command_element;
1573 }
1574
1575 private Element parseSubCollectionDefaultIndex(String command_str) {
1576 Element command_element = null;
1577 try {
1578 StringTokenizer tokenizer = new StringTokenizer(command_str);
1579 if(tokenizer.countTokens() == 2) {
1580 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1581 tokenizer.nextToken();
1582 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1583 String content_str = tokenizer.nextToken();
1584 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1585 while(content_tokenizer.hasMoreTokens()) {
1586 Element content_element = document.createElement(CONTENT_ELEMENT);
1587 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1588 command_element.appendChild(content_element);
1589 content_element = null;
1590 }
1591 content_tokenizer = null;
1592 content_str = null;
1593 }
1594 tokenizer = null;
1595 }
1596 catch(Exception exception) {
1597 }
1598 return command_element;
1599 }
1600
1601 private Element parseSubCollectionIndex(String command_str) {
1602 Element command_element = null;
1603 try {
1604 StringTokenizer tokenizer = new StringTokenizer(command_str);
1605 tokenizer.nextToken();
1606 if(tokenizer.hasMoreTokens()) {
1607 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1608 }
1609 while(tokenizer.hasMoreTokens()) {
1610 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1611 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1612 String content_str = tokenizer.nextToken();
1613 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1614 while(content_tokenizer.hasMoreTokens()) {
1615 Element content_element = document.createElement(CONTENT_ELEMENT);
1616 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1617 subcollectionindex_element.appendChild(content_element);
1618 content_element = null;
1619 }
1620 content_tokenizer = null;
1621 content_str = null;
1622 command_element.appendChild(subcollectionindex_element);
1623 subcollectionindex_element = null;
1624 }
1625 tokenizer = null;
1626 }
1627 catch (Exception exception) {
1628 }
1629 return command_element;
1630 }
1631
1632 private Element parseSuperCollection(String command_str) {
1633 Element command_element = null;
1634 try {
1635 StringTokenizer tokenizer = new StringTokenizer(command_str);
1636 if(tokenizer.countTokens() >= 3) {
1637 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1638 tokenizer.nextToken();
1639 while(tokenizer.hasMoreTokens()) {
1640 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1641 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1642 command_element.appendChild(collection_element);
1643 collection_element = null;
1644 }
1645 }
1646 tokenizer = null;
1647 }
1648 catch(Exception exception) {
1649 }
1650 return command_element;
1651 }
1652
1653 private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1654 StringBuffer text = new StringBuffer();
1655 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1656 text.append(PLUGIN_STR);
1657 text.append(TAB_CHARACTER);
1658 text.append(TAB_CHARACTER);
1659 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1660 // Retrieve, and output, the arguments
1661 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1662 int option_elements_length = option_elements.getLength();
1663 if(option_elements_length > 0) {
1664 text.append(SPACE_CHARACTER);
1665 for(int j = 0; j < option_elements_length; j++) {
1666 Element option_element = (Element) option_elements.item(j);
1667 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1668 text.append(StaticStrings.MINUS_CHARACTER);
1669 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1670 String value_str = XMLTools.getValue(option_element);
1671 if(!show_extracted_namespace && value_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1672 value_str = value_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1673 }
1674 if(value_str.length() > 0) {
1675 text.append(SPACE_CHARACTER);
1676 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1677 text.append(value_str);
1678 }
1679 else {
1680 text.append(SPEECH_CHARACTER);
1681 text.append(value_str);
1682 text.append(SPEECH_CHARACTER);
1683 }
1684 }
1685 value_str = null;
1686 if(j < option_elements_length - 1) {
1687 text.append(SPACE_CHARACTER);
1688 }
1689 }
1690 option_element = null;
1691 }
1692 }
1693 option_elements = null;
1694 }
1695 return text.toString();
1696 }
1697
1698 private String searchtypeToString(Element command_element) {
1699 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1700 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1701 text.append(TAB_CHARACTER);
1702 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1703 int search_elements_length = search_elements.getLength();
1704 for(int i = 0; i < search_elements_length; i++) {
1705 Element search_element = (Element) search_elements.item(i);
1706 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1707 text.append(SPACE_CHARACTER);
1708 }
1709 return text.substring(0, text.length() - 1);
1710 }
1711 else {
1712 return null;
1713 }
1714 }
1715
1716 private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1717 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1718 text.append(SPACE_CHARACTER);
1719 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1720 text.append(SPACE_CHARACTER);
1721 text.append(TAB_CHARACTER);
1722 text.append(SPEECH_CHARACTER);
1723 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1724 text.append(EXCLAMATION_CHARACTER);
1725 }
1726 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1727 if(!show_extracted_namespace && content_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1728 content_str = content_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1729 }
1730 text.append(content_str);
1731 content_str = null;
1732 text.append(SEPARATOR_CHARACTER);
1733 text.append(XMLTools.getValue(command_element));
1734 text.append(SEPARATOR_CHARACTER);
1735 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1736 if(options_str.length() > 0) {
1737 text.append(options_str);
1738 }
1739 options_str = null;
1740 text.append(SPEECH_CHARACTER);
1741 return text.toString();
1742 }
1743
1744 private String subcollectionDefaultIndexToString(Element command_element) {
1745 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1746 text.append(TAB_CHARACTER);
1747 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1748 int content_elements_length = content_elements.getLength();
1749 for(int j = 0; j < content_elements_length; j++) {
1750 Element content_element = (Element) content_elements.item(j);
1751 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1752 if(j < content_elements_length - 1) {
1753 text.append(StaticStrings.COMMA_CHARACTER);
1754 }
1755 }
1756 return text.toString();
1757 }
1758
1759 private String subcollectionIndexesToString(Element command_element) {
1760 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1761 text.append(TAB_CHARACTER);
1762 // Retrieve all of the subcollection index partitions
1763 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1764 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1765 if(subcollectionindex_elements_length == 0) {
1766 return null;
1767 }
1768 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1769 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1770 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1771 int content_elements_length = content_elements.getLength();
1772 for(int k = 0; k < content_elements_length; k++) {
1773 Element content_element = (Element) content_elements.item(k);
1774 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1775 if(k < content_elements_length - 1) {
1776 text.append(StaticStrings.COMMA_CHARACTER);
1777 }
1778 }
1779 if(j < subcollectionindex_elements_length - 1) {
1780 text.append(SPACE_CHARACTER);
1781 }
1782 }
1783 return text.toString();
1784 }
1785
1786 private String supercollectionToString(Element command_element) {
1787 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1788 int content_elements_length = content_elements.getLength();
1789 if(content_elements_length > 1) {
1790 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1791 text.append(TAB_CHARACTER);
1792 for(int j = 0; j < content_elements_length; j++) {
1793 Element content_element = (Element) content_elements.item(j);
1794 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1795 if(j < content_elements_length - 1) {
1796 text.append(SPACE_CHARACTER);
1797 }
1798 }
1799 return text.toString();
1800 }
1801 return null;
1802 }
1803
1804 private String unknownToString(Element command_element) {
1805 return XMLTools.getValue(command_element);
1806 }
1807
1808 /** 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.
1809 * @param writer the BufferedWriter to which the str will be written
1810 * @param str the String to be written
1811 */
1812 private void write(BufferedWriter writer, String str)
1813 throws IOException {
1814 writer.write(str, 0, str.length());
1815 }
1816}
Note: See TracBrowser for help on using the repository browser.