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

Last change on this file since 12803 was 12803, checked in by mdewsnip, 18 years ago

Moved dealing with the Local Library out of CollectionDesignManager and into CollectionConfiguration, as part of tidying up the saving of the collect.cfg file.

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