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

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

removed some leftover setMnemonics

  • Property svn:keywords set to Author Date Id Revision
File size: 68.5 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.util.*;
33import javax.swing.*;
34import org.greenstone.gatherer.Configuration;
35import org.greenstone.gatherer.DebugStream;
36import org.greenstone.gatherer.Gatherer;
37import org.greenstone.gatherer.gui.GLIButton;
38import org.greenstone.gatherer.metadata.MetadataElement;
39import org.greenstone.gatherer.metadata.MetadataSetManager;
40import org.greenstone.gatherer.metadata.MetadataTools;
41import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
42import org.greenstone.gatherer.util.DOMTree;
43import org.greenstone.gatherer.util.Codec;
44import org.greenstone.gatherer.util.StaticStrings;
45import org.greenstone.gatherer.util.XMLTools;
46import org.greenstone.gatherer.util.ZipTools;
47import org.w3c.dom.*;
48
49/** This class provides either access to a pseudo-G3 document, or parses a collect.cfg file in such a way as to provide an xml-type view of its content. This later version is useful as it allows the manipulation and free form editing of a legacy collect.cfg file while still allowing the various CDM data managers to base themselves directly on this model (whereas they used to be independant ListModels which clobbered the ordering of unparsed commands).
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(TRUE_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 try {
832
833 Element collect_cfg_element = document.getDocumentElement();
834 // Read in the file one command at a time.
835 InputStream istream = new FileInputStream(collect_cfg_file);
836 Reader in_reader = new InputStreamReader(istream, ENCODING);
837 BufferedReader in = new BufferedReader(in_reader);
838 String command_str = null;
839 while((command_str = in.readLine()) != null) {
840 boolean append_element = true;
841 Element command_element = null;
842 // A command may be broken over several lines.
843 command_str = command_str.trim();
844 boolean eof = false;
845 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) {
846 String next_line = in.readLine();
847 if(next_line != null) {
848 next_line = next_line.trim();
849 if(next_line.length() > 0) {
850 // Remove the new line character
851 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
852 // And append the next line, which due to the test above must be non-zero length
853 command_str = command_str + next_line;
854 }
855 next_line = null;
856 }
857 // If we've reached the end of the file theres nothing more we can do
858 else {
859 eof = true;
860 }
861 }
862 // If there is still a new line character, then we remove it and hope for the best
863 if(command_str.endsWith(NEWLINE_CHARACTER)) {
864 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
865 }
866 // Now we've either got a command to parse...
867 if(command_str.length() != 0) {
868 // Start trying to figure out what it is
869 //StringTokenizer tokenizer = new StringTokenizer(command_str);
870 // 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.
871 CommandTokenizer tokenizer = new CommandTokenizer(command_str, in);
872 String command_type = tokenizer.nextToken().toLowerCase();
873 // 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
874 if(command_element == null && command_type.equals(CLASSIFY_STR)) {
875 command_element = parseClassify(command_str);
876 }
877 if(command_element == null && command_type.equals(FORMAT_STR)) {
878 command_element = parseFormat(tokenizer); // Revised to handle multiple lines
879 }
880 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) {
881 command_element = parseIndex(command_str);
882 }
883 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) {
884
885 command_element = parseIndexDefault(command_str);
886 }
887 if(command_element == null && command_type.equals(LANGUAGES_STR)) {
888 command_element = parseLanguage(command_str);
889 }
890 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) {
891 command_element = parseLanguageDefault(command_str);
892 }
893 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) {
894 command_element = parseLevels(command_str);
895 }
896 if(command_element == null && (command_type.equals(LEVEL_DEFAULT_STR) || command_type.equals(COMMENTED_LEVEL_DEFAULT_STR))) {
897
898 command_element = parseLevelDefault(command_str);
899 }
900
901 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) {
902 command_element = parseMetadata(tokenizer); // Revised to handle multiple lines
903 }
904 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))) {
905 command_element = parseMetadataSpecial(command_str);
906 }
907 if(command_element == null && command_type.equals(PLUGIN_STR)) {
908 command_element = parsePlugin(command_str);
909 }
910 // leave here for backwards compatibility
911 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) {
912 command_element = parseSearchType(command_str);
913 }
914 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) {
915 command_element = parseSubCollection(command_str);
916 }
917 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) {
918 command_element = parseSubCollectionDefaultIndex(command_str);
919 }
920 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) {
921 command_element = parseSubCollectionIndex(command_str);
922 }
923 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) {
924 command_element = parseSuperCollection(command_str);
925 }
926 // Doesn't match any known type
927 command_type = null;
928 if(command_element == null) {
929 // No-one knows what to do with this command, so we create an Unknown command element
930 command_element = document.createElement(UNKNOWN_ELEMENT);
931 XMLTools.setValue(command_element, command_str);
932 }
933 }
934 // Or an empty line to remember for later
935 else {
936 command_element = document.createElement(NEWLINE_ELEMENT);
937 }
938 // 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
939 //if(append_element) {
940 collect_cfg_element.appendChild(command_element);
941 //}
942 }
943
944 }
945 catch(Exception exception) {
946 DebugStream.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
947 DebugStream.printStackTrace(exception);
948 }
949 }
950
951 private Element parseClassify(String command_str) {
952 Element command_element = null;
953 try {
954 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
955 // 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).
956 if(tokenizer.countTokens() >= 2) { // Must support "classify Phind" (no args)
957 command_element = document.createElement(CLASSIFY_ELEMENT);
958 // First token is classify
959 tokenizer.nextToken();
960 // The next token is the classifier type
961 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
962 // Now we parse out the remaining arguments into a hashmapping from name to value
963 HashMap arguments = parseArguments(tokenizer);
964 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
965 Iterator names = arguments.keySet().iterator();
966 while(names.hasNext()) {
967 String name = (String) names.next();
968 String value = (String) arguments.get(name); // Can be null
969 // The metadata argument gets added as the content attribute
970 if (name.equals(METADATA_ARGUMENT) && value != null) {
971 // Add the extracted namespace onto un-namespaced metadata names
972 StringTokenizer string_tokenizer = new StringTokenizer(value, ",");
973 value = "";
974 while (string_tokenizer.hasMoreElements()) {
975 String token = (String) string_tokenizer.nextElement();
976
977 if (token.indexOf(StaticStrings.NS_SEP) == -1) {
978 token = StaticStrings.EXTRACTED_NAMESPACE + token;
979 }
980 else {
981 MetadataElement metadata_element = MetadataTools.getMetadataElementWithName(token);
982 if (metadata_element != null) {
983 token = metadata_element.getDisplayName();
984 }
985 }
986
987 if (!value.equals("")) {
988 value = value + ",";
989 }
990 value = value + token;
991 }
992 }
993 // Everything else is an Option Element
994 Element option_element = document.createElement(OPTION_ELEMENT);
995 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
996 if(value != null) {
997 // Remove any speech marks appended in strings containing whitespace
998 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
999 value = value.substring(1, value.length() - 1);
1000 }
1001 XMLTools.setValue(option_element, value);
1002 }
1003 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1004 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1005 command_element.appendChild(option_element);
1006 option_element = null;
1007 name = null;
1008 value = null;
1009 }
1010 names = null;
1011 arguments = null;
1012 }
1013 tokenizer = null;
1014 }
1015 catch(Exception error) {
1016 }
1017 return command_element;
1018 }
1019
1020 private Element parseFormat(CommandTokenizer tokenizer) {
1021 Element command_element = null;
1022 try {
1023 command_element = document.createElement(FORMAT_ELEMENT);
1024 String name_str = tokenizer.nextToken();
1025 String value_str = tokenizer.nextToken();
1026 if(name_str != null && value_str != null) {
1027 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1028 // If the value is true or false we add it as an attribute
1029 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
1030 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
1031 }
1032 // Otherwise it gets added as a text node
1033 else {
1034 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1035 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1036 XMLTools.setValue(command_element, value_str);
1037 }
1038 }
1039 else {
1040 command_element = null;
1041 }
1042 name_str = null;
1043 value_str = null;
1044 }
1045 catch (Exception exception) {
1046 DebugStream.printStackTrace(exception);
1047 command_element = null;
1048 }
1049 return command_element;
1050 }
1051
1052 private Element parseIndex(String command_str) {
1053 Element command_element = null;
1054 try {
1055 StringTokenizer tokenizer = new StringTokenizer(command_str);
1056 String command = tokenizer.nextToken();
1057 command_element = document.createElement(INDEXES_ELEMENT);
1058 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1059 command = null;
1060 if(!tokenizer.hasMoreTokens()) {
1061
1062 // there are no indexes
1063 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1064 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1065 tokenizer = null;
1066 return command_element;
1067 }
1068
1069 while(tokenizer.hasMoreTokens()) {
1070 Element index_element = document.createElement(INDEX_ELEMENT);
1071 String index_str = tokenizer.nextToken();
1072 // 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.
1073 boolean old_index;
1074 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1075 old_index = true;
1076 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1077 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1078 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1079 }
1080 else {
1081 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1082 old_index = false;
1083 }
1084 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1085 while(content_tokenizer.hasMoreTokens()) {
1086 Element content_element = document.createElement(CONTENT_ELEMENT);
1087 String content_str = content_tokenizer.nextToken();
1088 // 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.
1089 if(content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1090 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1091 // Our special strings are OK.
1092 }
1093 else {
1094 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1095 }
1096 }
1097 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1098 index_element.appendChild(content_element);
1099 content_element = null;
1100 }
1101 content_tokenizer = null;
1102 index_str = null;
1103 command_element.appendChild(index_element);
1104 index_element = null;
1105 }
1106 tokenizer = null;
1107 }
1108 catch (Exception exception) {
1109 exception.printStackTrace();
1110 }
1111 return command_element;
1112 }
1113
1114 private Element parseIndexDefault(String command_str) {
1115 Element command_element = null;
1116 try {
1117 StringTokenizer tokenizer = new StringTokenizer(command_str);
1118 if(tokenizer.countTokens() >= 2) {
1119 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1120 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1121 String index_str = tokenizer.nextToken();
1122 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1123 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1124 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1125 while(content_tokenizer.hasMoreTokens()) {
1126 Element content_element = document.createElement(CONTENT_ELEMENT);
1127 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1128 command_element.appendChild(content_element);
1129 content_element = null;
1130 }
1131 content_tokenizer = null;
1132 content_str = null;
1133 content_str = null;
1134 index_str = null;
1135 }
1136 tokenizer = null;
1137 }
1138 catch (Exception exception) {
1139 }
1140 return command_element;
1141 }
1142
1143 private Element parseLanguage(String command_str) {
1144 Element command_element = null;
1145 try {
1146 StringTokenizer tokenizer = new StringTokenizer(command_str);
1147 tokenizer.nextToken();
1148 if(tokenizer.hasMoreTokens()) {
1149 command_element = document.createElement(LANGUAGES_ELEMENT);
1150 while(tokenizer.hasMoreTokens()) {
1151 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1152 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1153 command_element.appendChild(language_element);
1154 language_element = null;
1155 }
1156 }
1157 tokenizer = null;
1158 }
1159 catch (Exception exception) {
1160 }
1161 return command_element;
1162 }
1163
1164 private Element parseLanguageDefault(String command_str) {
1165 Element command_element = null;
1166 try {
1167 StringTokenizer tokenizer = new StringTokenizer(command_str);
1168 if(tokenizer.countTokens() >= 2) {
1169 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1170 tokenizer.nextToken();
1171 String default_language_str = tokenizer.nextToken();
1172 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1173 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1174 default_language_str = null;
1175 }
1176 tokenizer = null;
1177 }
1178 catch (Exception exception) {
1179 }
1180 return command_element;
1181 }
1182
1183 private Element parseLevels(String command_str) {
1184 Element command_element = null;
1185 try {
1186 StringTokenizer tokenizer = new StringTokenizer(command_str);
1187 // First token is command type (levels)
1188 String command = tokenizer.nextToken();
1189 if(tokenizer.hasMoreTokens()) {
1190 command_element = document.createElement(LEVELS_ELEMENT);
1191 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1192 while(tokenizer.hasMoreTokens()) {
1193 Element level_element = document.createElement(LEVEL_ELEMENT);
1194 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1195 command_element.appendChild(level_element);
1196 level_element = null;
1197 }
1198 }
1199 command = null;
1200 }
1201 catch(Exception exception) {
1202 }
1203 return command_element;
1204 }
1205
1206 private Element parseLevelDefault(String command_str) {
1207 Element command_element = null;
1208 try {
1209 StringTokenizer tokenizer = new StringTokenizer(command_str);
1210 if(tokenizer.countTokens() >= 2) {
1211 command_element = document.createElement(LEVEL_DEFAULT_ELEMENT);
1212 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(LEVEL_DEFAULT_STR) ? TRUE_STR : FALSE_STR)); // is it commented out or not?
1213 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1214 }
1215
1216 tokenizer = null;
1217 }
1218 catch (Exception exception) {
1219 }
1220 return command_element;
1221 }
1222
1223 private Element parseMetadata(CommandTokenizer tokenizer) {
1224 Element command_element = null;
1225 try {
1226 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1227 String name_str = tokenizer.nextToken();
1228 String value_str = tokenizer.nextToken();
1229 if(name_str != null && value_str != null) {
1230 String language_str = Configuration.getLanguage();
1231 // Check if the value string is actually a language string
1232 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1233 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1234 value_str = tokenizer.nextToken();
1235 }
1236 if(value_str != null) {
1237 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1238 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1239 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1240 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1241 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1242 XMLTools.setValue(command_element, value_str);
1243 }
1244 else {
1245 command_element = null;
1246 }
1247 language_str = null;
1248 }
1249 else {
1250 command_element = null;
1251 }
1252 name_str = null;
1253 value_str = null;
1254 }
1255 catch (Exception exception) {
1256 DebugStream.printStackTrace(exception);
1257 command_element = null;
1258 }
1259 return command_element;
1260 }
1261
1262 private Element parseMetadataSpecial(String command_str) {
1263 Element command_element = null;
1264 try {
1265 StringTokenizer tokenizer = new StringTokenizer(command_str);
1266 if(tokenizer.countTokens() >= 2) {
1267 String name_str = tokenizer.nextToken();
1268 String value_str = tokenizer.nextToken();
1269 if (name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1270 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1271 }
1272 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1273 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1274 }
1275 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1276 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1277 }
1278 else if (name_str.equals(BUILDTYPE_STR)) {
1279 command_element = document.createElement(BUILDTYPE_ELEMENT);
1280 }
1281 if(command_element != null) {
1282 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1283 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1284 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1285 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1286 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1287 value_str = value_str.substring(1, value_str.length() - 1);
1288 }
1289 XMLTools.setValue(command_element, value_str);
1290 }
1291 value_str = null;
1292 name_str = null;
1293 }
1294 tokenizer = null;
1295 }
1296 catch (Exception exception) {
1297 }
1298 return command_element;
1299 }
1300
1301 private Element parsePlugin(String command_str) {
1302 Element command_element = null;
1303 boolean use_metadata_files = false;
1304 try {
1305 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1306 // 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).
1307 if(tokenizer.countTokens() >= 2) {
1308 command_element = document.createElement(PLUGIN_ELEMENT);
1309 // First token is plugin
1310 tokenizer.nextToken();
1311 // The next token is the type
1312 String type = tokenizer.nextToken();
1313 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1314 // Now we parse out the remaining arguments into a hashmapping from name to value
1315 HashMap arguments = parseArguments(tokenizer);
1316 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1317 Iterator names = arguments.keySet().iterator();
1318 while(names.hasNext()) {
1319 String name = (String) names.next();
1320 String value = (String) arguments.get(name); // Can be null
1321 Element option_element = document.createElement(OPTION_ELEMENT);
1322 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1323 use_metadata_files = true;
1324 }
1325 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1326 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1327 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1328 if(value != null) {
1329 // Remove any speech marks appended in strings containing whitespace
1330 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1331 value = value.substring(1, value.length() - 1);
1332 }
1333 if(name.equals(METADATA_ARGUMENT)) {
1334 // 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.
1335 if(value.indexOf(StaticStrings.NS_SEP) == -1) {
1336 value = StaticStrings.EXTRACTED_NAMESPACE + value;
1337 }
1338 }
1339 XMLTools.setValue(option_element, value);
1340 }
1341 command_element.appendChild(option_element);
1342 option_element = null;
1343 name = null;
1344 value = null;
1345 }
1346
1347 // We must have some RecPlug options: use_metadata_files
1348 if (type.equals(RECPLUG_STR)) {
1349 if (!use_metadata_files) {
1350 Element option_element = document.createElement(OPTION_ELEMENT);
1351 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1352 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1353 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1354 command_element.appendChild(option_element);
1355 option_element = null;
1356 }
1357 }
1358 type = null;
1359 names = null;
1360 arguments = null;
1361 }
1362 tokenizer = null;
1363 }
1364 catch(Exception exception) {
1365 }
1366 return command_element;
1367 }
1368
1369 /* search types are now handled as formats - leave this here to convert in case we have an old config file */
1370 private Element parseSearchType(String command_str) {
1371 Element command_element = null;
1372 try {
1373 StringTokenizer tokenizer = new StringTokenizer(command_str);
1374 // First token is command type (searchtype)
1375 tokenizer.nextToken();
1376 if(tokenizer.hasMoreTokens()) {
1377 command_element = document.createElement(FORMAT_ELEMENT);
1378 command_element.setAttribute(NAME_ATTRIBUTE, "SearchTypes");
1379 String value = tokenizer.nextToken();
1380 while(tokenizer.hasMoreTokens()) {
1381 value += ","+tokenizer.nextToken();
1382 }
1383 value = Codec.transform(value, Codec.GREENSTONE_TO_DOM);
1384 XMLTools.setValue(command_element, value);
1385
1386 }
1387 }
1388 catch(Exception exception) {
1389 }
1390 return command_element;
1391 }
1392
1393 private Element parseSubCollection(String command_str) {
1394 Element command_element = null;
1395 try {
1396 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1397 if(tokenizer.countTokens() >= 3) {
1398 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1399 // First token is command type
1400 tokenizer.nextToken();
1401 // Then subcollection identifier
1402 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1403 // Then finally the pattern used to build the subcollection partition
1404 String full_pattern_str = tokenizer.nextToken();
1405 // Set inclusion/exclusion flag and remove any exclamation mark
1406 boolean exclusion = full_pattern_str.startsWith(EXCLAMATION_CHARACTER);
1407 if (exclusion) {
1408 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length());
1409 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1410 }
1411 else {
1412 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1413 }
1414 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1415 if(pattern_tokenizer.countTokens() >= 2) {
1416 String content_str = pattern_tokenizer.nextToken();
1417 // 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.
1418 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1419 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1420 }
1421 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1422 XMLTools.setValue(command_element, pattern_tokenizer.nextToken());
1423 if(pattern_tokenizer.hasMoreTokens()) {
1424 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1425 }
1426 }
1427 pattern_tokenizer = null;
1428 }
1429 }
1430 catch(Exception exception) {
1431 exception.printStackTrace();
1432 }
1433 return command_element;
1434 }
1435
1436 private Element parseSubCollectionDefaultIndex(String command_str) {
1437 Element command_element = null;
1438 try {
1439 StringTokenizer tokenizer = new StringTokenizer(command_str);
1440 if(tokenizer.countTokens() == 2) {
1441 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1442 tokenizer.nextToken();
1443 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1444 String content_str = tokenizer.nextToken();
1445 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1446 while(content_tokenizer.hasMoreTokens()) {
1447 Element content_element = document.createElement(CONTENT_ELEMENT);
1448 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1449 command_element.appendChild(content_element);
1450 content_element = null;
1451 }
1452 content_tokenizer = null;
1453 content_str = null;
1454 }
1455 tokenizer = null;
1456 }
1457 catch(Exception exception) {
1458 }
1459 return command_element;
1460 }
1461
1462 private Element parseSubCollectionIndex(String command_str) {
1463 Element command_element = null;
1464 try {
1465 StringTokenizer tokenizer = new StringTokenizer(command_str);
1466 tokenizer.nextToken();
1467 if(tokenizer.hasMoreTokens()) {
1468 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1469 }
1470 while(tokenizer.hasMoreTokens()) {
1471 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1472 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1473 String content_str = tokenizer.nextToken();
1474 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1475 while(content_tokenizer.hasMoreTokens()) {
1476 Element content_element = document.createElement(CONTENT_ELEMENT);
1477 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1478 subcollectionindex_element.appendChild(content_element);
1479 content_element = null;
1480 }
1481 content_tokenizer = null;
1482 content_str = null;
1483 command_element.appendChild(subcollectionindex_element);
1484 subcollectionindex_element = null;
1485 }
1486 tokenizer = null;
1487 }
1488 catch (Exception exception) {
1489 }
1490 return command_element;
1491 }
1492
1493 private Element parseSuperCollection(String command_str) {
1494 Element command_element = null;
1495 try {
1496 StringTokenizer tokenizer = new StringTokenizer(command_str);
1497 if(tokenizer.countTokens() >= 3) {
1498 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1499 tokenizer.nextToken();
1500 while(tokenizer.hasMoreTokens()) {
1501 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1502 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1503 command_element.appendChild(collection_element);
1504 collection_element = null;
1505 }
1506 }
1507 tokenizer = null;
1508 }
1509 catch(Exception exception) {
1510 }
1511 return command_element;
1512 }
1513
1514 static private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1515 StringBuffer text = new StringBuffer();
1516 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1517 text.append(PLUGIN_STR);
1518 text.append(TAB_CHARACTER);
1519 text.append(TAB_CHARACTER);
1520 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1521 // Retrieve, and output, the arguments
1522 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1523 int option_elements_length = option_elements.getLength();
1524 if(option_elements_length > 0) {
1525 text.append(SPACE_CHARACTER);
1526 for(int j = 0; j < option_elements_length; j++) {
1527 Element option_element = (Element) option_elements.item(j);
1528 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1529 text.append(StaticStrings.MINUS_CHARACTER);
1530 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1531 String value_str = XMLTools.getValue(option_element);
1532 if(!show_extracted_namespace && value_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1533 value_str = value_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1534 }
1535 if(value_str.length() > 0) {
1536 text.append(SPACE_CHARACTER);
1537 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1538 text.append(value_str);
1539 }
1540 else {
1541 text.append(SPEECH_CHARACTER);
1542 text.append(value_str);
1543 text.append(SPEECH_CHARACTER);
1544 }
1545 }
1546 value_str = null;
1547 if(j < option_elements_length - 1) {
1548 text.append(SPACE_CHARACTER);
1549 }
1550 }
1551 option_element = null;
1552 }
1553 }
1554 option_elements = null;
1555 }
1556 return text.toString();
1557 }
1558
1559 static private String searchtypeToString(Element command_element) {
1560 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1561 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1562 text.append(TAB_CHARACTER);
1563 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1564 int search_elements_length = search_elements.getLength();
1565 for(int i = 0; i < search_elements_length; i++) {
1566 Element search_element = (Element) search_elements.item(i);
1567 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1568 text.append(SPACE_CHARACTER);
1569 }
1570 return text.substring(0, text.length() - 1);
1571 }
1572 else {
1573 return null;
1574 }
1575 }
1576
1577 static private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1578 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1579 text.append(SPACE_CHARACTER);
1580 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1581 text.append(SPACE_CHARACTER);
1582 text.append(TAB_CHARACTER);
1583 text.append(SPEECH_CHARACTER);
1584 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1585 text.append(EXCLAMATION_CHARACTER);
1586 }
1587 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1588 if(!show_extracted_namespace && content_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1589 content_str = content_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1590 }
1591 text.append(content_str);
1592 content_str = null;
1593 text.append(SEPARATOR_CHARACTER);
1594 text.append(XMLTools.getValue(command_element));
1595 text.append(SEPARATOR_CHARACTER);
1596 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1597 if(options_str.length() > 0) {
1598 text.append(options_str);
1599 }
1600 options_str = null;
1601 text.append(SPEECH_CHARACTER);
1602 return text.toString();
1603 }
1604
1605 static private String subcollectionDefaultIndexToString(Element command_element) {
1606 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1607 text.append(TAB_CHARACTER);
1608 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1609 int content_elements_length = content_elements.getLength();
1610 for(int j = 0; j < content_elements_length; j++) {
1611 Element content_element = (Element) content_elements.item(j);
1612 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1613 if(j < content_elements_length - 1) {
1614 text.append(StaticStrings.COMMA_CHARACTER);
1615 }
1616 }
1617 return text.toString();
1618 }
1619
1620 static private String subcollectionIndexesToString(Element command_element) {
1621 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1622 text.append(TAB_CHARACTER);
1623 // Retrieve all of the subcollection index partitions
1624 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1625 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1626 if(subcollectionindex_elements_length == 0) {
1627 return null;
1628 }
1629 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1630 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1631 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1632 int content_elements_length = content_elements.getLength();
1633 for(int k = 0; k < content_elements_length; k++) {
1634 Element content_element = (Element) content_elements.item(k);
1635 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1636 if(k < content_elements_length - 1) {
1637 text.append(StaticStrings.COMMA_CHARACTER);
1638 }
1639 }
1640 if(j < subcollectionindex_elements_length - 1) {
1641 text.append(SPACE_CHARACTER);
1642 }
1643 }
1644 return text.toString();
1645 }
1646
1647 static private String supercollectionToString(Element command_element) {
1648 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1649 int content_elements_length = content_elements.getLength();
1650 if(content_elements_length > 1) {
1651 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1652 text.append(TAB_CHARACTER);
1653 for(int j = 0; j < content_elements_length; j++) {
1654 Element content_element = (Element) content_elements.item(j);
1655 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1656 if(j < content_elements_length - 1) {
1657 text.append(SPACE_CHARACTER);
1658 }
1659 }
1660 return text.toString();
1661 }
1662 return null;
1663 }
1664
1665 static private String unknownToString(Element command_element) {
1666 return XMLTools.getValue(command_element);
1667 }
1668
1669 /** 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.
1670 * @param writer the BufferedWriter to which the str will be written
1671 * @param str the String to be written
1672 */
1673 private void write(BufferedWriter writer, String str)
1674 throws IOException {
1675 writer.write(str, 0, str.length());
1676 }
1677}
Note: See TracBrowser for help on using the repository browser.