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

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

Removed all occurrences of classes explicitly importing other classes in the same package.

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