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

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

added a hack to cope with pre 2.71 collections which don't specify a build type. if no build type specified, use mg unless searchtypes were specified, in which case use mgpp

  • Property svn:keywords set to Author Date Id Revision
File size: 69.2 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 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1031 command_element.appendChild(option_element);
1032 option_element = null;
1033 name = null;
1034 value = null;
1035 }
1036 names = null;
1037 arguments = null;
1038 }
1039 tokenizer = null;
1040 }
1041 catch(Exception error) {
1042 }
1043 return command_element;
1044 }
1045
1046 private Element parseFormat(CommandTokenizer tokenizer) {
1047 Element command_element = null;
1048 try {
1049 command_element = document.createElement(FORMAT_ELEMENT);
1050 String name_str = tokenizer.nextToken();
1051 String value_str = tokenizer.nextToken();
1052 if(name_str != null && value_str != null) {
1053 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1054 // If the value is true or false we add it as an attribute
1055 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
1056 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
1057 }
1058 // Otherwise it gets added as a text node
1059 else {
1060 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1061 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1062 XMLTools.setValue(command_element, value_str);
1063 }
1064 }
1065 else {
1066 command_element = null;
1067 }
1068 name_str = null;
1069 value_str = null;
1070 }
1071 catch (Exception exception) {
1072 DebugStream.printStackTrace(exception);
1073 command_element = null;
1074 }
1075 return command_element;
1076 }
1077
1078 private Element parseIndex(String command_str) {
1079 Element command_element = null;
1080 try {
1081 StringTokenizer tokenizer = new StringTokenizer(command_str);
1082 String command = tokenizer.nextToken();
1083 command_element = document.createElement(INDEXES_ELEMENT);
1084 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1085 command = null;
1086 if(!tokenizer.hasMoreTokens()) {
1087
1088 // there are no indexes
1089 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1090 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1091 tokenizer = null;
1092 return command_element;
1093 }
1094
1095 while(tokenizer.hasMoreTokens()) {
1096 Element index_element = document.createElement(INDEX_ELEMENT);
1097 String index_str = tokenizer.nextToken();
1098 // 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.
1099 boolean old_index;
1100 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1101 old_index = true;
1102 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1103 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1104 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1105 }
1106 else {
1107 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1108 old_index = false;
1109 }
1110 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1111 while(content_tokenizer.hasMoreTokens()) {
1112 Element content_element = document.createElement(CONTENT_ELEMENT);
1113 String content_str = content_tokenizer.nextToken();
1114 // 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.
1115 if(content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1116 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1117 // Our special strings are OK.
1118 }
1119 else {
1120 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1121 }
1122 }
1123 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1124 index_element.appendChild(content_element);
1125 content_element = null;
1126 }
1127 content_tokenizer = null;
1128 index_str = null;
1129 command_element.appendChild(index_element);
1130 index_element = null;
1131 }
1132 tokenizer = null;
1133 }
1134 catch (Exception exception) {
1135 exception.printStackTrace();
1136 }
1137 return command_element;
1138 }
1139
1140 private Element parseIndexDefault(String command_str) {
1141 Element command_element = null;
1142 try {
1143 StringTokenizer tokenizer = new StringTokenizer(command_str);
1144 if(tokenizer.countTokens() >= 2) {
1145 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1146 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1147 String index_str = tokenizer.nextToken();
1148 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1149 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1150 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1151 while(content_tokenizer.hasMoreTokens()) {
1152 Element content_element = document.createElement(CONTENT_ELEMENT);
1153 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1154 command_element.appendChild(content_element);
1155 content_element = null;
1156 }
1157 content_tokenizer = null;
1158 content_str = null;
1159 content_str = null;
1160 index_str = null;
1161 }
1162 tokenizer = null;
1163 }
1164 catch (Exception exception) {
1165 }
1166 return command_element;
1167 }
1168
1169 private Element parseLanguage(String command_str) {
1170 Element command_element = null;
1171 try {
1172 StringTokenizer tokenizer = new StringTokenizer(command_str);
1173 tokenizer.nextToken();
1174 if(tokenizer.hasMoreTokens()) {
1175 command_element = document.createElement(LANGUAGES_ELEMENT);
1176 while(tokenizer.hasMoreTokens()) {
1177 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1178 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1179 command_element.appendChild(language_element);
1180 language_element = null;
1181 }
1182 }
1183 tokenizer = null;
1184 }
1185 catch (Exception exception) {
1186 }
1187 return command_element;
1188 }
1189
1190 private Element parseLanguageDefault(String command_str) {
1191 Element command_element = null;
1192 try {
1193 StringTokenizer tokenizer = new StringTokenizer(command_str);
1194 if(tokenizer.countTokens() >= 2) {
1195 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1196 tokenizer.nextToken();
1197 String default_language_str = tokenizer.nextToken();
1198 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1199 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1200 default_language_str = null;
1201 }
1202 tokenizer = null;
1203 }
1204 catch (Exception exception) {
1205 }
1206 return command_element;
1207 }
1208
1209 private Element parseLevels(String command_str) {
1210 Element command_element = null;
1211 try {
1212 StringTokenizer tokenizer = new StringTokenizer(command_str);
1213 // First token is command type (levels)
1214 String command = tokenizer.nextToken();
1215 if(tokenizer.hasMoreTokens()) {
1216 command_element = document.createElement(LEVELS_ELEMENT);
1217 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1218 while(tokenizer.hasMoreTokens()) {
1219 Element level_element = document.createElement(LEVEL_ELEMENT);
1220 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1221 command_element.appendChild(level_element);
1222 level_element = null;
1223 }
1224 }
1225 command = null;
1226 }
1227 catch(Exception exception) {
1228 }
1229 return command_element;
1230 }
1231
1232 private Element parseLevelDefault(String command_str) {
1233 Element command_element = null;
1234 try {
1235 StringTokenizer tokenizer = new StringTokenizer(command_str);
1236 if(tokenizer.countTokens() >= 2) {
1237 command_element = document.createElement(LEVEL_DEFAULT_ELEMENT);
1238 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(LEVEL_DEFAULT_STR) ? TRUE_STR : FALSE_STR)); // is it commented out or not?
1239 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1240 }
1241
1242 tokenizer = null;
1243 }
1244 catch (Exception exception) {
1245 }
1246 return command_element;
1247 }
1248
1249 private Element parseMetadata(CommandTokenizer tokenizer) {
1250 Element command_element = null;
1251 try {
1252 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1253 String name_str = tokenizer.nextToken();
1254 String value_str = tokenizer.nextToken();
1255 if(name_str != null && value_str != null) {
1256 String language_str = Configuration.getLanguage();
1257 // Check if the value string is actually a language string
1258 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1259 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1260 value_str = tokenizer.nextToken();
1261 }
1262 if(value_str != null) {
1263 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1264 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1265 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1266 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1267 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1268 XMLTools.setValue(command_element, value_str);
1269 }
1270 else {
1271 command_element = null;
1272 }
1273 language_str = null;
1274 }
1275 else {
1276 command_element = null;
1277 }
1278 name_str = null;
1279 value_str = null;
1280 }
1281 catch (Exception exception) {
1282 DebugStream.printStackTrace(exception);
1283 command_element = null;
1284 }
1285 return command_element;
1286 }
1287
1288 private Element parseMetadataSpecial(String command_str) {
1289 Element command_element = null;
1290 try {
1291 StringTokenizer tokenizer = new StringTokenizer(command_str);
1292 if(tokenizer.countTokens() >= 2) {
1293 String name_str = tokenizer.nextToken();
1294 String value_str = tokenizer.nextToken();
1295 if (name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1296 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1297 }
1298 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1299 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1300 }
1301 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1302 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1303 }
1304 else if (name_str.equals(BUILDTYPE_STR)) {
1305 command_element = document.createElement(BUILDTYPE_ELEMENT);
1306 }
1307 if(command_element != null) {
1308 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1309 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1310 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1311 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1312 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1313 value_str = value_str.substring(1, value_str.length() - 1);
1314 }
1315 XMLTools.setValue(command_element, value_str);
1316 }
1317 value_str = null;
1318 name_str = null;
1319 }
1320 tokenizer = null;
1321 }
1322 catch (Exception exception) {
1323 }
1324 return command_element;
1325 }
1326
1327 private Element parsePlugin(String command_str) {
1328 Element command_element = null;
1329 boolean use_metadata_files = false;
1330 try {
1331 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1332 // 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).
1333 if(tokenizer.countTokens() >= 2) {
1334 command_element = document.createElement(PLUGIN_ELEMENT);
1335 // First token is plugin
1336 tokenizer.nextToken();
1337 // The next token is the type
1338 String type = tokenizer.nextToken();
1339 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1340 // Now we parse out the remaining arguments into a hashmapping from name to value
1341 HashMap arguments = parseArguments(tokenizer);
1342 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1343 Iterator names = arguments.keySet().iterator();
1344 while(names.hasNext()) {
1345 String name = (String) names.next();
1346 String value = (String) arguments.get(name); // Can be null
1347 Element option_element = document.createElement(OPTION_ELEMENT);
1348 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1349 use_metadata_files = true;
1350 }
1351 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1352 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1353 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1354 if(value != null) {
1355 // Remove any speech marks appended in strings containing whitespace
1356 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1357 value = value.substring(1, value.length() - 1);
1358 }
1359 if(name.equals(METADATA_ARGUMENT)) {
1360 // 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.
1361 if(value.indexOf(StaticStrings.NS_SEP) == -1) {
1362 value = StaticStrings.EXTRACTED_NAMESPACE + value;
1363 }
1364 }
1365 XMLTools.setValue(option_element, value);
1366 }
1367 command_element.appendChild(option_element);
1368 option_element = null;
1369 name = null;
1370 value = null;
1371 }
1372
1373 // We must have some RecPlug options: use_metadata_files
1374 if (type.equals(RECPLUG_STR)) {
1375 if (!use_metadata_files) {
1376 Element option_element = document.createElement(OPTION_ELEMENT);
1377 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1378 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1379 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1380 command_element.appendChild(option_element);
1381 option_element = null;
1382 }
1383 }
1384 type = null;
1385 names = null;
1386 arguments = null;
1387 }
1388 tokenizer = null;
1389 }
1390 catch(Exception exception) {
1391 }
1392 return command_element;
1393 }
1394
1395 /* search types are now handled as formats - leave this here to convert in case we have an old config file */
1396 private Element parseSearchType(String command_str) {
1397 Element command_element = null;
1398 try {
1399 StringTokenizer tokenizer = new StringTokenizer(command_str);
1400 // First token is command type (searchtype)
1401 tokenizer.nextToken();
1402 if(tokenizer.hasMoreTokens()) {
1403 command_element = document.createElement(FORMAT_ELEMENT);
1404 command_element.setAttribute(NAME_ATTRIBUTE, "SearchTypes");
1405 String value = tokenizer.nextToken();
1406 while(tokenizer.hasMoreTokens()) {
1407 value += ","+tokenizer.nextToken();
1408 }
1409 value = Codec.transform(value, Codec.GREENSTONE_TO_DOM);
1410 XMLTools.setValue(command_element, value);
1411 }
1412 }
1413 catch(Exception exception) {
1414 }
1415 return command_element;
1416 }
1417
1418 private Element parseSubCollection(String command_str) {
1419 Element command_element = null;
1420 try {
1421 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1422 if(tokenizer.countTokens() >= 3) {
1423 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1424 // First token is command type
1425 tokenizer.nextToken();
1426 // Then subcollection identifier
1427 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1428 // Then finally the pattern used to build the subcollection partition
1429 String full_pattern_str = tokenizer.nextToken();
1430 // Set inclusion/exclusion flag and remove any exclamation mark
1431 boolean exclusion = full_pattern_str.startsWith(EXCLAMATION_CHARACTER);
1432 if (exclusion) {
1433 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length());
1434 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1435 }
1436 else {
1437 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1438 }
1439 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1440 if(pattern_tokenizer.countTokens() >= 2) {
1441 String content_str = pattern_tokenizer.nextToken();
1442 // 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.
1443 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1444 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1445 }
1446 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1447 XMLTools.setValue(command_element, pattern_tokenizer.nextToken());
1448 if(pattern_tokenizer.hasMoreTokens()) {
1449 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1450 }
1451 }
1452 pattern_tokenizer = null;
1453 }
1454 }
1455 catch(Exception exception) {
1456 exception.printStackTrace();
1457 }
1458 return command_element;
1459 }
1460
1461 private Element parseSubCollectionDefaultIndex(String command_str) {
1462 Element command_element = null;
1463 try {
1464 StringTokenizer tokenizer = new StringTokenizer(command_str);
1465 if(tokenizer.countTokens() == 2) {
1466 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1467 tokenizer.nextToken();
1468 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1469 String content_str = tokenizer.nextToken();
1470 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1471 while(content_tokenizer.hasMoreTokens()) {
1472 Element content_element = document.createElement(CONTENT_ELEMENT);
1473 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1474 command_element.appendChild(content_element);
1475 content_element = null;
1476 }
1477 content_tokenizer = null;
1478 content_str = null;
1479 }
1480 tokenizer = null;
1481 }
1482 catch(Exception exception) {
1483 }
1484 return command_element;
1485 }
1486
1487 private Element parseSubCollectionIndex(String command_str) {
1488 Element command_element = null;
1489 try {
1490 StringTokenizer tokenizer = new StringTokenizer(command_str);
1491 tokenizer.nextToken();
1492 if(tokenizer.hasMoreTokens()) {
1493 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1494 }
1495 while(tokenizer.hasMoreTokens()) {
1496 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1497 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1498 String content_str = tokenizer.nextToken();
1499 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1500 while(content_tokenizer.hasMoreTokens()) {
1501 Element content_element = document.createElement(CONTENT_ELEMENT);
1502 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1503 subcollectionindex_element.appendChild(content_element);
1504 content_element = null;
1505 }
1506 content_tokenizer = null;
1507 content_str = null;
1508 command_element.appendChild(subcollectionindex_element);
1509 subcollectionindex_element = null;
1510 }
1511 tokenizer = null;
1512 }
1513 catch (Exception exception) {
1514 }
1515 return command_element;
1516 }
1517
1518 private Element parseSuperCollection(String command_str) {
1519 Element command_element = null;
1520 try {
1521 StringTokenizer tokenizer = new StringTokenizer(command_str);
1522 if(tokenizer.countTokens() >= 3) {
1523 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1524 tokenizer.nextToken();
1525 while(tokenizer.hasMoreTokens()) {
1526 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1527 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1528 command_element.appendChild(collection_element);
1529 collection_element = null;
1530 }
1531 }
1532 tokenizer = null;
1533 }
1534 catch(Exception exception) {
1535 }
1536 return command_element;
1537 }
1538
1539 static private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1540 StringBuffer text = new StringBuffer();
1541 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1542 text.append(PLUGIN_STR);
1543 text.append(TAB_CHARACTER);
1544 text.append(TAB_CHARACTER);
1545 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1546 // Retrieve, and output, the arguments
1547 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1548 int option_elements_length = option_elements.getLength();
1549 if(option_elements_length > 0) {
1550 text.append(SPACE_CHARACTER);
1551 for(int j = 0; j < option_elements_length; j++) {
1552 Element option_element = (Element) option_elements.item(j);
1553 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1554 text.append(StaticStrings.MINUS_CHARACTER);
1555 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1556 String value_str = XMLTools.getValue(option_element);
1557 if(!show_extracted_namespace && value_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1558 value_str = value_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1559 }
1560 if(value_str.length() > 0) {
1561 text.append(SPACE_CHARACTER);
1562 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1563 text.append(value_str);
1564 }
1565 else {
1566 text.append(SPEECH_CHARACTER);
1567 text.append(value_str);
1568 text.append(SPEECH_CHARACTER);
1569 }
1570 }
1571 value_str = null;
1572 if(j < option_elements_length - 1) {
1573 text.append(SPACE_CHARACTER);
1574 }
1575 }
1576 option_element = null;
1577 }
1578 }
1579 option_elements = null;
1580 }
1581 return text.toString();
1582 }
1583
1584 static private String searchtypeToString(Element command_element) {
1585 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1586 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1587 text.append(TAB_CHARACTER);
1588 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1589 int search_elements_length = search_elements.getLength();
1590 for(int i = 0; i < search_elements_length; i++) {
1591 Element search_element = (Element) search_elements.item(i);
1592 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1593 text.append(SPACE_CHARACTER);
1594 }
1595 return text.substring(0, text.length() - 1);
1596 }
1597 else {
1598 return null;
1599 }
1600 }
1601
1602 static private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1603 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1604 text.append(SPACE_CHARACTER);
1605 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1606 text.append(SPACE_CHARACTER);
1607 text.append(TAB_CHARACTER);
1608 text.append(SPEECH_CHARACTER);
1609 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1610 text.append(EXCLAMATION_CHARACTER);
1611 }
1612 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1613 if(!show_extracted_namespace && content_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1614 content_str = content_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1615 }
1616 text.append(content_str);
1617 content_str = null;
1618 text.append(SEPARATOR_CHARACTER);
1619 text.append(XMLTools.getValue(command_element));
1620 text.append(SEPARATOR_CHARACTER);
1621 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1622 if(options_str.length() > 0) {
1623 text.append(options_str);
1624 }
1625 options_str = null;
1626 text.append(SPEECH_CHARACTER);
1627 return text.toString();
1628 }
1629
1630 static private String subcollectionDefaultIndexToString(Element command_element) {
1631 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1632 text.append(TAB_CHARACTER);
1633 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1634 int content_elements_length = content_elements.getLength();
1635 for(int j = 0; j < content_elements_length; j++) {
1636 Element content_element = (Element) content_elements.item(j);
1637 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1638 if(j < content_elements_length - 1) {
1639 text.append(StaticStrings.COMMA_CHARACTER);
1640 }
1641 }
1642 return text.toString();
1643 }
1644
1645 static private String subcollectionIndexesToString(Element command_element) {
1646 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1647 text.append(TAB_CHARACTER);
1648 // Retrieve all of the subcollection index partitions
1649 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1650 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1651 if(subcollectionindex_elements_length == 0) {
1652 return null;
1653 }
1654 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1655 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1656 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1657 int content_elements_length = content_elements.getLength();
1658 for(int k = 0; k < content_elements_length; k++) {
1659 Element content_element = (Element) content_elements.item(k);
1660 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1661 if(k < content_elements_length - 1) {
1662 text.append(StaticStrings.COMMA_CHARACTER);
1663 }
1664 }
1665 if(j < subcollectionindex_elements_length - 1) {
1666 text.append(SPACE_CHARACTER);
1667 }
1668 }
1669 return text.toString();
1670 }
1671
1672 static private String supercollectionToString(Element command_element) {
1673 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1674 int content_elements_length = content_elements.getLength();
1675 if(content_elements_length > 1) {
1676 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1677 text.append(TAB_CHARACTER);
1678 for(int j = 0; j < content_elements_length; j++) {
1679 Element content_element = (Element) content_elements.item(j);
1680 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1681 if(j < content_elements_length - 1) {
1682 text.append(SPACE_CHARACTER);
1683 }
1684 }
1685 return text.toString();
1686 }
1687 return null;
1688 }
1689
1690 static private String unknownToString(Element command_element) {
1691 return XMLTools.getValue(command_element);
1692 }
1693
1694 /** 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.
1695 * @param writer the BufferedWriter to which the str will be written
1696 * @param str the String to be written
1697 */
1698 private void write(BufferedWriter writer, String str)
1699 throws IOException {
1700 writer.write(str, 0, str.length());
1701 }
1702}
Note: See TracBrowser for help on using the repository browser.