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

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

Replaced some "PlugIn" with "Plugin".

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