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

Last change on this file since 7224 was 6852, checked in by mdewsnip, 20 years ago

Fixed up tabbing.

  • Property svn:keywords set to Author Date Id Revision
File size: 77.1 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.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.msm.MSMUtils;
38import org.greenstone.gatherer.util.DOMTree;
39import org.greenstone.gatherer.util.Codec;
40import org.greenstone.gatherer.util.StaticStrings;
41import org.greenstone.gatherer.util.Utility;
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 static final private String EXTRACTED_PREFIX = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP;
309 /** Gives the preferred ordering of commands */
310 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};
311
312 /** ************************** Public Data Members ***************************/
313
314 /** ************************** Private Data Members ***************************/
315
316 /** Is the configuration file currently being read in one of the infamous G2.39 ones. */
317 private boolean is_twopointthreenine = false;
318 private File collect_config_file;
319
320 /** ************************** Public Methods ***************************/
321
322 public CollectionConfiguration(File collect_config_file) {
323 this.self = this;
324 this.collect_config_file = collect_config_file;
325 // If collect_cfg is xml we can load it straight away
326 String collect_config_name = collect_config_file.getName();
327 if(collect_config_name.equals(COLLECTCONFIGURATION_XML)) {
328 // Parse with Utility but don't use class loader
329 document = Utility.parse(collect_config_file, false);
330 }
331 // Otherwise if this is a legacy collect.cfg file then read in the template and send to magic parser
332 else if(collect_config_name.equals(COLLECT_CFG)) {
333 document = Utility.parse(PSEUDO_COLLECTCONFIGURATION_XML, true);
334 parse(collect_config_file);
335 }
336 }
337
338 /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
339 public void display() {
340 JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false);
341 dialog.setSize(400,400);
342 JPanel content_pane = (JPanel) dialog.getContentPane();
343 final DOMTree tree = new DOMTree(document);
344 JButton refresh_button = new GLIButton("Refresh Tree");
345 refresh_button.setMnemonic(KeyEvent.VK_R);
346 refresh_button.addActionListener(new ActionListener() {
347 public void actionPerformed(ActionEvent event) {
348 tree.setDocument(document);
349 }
350 });
351 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
352 content_pane.setLayout(new BorderLayout());
353 content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
354 content_pane.add(refresh_button, BorderLayout.SOUTH);
355 dialog.show();
356 }
357
358 public Element getBeta() {
359 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_BETA_ELEMENT, null, null);
360 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_BETA_STR);
361 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
362 return element;
363 }
364
365 public Element getCreator() {
366 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
367 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_CREATOR_STR);
368 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
369 return element;
370 }
371
372 public Element getDocumentElement() {
373 return document.getDocumentElement();
374 }
375
376 public File getFile() {
377 return collect_config_file;
378 }
379
380 /** Retrieve or create the languages Element. */
381 public Element getLanguages() {
382 return getOrCreateElementByTagName(LANGUAGES_ELEMENT, null, null);
383 }
384
385 public Element getLevels() {
386 return getOrCreateElementByTagName(LEVELS_ELEMENT, null, null);
387 }
388
389 public Element getMaintainer() {
390 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
391 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_MAINTAINER_STR);
392 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
393 return element;
394 }
395
396 /** 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. */
397 public Element getMGIndexes() {
398 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, FALSE_STR);
399 }
400
401 public Element getMGPPIndexes() {
402 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, TRUE_STR);
403 }
404
405 public Element getPublic() {
406 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
407 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_PUBLIC_STR);
408 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
409 return element;
410 }
411
412 /** Retrieve or create the searchtype element. */
413 public Element getSearchType() {
414 ///ystem.err.println("Get or create element by tag name: " + name);
415 Element document_element = document.getDocumentElement();
416 NodeList elements = document_element.getElementsByTagName(SEARCHTYPE_ELEMENT);
417 int elements_length = elements.getLength();
418 if(elements_length > 0) {
419 document_element = null;
420 return (Element) elements.item(0);
421 }
422 // Create the element
423 Element element = document.createElement(SEARCHTYPE_ELEMENT);
424 Node target_node = findInsertionPoint(element);
425 if(target_node != null) {
426 document_element.insertBefore(element, target_node);
427 }
428 else {
429 document_element.appendChild(element);
430 }
431 document_element = null;
432 // Append a default search type node - form
433 Element a_searchtype_element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CONTENT_ELEMENT);
434 a_searchtype_element.setAttribute(CollectionConfiguration.NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[0]);
435 element.appendChild(a_searchtype_element);
436 return element;
437 }
438
439 /** Retrieve or create the subindexes Element. */
440 public Element getSubIndexes() {
441 return getOrCreateElementByTagName(SUBCOLLECTION_INDEXES_ELEMENT, null, null);
442 }
443
444 /** Retrieve or create the supercollections Element. */
445 public Element getSuperCollection() {
446 return getOrCreateElementByTagName(SUPERCOLLECTION_ELEMENT, null, null);
447 }
448
449 public boolean ready() {
450 return document != null;
451 }
452
453 public void save() {
454 save(false);
455 }
456
457 public void save(boolean force_xml) {
458 if(collect_config_file.exists()) {
459 File original_file = new File(collect_config_file.getParentFile(), COLLECT_CFG);
460 File backup_file = new File(collect_config_file.getParentFile(), "collect.bak");
461 if(backup_file.exists()) {
462 backup_file.delete();
463 }
464 if(!original_file.renameTo(backup_file)) {
465 Gatherer.println("Can't rename collect.cfg");
466 }
467 }
468 if(force_xml || collect_config_file.getName().equals(COLLECTCONFIGURATION_XML)) {
469 ///ystem.err.println("Writing XML");
470 Utility.export(document, new File(collect_config_file.getParentFile(), COLLECTCONFIGURATION_XML));
471 }
472 else {
473 ///ystem.err.println("Writing text");
474 try {
475 OutputStream ostream = new FileOutputStream(collect_config_file);
476 Writer file_writer = new OutputStreamWriter(ostream, ENCODING);
477 //FileWriter file_writer = new FileWriter(collect_config_file, false);
478 BufferedWriter buffered_writer = new BufferedWriter(file_writer);
479 // 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).
480 // is this still true?? now we are writing all metadata with a lang tag. can we get rid of known_metadata??
481 // Yes we can. Lets see..
482 // known_metadata = new ArrayList(); 'blamo'
483 Element collect_config_element = document.getDocumentElement();
484 NodeList command_elements = collect_config_element.getChildNodes();
485 boolean just_wrote_newline = false; // Prevent two or more newlines in a row
486 for(int i = 0; i < command_elements.getLength(); i++) {
487 Node command_node = command_elements.item(i);
488 if(command_node instanceof Element) {
489 Element command_element = (Element) command_node;
490 // The only thing left are NewLine elements
491 if(command_element.getNodeName().equals(NEWLINE_ELEMENT) && !just_wrote_newline) {
492 buffered_writer.newLine();
493 just_wrote_newline = true;
494 }
495 // 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)
496 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)){
497 String command = toString(command_element, false);
498 if(command != null && command.length() > 0) {
499 write(buffered_writer, command);
500 buffered_writer.newLine();
501 just_wrote_newline = false;
502 }
503 }
504 }
505 }
506 buffered_writer.close();
507 // known_metadata = null; 'poof'
508 }
509 catch (Exception exception) {
510 Gatherer.println("Error in CollectionConfiguration.save(boolean): " + exception);
511 Gatherer.printStackTrace(exception);
512 }
513 }
514 }
515
516 /** ************************** Private Methods ***************************/
517
518 private String classifyToString(Element command_element, boolean show_extracted_namespace) {
519 StringBuffer text = new StringBuffer(CLASSIFY_STR);
520 text.append(TAB_CHARACTER);
521 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
522 text.append(SPACE_CHARACTER);
523 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
524 int option_elements_length = option_elements.getLength();
525 for(int j = 0; j < option_elements_length; j++) {
526 Element option_element = (Element) option_elements.item(j);
527 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
528 text.append(StaticStrings.MINUS_CHARACTER);
529 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
530 String value_str = MSMUtils.getValue(option_element);
531 if(value_str.length() > 0) {
532 // If the value happens to be the identifier of an extracted metadata element, then remove the namespace.
533 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) {
534 value_str = value_str.substring(EXTRACTED_PREFIX.length());
535 }
536 text.append(SPACE_CHARACTER);
537 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
538 text.append(value_str);
539 }
540 else {
541 text.append(SPEECH_CHARACTER);
542 text.append(value_str);
543 text.append(SPEECH_CHARACTER);
544 }
545 }
546 value_str = null;
547 if(j < option_elements_length - 1) {
548 text.append(SPACE_CHARACTER);
549 }
550 }
551 option_element = null;
552 }
553 option_elements = null;
554 return text.toString();
555 }
556
557 private String formatToString(Element command_element, boolean show_extracted_namespace) {
558 StringBuffer text = new StringBuffer(FORMAT_STR);
559 text.append(SPACE_CHARACTER);
560 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
561 text.append(SPACE_CHARACTER);
562 String value_str = command_element.getAttribute(VALUE_ATTRIBUTE);
563 if(value_str.length() != 0) {
564 text.append(value_str);
565 }
566 else {
567 // Remember to encode format string to Greenstone specification
568 value_str = Codec.transform(MSMUtils.getValue(command_element), Codec.DOM_TO_GREENSTONE);
569 // Remove any references to a namespace for extracted metadata
570 if(!show_extracted_namespace) {
571 value_str.replaceAll(EXTRACTED_PREFIX, "");
572 }
573 text.append(SPEECH_CHARACTER);
574 text.append(value_str);
575 text.append(SPEECH_CHARACTER);
576 }
577 value_str = null;
578 return text.toString();
579 }
580
581 /** Retrieve or create the indexes Element. */
582 private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value) {
583 Element document_element = document.getDocumentElement();
584 NodeList elements = document_element.getElementsByTagName(name);
585 int elements_length = elements.getLength();
586 if(elements_length > 0) {
587 if(conditional_attribute == null) {
588 document_element = null;
589 return (Element) elements.item(0);
590 }
591 else {
592 for(int i = 0; i < elements_length; i++) {
593 Element element = (Element) elements.item(i);
594 if(element.getAttribute(conditional_attribute).equals(required_value)) {
595 document_element = null;
596 return element;
597 }
598 element = null;
599 }
600 }
601 }
602 // Create the element
603 Element element = document.createElement(name);
604 // If there was a property set it
605 if(conditional_attribute != null) {
606 element.setAttribute(conditional_attribute, required_value);
607 }
608 Node target_node = findInsertionPoint(element);
609 if(target_node != null) {
610 document_element.insertBefore(element, target_node);
611 }
612 else {
613 document_element.appendChild(element);
614 }
615 document_element = null;
616 return element;
617 }
618
619 private String indexesToString(Element command_element, boolean show_extracted_namespace) {
620 boolean comment_only = false;
621 StringBuffer text = new StringBuffer("");
622 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
623 text.append("#");
624 comment_only = true;
625 }
626 text.append(INDEX_STR);
627 text.append(TAB_CHARACTER);
628 if(!comment_only) {
629 text.append(TAB_CHARACTER);
630 }
631 NodeList index_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
632 if (index_elements.getLength() == 0) { // no indexes
633 return "";
634 }
635 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
636 int index_elements_length = index_elements.getLength();
637 for(int j = 0; j < index_elements_length; j++) {
638 Element index_element = (Element) index_elements.item(j);
639 String level_str = index_element.getAttribute(LEVEL_ATTRIBUTE);
640 if(level_str.length() > 0) {
641 text.append(level_str);
642 text.append(StaticStrings.COLON_CHARACTER);
643 }
644 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT);
645 int content_elements_length = content_elements.getLength();
646 // Don't output anything if no indexes are set
647 if(content_elements_length == 0) {
648 return null;
649 }
650 for(int k = 0; k < content_elements_length; k++) {
651 Element content_element = (Element) content_elements.item(k);
652 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
653 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
654 name_str = name_str.substring(EXTRACTED_PREFIX.length());
655 }
656 text.append(name_str);
657 name_str = null;
658 if(k < content_elements_length - 1) {
659 text.append(StaticStrings.COMMA_CHARACTER);
660 }
661 content_element = null;
662 }
663 if(j < index_elements_length - 1) {
664 text.append(SPACE_CHARACTER);
665 }
666 content_elements = null;
667 index_element = null;
668 }
669 index_elements = null;
670 return text.toString();
671 }
672
673 private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
674 StringBuffer text = new StringBuffer("");
675 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
676 text.append("#");
677 }
678 text.append(INDEX_DEFAULT_STR);
679 text.append(TAB_CHARACTER);
680 text.append(command_element.getAttribute(LEVEL_ATTRIBUTE));
681 text.append(StaticStrings.COLON_CHARACTER);
682 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
683 int content_elements_length = content_elements.getLength();
684 for(int j = 0; j < content_elements_length; j++) {
685 Element content_element = (Element) content_elements.item(j);
686 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
687 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
688 name_str = name_str.substring(EXTRACTED_PREFIX.length());
689 }
690 text.append(name_str);
691 name_str = null;
692 if(j < content_elements_length - 1) {
693 text.append(StaticStrings.COMMA_CHARACTER);
694 }
695 content_element = null;
696 }
697 content_elements = null;
698 return text.toString();
699 }
700
701 private String languagesToString(Element command_element) {
702 StringBuffer text = new StringBuffer(LANGUAGES_STR);
703 text.append(TAB_CHARACTER);
704 // Retrieve all the languages and write them out in a space separated list
705 NodeList language_elements = command_element.getElementsByTagName(LANGUAGE_ELEMENT);
706 int language_elements_length = language_elements.getLength();
707 if(language_elements_length == 0) {
708 return null;
709 }
710 for(int j = 0; j < language_elements_length; j++) {
711 Element language_element = (Element) language_elements.item(j);
712 text.append(language_element.getAttribute(NAME_ATTRIBUTE));
713 if(j < language_elements_length - 1) {
714 text.append(SPACE_CHARACTER);
715 }
716 }
717 return text.toString();
718 }
719
720 private String languageDefaultToString(Element command_element) {
721 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR);
722 text.append(TAB_CHARACTER);
723 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
724 return text.toString();
725 }
726
727 private String levelsToString(Element command_element) {
728 StringBuffer text = new StringBuffer("");
729 if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
730 text.append("#");
731 }
732 text.append(LEVELS_STR);
733 text.append(TAB_CHARACTER);
734 text.append(TAB_CHARACTER);
735 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
736 int content_elements_length = content_elements.getLength();
737 // Don't output anything if no levels are set.
738 if(content_elements_length == 0) {
739 return null;
740 }
741 for(int i = 0; i < content_elements_length; i++) {
742 Element content_element = (Element) content_elements.item(i);
743 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
744 text.append(SPACE_CHARACTER);
745 }
746 return text.substring(0, text.length() - 1);
747 }
748
749 static public String metadataToString(Element command_element, boolean text_value) {
750 boolean special = false;
751 // If there is no value attribute, then we don't write anything
752 StringBuffer text = new StringBuffer("");
753 String name_str = command_element.getAttribute(NAME_ATTRIBUTE);
754 // 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.
755 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
756 text.append(name_str);
757 text.append(TAB_CHARACTER);
758 special = true;
759 }
760 else if(name_str.equals(COLLECTIONMETADATA_BETA_STR) || name_str.equals(COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
761 text.append(name_str);
762 text.append(TAB_CHARACTER);
763 text.append(TAB_CHARACTER);
764 special = true;
765 }
766 else {
767 text.append(COLLECTIONMETADATA_STR);
768 text.append(TAB_CHARACTER);
769 text.append(name_str);
770 text.append(SPACE_CHARACTER);
771 String language_str = command_element.getAttribute(LANGUAGE_ATTRIBUTE);
772 // If this is element is in english, and it is the first one found, we don't need to write the language argument.
773 //if(!language_str.equals(ENGLISH_LANGUAGE_STR) || known_metadata == null || known_metadata.contains(name_str)) {
774 // changed so that we always write the language string
775 text.append(LBRACKET_CHARACTER);
776 text.append(LANGUAGE_ARGUMENT);
777 text.append(language_str);
778 text.append(RBRACKET_CHARACTER);
779 text.append(SPACE_CHARACTER);
780 //}
781 if(known_metadata != null) {
782 known_metadata.add(name_str);
783 }
784 language_str = null;
785 }
786 name_str = null;
787
788 String value_str = MSMUtils.getValue(command_element);
789 // 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
790 if(text_value == CollectionMeta.TEXT) {
791 value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT);
792 }
793 else {
794 value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE);
795 }
796
797 // We don't wrap the email addresses in quotes, nor the other special metadata
798 if(special) {
799 text.append(value_str);
800 }
801 else {
802 text.append(SPEECH_CHARACTER);
803 text.append(value_str);
804 text.append(SPEECH_CHARACTER);
805 }
806 value_str = null;
807 return text.toString();
808 }
809
810 /** Parse a collect.cfg into a DOM model representation. */
811 private void parse(File collect_config_file) {
812 try {
813 ArrayList acquired_collectionmeta_names = null;
814 ArrayList obsolete_collectionmeta_names = null;
815 HashMap changed_collectionmeta_names = null;
816
817 // Life is made oh-so-more tricky by the existance of G2.39 config files. There are two ways to handle them:
818 // 1. Notice that the file is G2.39 from the start, then as I parse it magic it into G2.4 standard
819 // 2. Extend the parsing method to handle reading in G2.39, then afterwards go through the DOM changing it to G2.4 as appropriate.
820 // 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.
821
822 // Search for 'buildtype mgpp'
823 InputStream input_stream_one = new FileInputStream(collect_config_file);
824 Reader reader_one = new InputStreamReader(input_stream_one, ENCODING);
825 BufferedReader buffered_reader_one = new BufferedReader(reader_one);
826 String search_line_str = null;
827 while(!is_twopointthreenine && (search_line_str = buffered_reader_one.readLine()) != null) {
828 if(search_line_str.toLowerCase().indexOf(BUILDTYPE_STR) != -1) {
829 is_twopointthreenine = true;
830 acquired_collectionmeta_names = new ArrayList();
831 changed_collectionmeta_names = new HashMap();
832 obsolete_collectionmeta_names = new ArrayList();
833 }
834 }
835 buffered_reader_one.close();
836 reader_one.close();
837 input_stream_one.close();
838 buffered_reader_one = null;
839 reader_one = null;
840 input_stream_one = null;
841
842 Element collect_cfg_element = document.getDocumentElement();
843 // Read in the file one command at a time.
844 InputStream istream = new FileInputStream(collect_config_file);
845 Reader in_reader = new InputStreamReader(istream, ENCODING);
846 //FileReader in_reader = new FileReader(collect_config_file);
847 BufferedReader in = new BufferedReader(in_reader);
848 String command_str = null;
849 while((command_str = in.readLine()) != null) {
850 boolean append_element = true;
851 Element command_element = null;
852 // A command may be broken over several lines.
853 command_str = command_str.trim();
854 boolean eof = false;
855 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) {
856 String next_line = in.readLine();
857 if(next_line != null) {
858 next_line = next_line.trim();
859 if(next_line.length() > 0) {
860 // Remove the new line character
861 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
862 // And append the next line, which due to the test above must be non-zero length
863 command_str = command_str + next_line;
864 }
865 next_line = null;
866 }
867 // If we've reached the end of the file theres nothing more we can do
868 else {
869 eof = true;
870 }
871 }
872 // If there is still a new line character, then we remove it and hope for the best
873 if(command_str.endsWith(NEWLINE_CHARACTER)) {
874 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
875 }
876 // Now we've either got a command to parse...
877 if(command_str.length() != 0) {
878 // Start trying to figure out what it is
879 //StringTokenizer tokenizer = new StringTokenizer(command_str);
880 // 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.
881 CommandTokenizer tokenizer = new CommandTokenizer(command_str, in);
882 String command_type = tokenizer.nextToken().toLowerCase();
883 // 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
884 if(command_element == null && command_type.equals(BUILDTYPE_STR)) {
885 Gatherer.println("G2.39 Buildtype command detected. Ignoring.");
886 command_element = document.createElement(UNKNOWN_ELEMENT);
887 append_element = false;
888 }
889 if(command_element == null && command_type.equals(CLASSIFY_STR)) {
890 command_element = parseClassify(command_str);
891 }
892 if(command_element == null && command_type.equals(FORMAT_STR)) {
893 command_element = parseFormat(tokenizer); // Revised to handle multiple lines
894 }
895 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) {
896 // 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.
897 if(is_twopointthreenine) {
898 Gatherer.println("G2.39 Index command detected. Modifying.");
899 Gatherer.println("Before: " + command_str);
900 StringBuffer new_command_str = new StringBuffer(command_type);
901 new_command_str.append(SPACE_CHARACTER);
902 new_command_str.append(ALLFIELDS_STR);
903 new_command_str.append(SPACE_CHARACTER);
904 ArrayList known_indexes = new ArrayList();
905 while(tokenizer.hasMoreTokens()) {
906 String old_index_str = tokenizer.nextToken();
907 // 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
908 if(old_index_str.indexOf(COMMA_CHARACTER) != -1) {
909 obsolete_collectionmeta_names.add(STOP_CHARACTER + old_index_str);
910 StringTokenizer string_tokenizer = new StringTokenizer(old_index_str, COMMA_CHARACTER);
911 while(string_tokenizer.hasMoreTokens()) {
912 String index_fragment_str = string_tokenizer.nextToken();
913 if(!known_indexes.contains(index_fragment_str)) {
914 known_indexes.add(index_fragment_str);
915 new_command_str.append(index_fragment_str);
916 new_command_str.append(SPACE_CHARACTER);
917 acquired_collectionmeta_names.add(STOP_CHARACTER + index_fragment_str);
918 }
919 index_fragment_str = null;
920 }
921 string_tokenizer = null;
922 }
923 // 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.
924 else {
925 if(!known_indexes.contains(old_index_str)) {
926 known_indexes.add(old_index_str);
927 new_command_str.append(old_index_str);
928 new_command_str.append(SPACE_CHARACTER);
929 }
930 else {
931 // Use the collectionmeta for the single index instead of generating a default one
932 acquired_collectionmeta_names.remove(STOP_CHARACTER + old_index_str);
933 }
934 }
935 old_index_str = null;
936 }
937 known_indexes = null;
938 command_str = new_command_str.toString();
939 new_command_str = null;
940 Gatherer.println("After: " + command_str);
941 }
942 command_element = parseIndex(command_str);
943 }
944 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) {
945
946 command_element = parseIndexDefault(command_str);
947 // If this was a G2.39 config file then we squelch the default index (no such thing in G2.4)
948 if(is_twopointthreenine) {
949 Gatherer.println("G2.39 Default Index command detected. Ignoring.");
950 append_element = false;
951 }
952 }
953 if(command_element == null && command_type.equals(LANGUAGES_STR)) {
954 command_element = parseLanguage(command_str);
955 }
956 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) {
957 command_element = parseLanguageDefault(command_str);
958 }
959 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) {
960 // 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.
961 if(is_twopointthreenine) {
962 Gatherer.println("G2.39 Levels command detected. Modifying.");
963 Gatherer.println("Before: " + command_str);
964 StringBuffer new_command_str = new StringBuffer(command_type);
965 new_command_str.append(SPACE_CHARACTER);
966 new_command_str.append(DOCUMENT_STR);
967 while(tokenizer.hasMoreTokens()) {
968 String token = tokenizer.nextToken();
969 // Generate a lower case version
970 String token_lc = token.toLowerCase();
971 // If they are still the same then it is all good baby, otherwise we have to remember to transform their collectionmeta as well
972 if(!token.equals(token_lc)) {
973 changed_collectionmeta_names.put(STOP_CHARACTER + token, STOP_CHARACTER + token_lc);
974 }
975 new_command_str.append(SPACE_CHARACTER);
976 new_command_str.append(token_lc);
977 token_lc = null;
978 token = null;
979 }
980 command_str = new_command_str.toString();
981 new_command_str = null;
982 Gatherer.println("After: " + command_str);
983 }
984 command_element = parseLevels(command_str);
985 }
986 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) {
987 command_element = parseMetadata(tokenizer); // Revised to handle multiple lines
988 }
989 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))) {
990 command_element = parseMetadataSpecial(command_str);
991 }
992 if(command_element == null && command_type.equals(PLUGIN_STR)) {
993 command_element = parsePlugIn(command_str);
994 }
995 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) {
996 command_element = parseSearchType(command_str);
997 }
998 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) {
999 command_element = parseSubCollection(command_str);
1000 }
1001 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) {
1002 command_element = parseSubCollectionDefaultIndex(command_str);
1003 }
1004 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) {
1005 command_element = parseSubCollectionIndex(command_str);
1006 }
1007 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) {
1008 command_element = parseSuperCollection(command_str);
1009 }
1010 // Doesn't match any known type
1011 command_type = null;
1012 if(command_element == null) {
1013 // No-one knows what to do with this command, so we create an Unknown command element
1014 command_element = document.createElement(UNKNOWN_ELEMENT);
1015 MSMUtils.setValue(command_element, command_str);
1016 }
1017 }
1018 // Or an empty line to remember for later
1019 else {
1020 command_element = document.createElement(NEWLINE_ELEMENT);
1021 }
1022 // 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
1023 if(append_element) {
1024 collect_cfg_element.appendChild(command_element);
1025 }
1026 }
1027
1028 // 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.
1029 if(is_twopointthreenine) {
1030 Element search_type_element = getSearchType();
1031 search_type_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1032 while(search_type_element.hasChildNodes()) {
1033 search_type_element.removeChild(search_type_element.getFirstChild());
1034 }
1035 Element plain_search_type_element = document.createElement(CONTENT_ELEMENT);
1036 plain_search_type_element.setAttribute(NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[1]);
1037 search_type_element.appendChild(plain_search_type_element);
1038 plain_search_type_element = null;
1039 Element form_search_type_element = document.createElement(CONTENT_ELEMENT);
1040 form_search_type_element.setAttribute(NAME_ATTRIBUTE, SearchTypeManager.SEARCH_TYPES[0]);
1041 search_type_element.appendChild(form_search_type_element);
1042 form_search_type_element = null;
1043 search_type_element = null;
1044
1045 // Search through the existing collectionmeta
1046 Element document_element = document.getDocumentElement();
1047 NodeList collectionmeta_elements = document_element.getElementsByTagName(COLLECTIONMETADATA_ELEMENT);
1048 Gatherer.println("There are " + obsolete_collectionmeta_names.size() + " collectionmeta to remove.");
1049 Gatherer.println("There are " + changed_collectionmeta_names.size() + " collectionmeta to change.");
1050 for(int z = collectionmeta_elements.getLength(); z > 0; z--) {
1051 Element collectionmeta_element = (Element) collectionmeta_elements.item(z - 1);
1052 String name = collectionmeta_element.getAttribute(NAME_ATTRIBUTE);
1053 Gatherer.println("Checking " + name);
1054 // Remove any obsolete metadata
1055 if(obsolete_collectionmeta_names.contains(name)) {
1056 Gatherer.println("G2.39 CollectMeta detected. Removing: " + name);
1057 document_element.removeChild(collectionmeta_element);
1058 }
1059 // We may have been asked to change the index name to lower case
1060 else if(changed_collectionmeta_names.containsKey(name)) {
1061 String new_name = (String) changed_collectionmeta_names.get(name);
1062 Gatherer.println("G2.39 CollectMeta detected. Changing: " + name + " -> " + new_name);
1063 collectionmeta_element.setAttribute(NAME_ATTRIBUTE, new_name);
1064 new_name = null;
1065 }
1066 name = null;
1067 }
1068
1069 // Finally add any newly acquired collectionmeta. This general defaults to the collectionmeta name less the full stop
1070 Gatherer.println("There are " + acquired_collectionmeta_names.size() + " collectionmeta to add.");
1071 for(int y = 0; y < acquired_collectionmeta_names.size(); y++) {
1072 String name = (String) acquired_collectionmeta_names.get(y);
1073 String value = name.substring(1);
1074 Gatherer.println("G2.39 CollectMeta missing. Adding: " + name + " [l=" + Gatherer.config.getLanguage() + "] \"" + value + "\"");
1075 Element element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1076 element.setAttribute(NAME_ATTRIBUTE, name);
1077 element.setAttribute(LANGUAGE_ATTRIBUTE, Gatherer.config.getLanguage());
1078 element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1079 MSMUtils.setValue(element, value);
1080 document_element.appendChild(element);
1081 element = null;
1082 value = null;
1083 name = null;
1084 }
1085
1086 document_element = null;
1087 }
1088 }
1089 catch(Exception exception) {
1090 Gatherer.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
1091 Gatherer.printStackTrace(exception);
1092 }
1093 }
1094
1095 private Element parseClassify(String command_str) {
1096 Element command_element = null;
1097 try {
1098 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1099 // 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).
1100 if(tokenizer.countTokens() >= 2) { // Must support "classify Phind" (no args)
1101 command_element = document.createElement(CLASSIFY_ELEMENT);
1102 // First token is classify
1103 tokenizer.nextToken();
1104 // The next token is the classifier type
1105 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
1106 // Now we parse out the remaining arguments into a hashmapping from name to value
1107 HashMap arguments = parseArguments(tokenizer);
1108 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1109 Iterator names = arguments.keySet().iterator();
1110 while(names.hasNext()) {
1111 String name = (String) names.next();
1112 String value = (String) arguments.get(name); // Can be null
1113 // The metadata argument gets added as the content attribute
1114 if(name.equals(METADATA_ARGUMENT) && value != null) {
1115 // 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.
1116 if(value.indexOf(MSMUtils.NS_SEP) == -1) {
1117 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
1118 }
1119 //command_element.setAttribute(CONTENT_ATTRIBUTE, value);
1120 }
1121 // Everything else is an Option Element
1122 Element option_element = document.createElement(OPTION_ELEMENT);
1123 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1124 if(value != null) {
1125 // Remove any speech marks appended in strings containing whitespace
1126 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1127 value = value.substring(1, value.length() - 1);
1128 }
1129 MSMUtils.setValue(option_element, value);
1130 }
1131 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1132 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1133 command_element.appendChild(option_element);
1134 option_element = null;
1135 name = null;
1136 value = null;
1137 }
1138 names = null;
1139 arguments = null;
1140 }
1141 tokenizer = null;
1142 }
1143 catch(Exception error) {
1144 }
1145 return command_element;
1146 }
1147
1148 private Element parseFormat(CommandTokenizer tokenizer) {
1149 Element command_element = null;
1150 try {
1151 command_element = document.createElement(FORMAT_ELEMENT);
1152 String name_str = tokenizer.nextToken();
1153 String value_str = tokenizer.nextToken();
1154 if(name_str != null && value_str != null) {
1155 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1156 // If the value is true or false we add it as an attribute
1157 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
1158 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
1159 }
1160 // Otherwise it gets added as a text node
1161 else {
1162 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1163 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1164 MSMUtils.setValue(command_element, value_str);
1165 }
1166 }
1167 else {
1168 command_element = null;
1169 }
1170 name_str = null;
1171 value_str = null;
1172 }
1173 catch (Exception exception) {
1174 Gatherer.printStackTrace(exception);
1175 command_element = null;
1176 }
1177 return command_element;
1178 }
1179
1180 private Element parseIndex(String command_str) {
1181 Element command_element = null;
1182 try {
1183 StringTokenizer tokenizer = new StringTokenizer(command_str);
1184 String command = tokenizer.nextToken();
1185 command_element = document.createElement(INDEXES_ELEMENT);
1186 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1187 command = null;
1188 if(!tokenizer.hasMoreTokens()) {
1189
1190 // there are no indexes
1191 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1192 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1193 tokenizer = null;
1194 return command_element;
1195 }
1196
1197 while(tokenizer.hasMoreTokens()) {
1198 Element index_element = document.createElement(INDEX_ELEMENT);
1199 String index_str = tokenizer.nextToken();
1200 // 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.
1201 boolean old_index;
1202 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1203 old_index = true;
1204 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1205 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1206 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1207 }
1208 else {
1209 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1210 old_index = false;
1211 }
1212 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1213 while(content_tokenizer.hasMoreTokens()) {
1214 Element content_element = document.createElement(CONTENT_ELEMENT);
1215 String content_str = content_tokenizer.nextToken();
1216 // 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.
1217 if(content_str.indexOf(MSMUtils.NS_SEP) == -1) {
1218 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1219 // Our special strings are OK.
1220 }
1221 else {
1222 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
1223 }
1224 }
1225 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1226 index_element.appendChild(content_element);
1227 content_element = null;
1228 }
1229 content_tokenizer = null;
1230 index_str = null;
1231 command_element.appendChild(index_element);
1232 index_element = null;
1233 }
1234 tokenizer = null;
1235 }
1236 catch (Exception exception) {
1237 exception.printStackTrace();
1238 }
1239 return command_element;
1240 }
1241
1242 private Element parseIndexDefault(String command_str) {
1243 Element command_element = null;
1244 try {
1245 StringTokenizer tokenizer = new StringTokenizer(command_str);
1246 if(tokenizer.countTokens() >= 2) {
1247 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1248 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1249 String index_str = tokenizer.nextToken();
1250 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1251 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1252 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1253 while(content_tokenizer.hasMoreTokens()) {
1254 Element content_element = document.createElement(CONTENT_ELEMENT);
1255 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1256 command_element.appendChild(content_element);
1257 content_element = null;
1258 }
1259 content_tokenizer = null;
1260 content_str = null;
1261 content_str = null;
1262 index_str = null;
1263 }
1264 tokenizer = null;
1265 }
1266 catch (Exception exception) {
1267 }
1268 return command_element;
1269 }
1270
1271 private Element parseLanguage(String command_str) {
1272 Element command_element = null;
1273 try {
1274 StringTokenizer tokenizer = new StringTokenizer(command_str);
1275 tokenizer.nextToken();
1276 if(tokenizer.hasMoreTokens()) {
1277 command_element = document.createElement(LANGUAGES_ELEMENT);
1278 while(tokenizer.hasMoreTokens()) {
1279 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1280 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1281 command_element.appendChild(language_element);
1282 language_element = null;
1283 }
1284 }
1285 tokenizer = null;
1286 }
1287 catch (Exception exception) {
1288 }
1289 return command_element;
1290 }
1291
1292 private Element parseLanguageDefault(String command_str) {
1293 Element command_element = null;
1294 try {
1295 StringTokenizer tokenizer = new StringTokenizer(command_str);
1296 if(tokenizer.countTokens() >= 2) {
1297 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1298 tokenizer.nextToken();
1299 String default_language_str = tokenizer.nextToken();
1300 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1301 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1302 default_language_str = null;
1303 }
1304 tokenizer = null;
1305 }
1306 catch (Exception exception) {
1307 }
1308 return command_element;
1309 }
1310
1311 private Element parseLevels(String command_str) {
1312 Element command_element = null;
1313 try {
1314 StringTokenizer tokenizer = new StringTokenizer(command_str);
1315 // First token is command type (levels)
1316 String command = tokenizer.nextToken();
1317 if(tokenizer.hasMoreTokens()) {
1318 command_element = document.createElement(LEVELS_ELEMENT);
1319 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1320 while(tokenizer.hasMoreTokens()) {
1321 Element level_element = document.createElement(CONTENT_ELEMENT);
1322 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1323 command_element.appendChild(level_element);
1324 level_element = null;
1325 }
1326 }
1327 command = null;
1328 }
1329 catch(Exception exception) {
1330 }
1331 return command_element;
1332 }
1333
1334 private Element parseMetadata(CommandTokenizer tokenizer) {
1335 Element command_element = null;
1336 try {
1337 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1338 String name_str = tokenizer.nextToken();
1339 String value_str = tokenizer.nextToken();
1340 if(name_str != null && value_str != null) {
1341 String language_str = Gatherer.config.getLanguage();
1342 // Check if the value string is actually a language string
1343 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1344 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1345 value_str = tokenizer.nextToken();
1346 }
1347 if(value_str != null) {
1348 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1349 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1350 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1351 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1352 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1353 MSMUtils.setValue(command_element, value_str);
1354 }
1355 else {
1356 command_element = null;
1357 }
1358 language_str = null;
1359 }
1360 else {
1361 command_element = null;
1362 }
1363 name_str = null;
1364 value_str = null;
1365 }
1366 catch (Exception exception) {
1367 Gatherer.printStackTrace(exception);
1368 command_element = null;
1369 }
1370 return command_element;
1371 }
1372
1373 private Element parseMetadataSpecial(String command_str) {
1374 Element command_element = null;
1375 try {
1376 StringTokenizer tokenizer = new StringTokenizer(command_str);
1377 if(tokenizer.countTokens() >= 2) {
1378 String name_str = tokenizer.nextToken();
1379 String value_str = tokenizer.nextToken();
1380 if(name_str.equals(COLLECTIONMETADATA_BETA_STR)) {
1381 command_element = document.createElement(COLLECTIONMETADATA_BETA_ELEMENT);
1382 }
1383 else if(name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1384 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1385 }
1386 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1387 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1388 }
1389 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1390 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1391 }
1392 if(command_element != null) {
1393 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1394 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1395 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1396 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1397 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1398 value_str = value_str.substring(1, value_str.length() - 1);
1399 }
1400 MSMUtils.setValue(command_element, value_str);
1401 }
1402 value_str = null;
1403 name_str = null;
1404 }
1405 tokenizer = null;
1406 }
1407 catch (Exception exception) {
1408 }
1409 return command_element;
1410 }
1411
1412 private Element parsePlugIn(String command_str) {
1413 Element command_element = null;
1414 boolean use_metadata_files = false;
1415 try {
1416 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1417 // 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).
1418 if(tokenizer.countTokens() >= 2) {
1419 command_element = document.createElement(PLUGIN_ELEMENT);
1420 // First token is plugin
1421 tokenizer.nextToken();
1422 // The next token is the type
1423 String type = tokenizer.nextToken();
1424 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1425 // Now we parse out the remaining arguments into a hashmapping from name to value
1426 HashMap arguments = parseArguments(tokenizer);
1427 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1428 Iterator names = arguments.keySet().iterator();
1429 while(names.hasNext()) {
1430 String name = (String) names.next();
1431 String value = (String) arguments.get(name); // Can be null
1432 Element option_element = document.createElement(OPTION_ELEMENT);
1433 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1434 use_metadata_files = true;
1435 }
1436 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1437 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1438 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1439 if(value != null) {
1440 // Remove any speech marks appended in strings containing whitespace
1441 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1442 value = value.substring(1, value.length() - 1);
1443 }
1444 if(name.equals(METADATA_ARGUMENT)) {
1445 // 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.
1446 if(value.indexOf(MSMUtils.NS_SEP) == -1) {
1447 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
1448 }
1449 }
1450 MSMUtils.setValue(option_element, value);
1451 }
1452 command_element.appendChild(option_element);
1453 option_element = null;
1454 name = null;
1455 value = null;
1456 }
1457
1458 // We must have some RecPlug options: use_metadata_files, and show_progress
1459 if (type.equals(RECPLUG_STR)) {
1460 if (!use_metadata_files) {
1461 Element option_element = document.createElement(OPTION_ELEMENT);
1462 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1463 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1464 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1465 command_element.appendChild(option_element);
1466 option_element = null;
1467 }
1468 }
1469 type = null;
1470 names = null;
1471 arguments = null;
1472 }
1473 tokenizer = null;
1474 }
1475 catch(Exception exception) {
1476 }
1477 return command_element;
1478 }
1479
1480 private Element parseSearchType(String command_str) {
1481 Element command_element = null;
1482 try {
1483 StringTokenizer tokenizer = new StringTokenizer(command_str);
1484 // First token is command type (levels)
1485 tokenizer.nextToken();
1486 if(tokenizer.hasMoreTokens()) {
1487 command_element = document.createElement(SEARCHTYPE_ELEMENT);
1488 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1489 while(tokenizer.hasMoreTokens()) {
1490 Element search_element = document.createElement(CONTENT_ELEMENT);
1491 search_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1492 command_element.appendChild(search_element);
1493 search_element = null;
1494 }
1495 }
1496 }
1497 catch(Exception exception) {
1498 }
1499 return command_element;
1500 }
1501
1502 private Element parseSubCollection(String command_str) {
1503 Element command_element = null;
1504 try {
1505 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1506 if(tokenizer.countTokens() >= 3) {
1507 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1508 // First token is command type
1509 tokenizer.nextToken();
1510 // Then subcollection identifier
1511 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1512 // Then finally the pattern used to build the subcollection partition
1513 String full_pattern_str = tokenizer.nextToken();
1514 // To make life easier I'm going to parse this up now.
1515 boolean exclusion = (full_pattern_str.substring(1, 2).equals(EXCLAIMATION_CHARACTER));
1516 // Set inclusion/exclusion flag, remove any exclaimation mark and the speech marks
1517 if(exclusion) {
1518 full_pattern_str = full_pattern_str.substring(2, full_pattern_str.length() - 1);
1519 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1520 }
1521 else {
1522 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length() - 1);
1523 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1524 }
1525 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1526 if(pattern_tokenizer.countTokens() >= 2) {
1527 String content_str = pattern_tokenizer.nextToken();
1528 // 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.
1529 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(MSMUtils.NS_SEP) == -1) {
1530 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
1531 }
1532 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1533 MSMUtils.setValue(command_element, pattern_tokenizer.nextToken());
1534 if(pattern_tokenizer.hasMoreTokens()) {
1535 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1536 }
1537 }
1538 pattern_tokenizer = null;
1539 }
1540 }
1541 catch(Exception exception) {
1542 exception.printStackTrace();
1543 }
1544 return command_element;
1545 }
1546
1547 private Element parseSubCollectionDefaultIndex(String command_str) {
1548 Element command_element = null;
1549 try {
1550 StringTokenizer tokenizer = new StringTokenizer(command_str);
1551 if(tokenizer.countTokens() == 2) {
1552 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1553 tokenizer.nextToken();
1554 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1555 String content_str = tokenizer.nextToken();
1556 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1557 while(content_tokenizer.hasMoreTokens()) {
1558 Element content_element = document.createElement(CONTENT_ELEMENT);
1559 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1560 command_element.appendChild(content_element);
1561 content_element = null;
1562 }
1563 content_tokenizer = null;
1564 content_str = null;
1565 }
1566 tokenizer = null;
1567 }
1568 catch(Exception exception) {
1569 }
1570 return command_element;
1571 }
1572
1573 private Element parseSubCollectionIndex(String command_str) {
1574 Element command_element = null;
1575 try {
1576 StringTokenizer tokenizer = new StringTokenizer(command_str);
1577 tokenizer.nextToken();
1578 if(tokenizer.hasMoreTokens()) {
1579 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1580 }
1581 while(tokenizer.hasMoreTokens()) {
1582 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1583 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1584 String content_str = tokenizer.nextToken();
1585 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1586 while(content_tokenizer.hasMoreTokens()) {
1587 Element content_element = document.createElement(CONTENT_ELEMENT);
1588 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1589 subcollectionindex_element.appendChild(content_element);
1590 content_element = null;
1591 }
1592 content_tokenizer = null;
1593 content_str = null;
1594 command_element.appendChild(subcollectionindex_element);
1595 subcollectionindex_element = null;
1596 }
1597 tokenizer = null;
1598 }
1599 catch (Exception exception) {
1600 }
1601 return command_element;
1602 }
1603
1604 private Element parseSuperCollection(String command_str) {
1605 Element command_element = null;
1606 try {
1607 StringTokenizer tokenizer = new StringTokenizer(command_str);
1608 if(tokenizer.countTokens() >= 3) {
1609 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1610 tokenizer.nextToken();
1611 while(tokenizer.hasMoreTokens()) {
1612 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1613 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1614 command_element.appendChild(collection_element);
1615 collection_element = null;
1616 }
1617 }
1618 tokenizer = null;
1619 }
1620 catch(Exception exception) {
1621 }
1622 return command_element;
1623 }
1624
1625 private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1626 StringBuffer text = new StringBuffer();
1627 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1628 text.append(PLUGIN_STR);
1629 text.append(TAB_CHARACTER);
1630 text.append(TAB_CHARACTER);
1631 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1632 // Retrieve, and output, the arguments
1633 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1634 int option_elements_length = option_elements.getLength();
1635 if(option_elements_length > 0) {
1636 text.append(SPACE_CHARACTER);
1637 for(int j = 0; j < option_elements_length; j++) {
1638 Element option_element = (Element) option_elements.item(j);
1639 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1640 text.append(StaticStrings.MINUS_CHARACTER);
1641 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1642 String value_str = MSMUtils.getValue(option_element);
1643 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) {
1644 value_str = value_str.substring(EXTRACTED_PREFIX.length());
1645 }
1646 if(value_str.length() > 0) {
1647 text.append(SPACE_CHARACTER);
1648 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1649 text.append(value_str);
1650 }
1651 else {
1652 text.append(SPEECH_CHARACTER);
1653 text.append(value_str);
1654 text.append(SPEECH_CHARACTER);
1655 }
1656 }
1657 value_str = null;
1658 if(j < option_elements_length - 1) {
1659 text.append(SPACE_CHARACTER);
1660 }
1661 }
1662 option_element = null;
1663 }
1664 }
1665 option_elements = null;
1666 }
1667 return text.toString();
1668 }
1669
1670 private String searchtypeToString(Element command_element) {
1671 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1672 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1673 text.append(TAB_CHARACTER);
1674 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1675 int search_elements_length = search_elements.getLength();
1676 for(int i = 0; i < search_elements_length; i++) {
1677 Element search_element = (Element) search_elements.item(i);
1678 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1679 text.append(SPACE_CHARACTER);
1680 }
1681 return text.substring(0, text.length() - 1);
1682 }
1683 else {
1684 return null;
1685 }
1686 }
1687
1688 private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1689 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1690 text.append(SPACE_CHARACTER);
1691 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1692 text.append(SPACE_CHARACTER);
1693 text.append(TAB_CHARACTER);
1694 text.append(SPEECH_CHARACTER);
1695 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1696 text.append(EXCLAIMATION_CHARACTER);
1697 }
1698 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1699 if(!show_extracted_namespace && content_str.startsWith(EXTRACTED_PREFIX)) {
1700 content_str = content_str.substring(EXTRACTED_PREFIX.length());
1701 }
1702 text.append(content_str);
1703 content_str = null;
1704 text.append(SEPARATOR_CHARACTER);
1705 text.append(MSMUtils.getValue(command_element));
1706 text.append(SEPARATOR_CHARACTER);
1707 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1708 if(options_str.length() > 0) {
1709 text.append(options_str);
1710 }
1711 options_str = null;
1712 text.append(SPEECH_CHARACTER);
1713 return text.toString();
1714 }
1715
1716 private String subcollectionDefaultIndexToString(Element command_element) {
1717 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1718 text.append(TAB_CHARACTER);
1719 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1720 int content_elements_length = content_elements.getLength();
1721 for(int j = 0; j < content_elements_length; j++) {
1722 Element content_element = (Element) content_elements.item(j);
1723 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1724 if(j < content_elements_length - 1) {
1725 text.append(StaticStrings.COMMA_CHARACTER);
1726 }
1727 }
1728 return text.toString();
1729 }
1730
1731 private String subcollectionIndexesToString(Element command_element) {
1732 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1733 text.append(TAB_CHARACTER);
1734 // Retrieve all of the subcollection index partitions
1735 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1736 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1737 if(subcollectionindex_elements_length == 0) {
1738 return null;
1739 }
1740 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1741 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1742 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1743 int content_elements_length = content_elements.getLength();
1744 for(int k = 0; k < content_elements_length; k++) {
1745 Element content_element = (Element) content_elements.item(k);
1746 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1747 if(k < content_elements_length - 1) {
1748 text.append(StaticStrings.COMMA_CHARACTER);
1749 }
1750 }
1751 if(j < subcollectionindex_elements_length - 1) {
1752 text.append(SPACE_CHARACTER);
1753 }
1754 }
1755 return text.toString();
1756 }
1757
1758 private String supercollectionToString(Element command_element) {
1759 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1760 int content_elements_length = content_elements.getLength();
1761 if(content_elements_length > 1) {
1762 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1763 text.append(TAB_CHARACTER);
1764 for(int j = 0; j < content_elements_length; j++) {
1765 Element content_element = (Element) content_elements.item(j);
1766 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1767 if(j < content_elements_length - 1) {
1768 text.append(SPACE_CHARACTER);
1769 }
1770 }
1771 return text.toString();
1772 }
1773 return null;
1774 }
1775
1776 private String unknownToString(Element command_element) {
1777 return MSMUtils.getValue(command_element);
1778 }
1779
1780 /** 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.
1781 * @param writer the BufferedWriter to which the str will be written
1782 * @param str the String to be written
1783 */
1784 private void write(BufferedWriter writer, String str)
1785 throws IOException {
1786 writer.write(str, 0, str.length());
1787 }
1788}
Note: See TracBrowser for help on using the repository browser.