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

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

removed the custom attribute setting

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