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

Last change on this file since 10250 was 10049, checked in by chi, 19 years ago

If the buildtype does not contain any value, it means that buildtype was not
selected. Thus, we don't want to write it into collect.cfg file.

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