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

Last change on this file since 12350 was 12350, checked in by kjdon, 18 years ago

change parseClassify to use a StringBuffer in an inner loop, and added support for languagemetadata in collect.cfg (used with language partitions

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