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

Last change on this file since 10611 was 10611, checked in by kjdon, 19 years ago

don't write out collectionmeta if the value is empty

  • 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 ZipTools.zipup(Gatherer.getCollectDirectoryPath(), collection_name, "collect.cfg", null, "", "");
514 RemoteGreenstoneServer.upload_url_zip(collection_name, "etc", "", null);
515 }
516 }
517 catch (Exception exception) {
518 DebugStream.println("Error in CollectionConfiguration.save(boolean): " + exception);
519 DebugStream.printStackTrace(exception);
520 }
521 }
522 }
523
524 /** ************************** Private Methods ***************************/
525
526 static private String classifyToString(Element command_element, boolean show_extracted_namespace)
527 {
528 StringBuffer text = new StringBuffer(CLASSIFY_STR);
529 text.append(TAB_CHARACTER);
530 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
531 text.append(SPACE_CHARACTER);
532 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
533 int option_elements_length = option_elements.getLength();
534 for(int j = 0; j < option_elements_length; j++) {
535 Element option_element = (Element) option_elements.item(j);
536 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
537 text.append(StaticStrings.MINUS_CHARACTER);
538 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
539 String value_str = XMLTools.getValue(option_element);
540
541 // Remove the extracted metadata namespaces if required
542 if (value_str.length() > 0) {
543 StringTokenizer string_tokenizer = new StringTokenizer(value_str, ",");
544 value_str = "";
545 while (string_tokenizer.hasMoreElements()) {
546 String raw_token = (String) string_tokenizer.nextElement();
547 String token = raw_token.trim();
548 MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
549 if (metadata_element != null) {
550 token = metadata_element.getFullName();
551 }
552
553 if (token.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
554 token = token.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
555 }
556
557 value_str = value_str + token;
558 if (string_tokenizer.hasMoreElements()) {
559 value_str = value_str + ",";
560 }
561 }
562 }
563
564 text.append(SPACE_CHARACTER);
565 if (value_str.indexOf(SPACE_CHARACTER) == -1) {
566 text.append(value_str);
567 }
568 else {
569 text.append(SPEECH_CHARACTER);
570 text.append(value_str);
571 text.append(SPEECH_CHARACTER);
572 }
573 value_str = null;
574 if(j < option_elements_length - 1) {
575 text.append(SPACE_CHARACTER);
576 }
577 }
578 option_element = null;
579 }
580 option_elements = null;
581 return text.toString();
582 }
583
584 static private String formatToString(Element command_element, boolean show_extracted_namespace) {
585 StringBuffer text = new StringBuffer(FORMAT_STR);
586 text.append(SPACE_CHARACTER);
587 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
588 text.append(SPACE_CHARACTER);
589 String value_str = command_element.getAttribute(VALUE_ATTRIBUTE);
590 if(value_str.length() != 0) {
591 text.append(value_str);
592 }
593 else {
594 // Remember to encode format string to Greenstone specification
595 value_str = Codec.transform(XMLTools.getValue(command_element), Codec.DOM_TO_GREENSTONE);
596 // Remove any references to a namespace for extracted metadata
597 if (!show_extracted_namespace) {
598 String match_string = "\\[" + MetadataSetManager.EXTRACTED_METADATA_NAMESPACE + "\\.";
599 value_str = value_str.replaceAll(match_string, "[");
600 }
601
602 text.append(SPEECH_CHARACTER);
603 text.append(value_str);
604 text.append(SPEECH_CHARACTER);
605 }
606 value_str = null;
607 return text.toString();
608 }
609
610 /** Retrieve or create the indexes Element. */
611 static private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value) {
612 Element document_element = document.getDocumentElement();
613 NodeList elements = document_element.getElementsByTagName(name);
614 int elements_length = elements.getLength();
615 if(elements_length > 0) {
616 if(conditional_attribute == null) {
617 document_element = null;
618 return (Element) elements.item(0);
619 }
620 else {
621 for(int i = 0; i < elements_length; i++) {
622 Element element = (Element) elements.item(i);
623 if(element.getAttribute(conditional_attribute).equals(required_value)) {
624 document_element = null;
625 return element;
626 }
627 element = null;
628 }
629 }
630 }
631 // Create the element
632 Element element = document.createElement(name);
633 // If there was a property set it
634 if(conditional_attribute != null) {
635 element.setAttribute(conditional_attribute, required_value);
636 }
637 Node target_node = findInsertionPoint(element);
638 if(target_node != null) {
639 document_element.insertBefore(element, target_node);
640 }
641 else {
642 document_element.appendChild(element);
643 }
644 document_element = null;
645 return element;
646 }
647
648 static private String indexesToString(Element command_element, boolean show_extracted_namespace) {
649 boolean comment_only = false;
650 StringBuffer text = new StringBuffer("");
651 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
652 text.append("#");
653 comment_only = true;
654 }
655 text.append(INDEX_STR);
656 text.append(TAB_CHARACTER);
657 if(!comment_only) {
658 text.append(TAB_CHARACTER);
659 }
660 NodeList index_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
661 if (index_elements.getLength() == 0) { // no indexes
662 return "";
663 }
664 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
665 int index_elements_length = index_elements.getLength();
666 for(int j = 0; j < index_elements_length; j++) {
667 Element index_element = (Element) index_elements.item(j);
668 String level_str = index_element.getAttribute(LEVEL_ATTRIBUTE);
669 if(level_str.length() > 0) {
670 text.append(level_str);
671 text.append(StaticStrings.COLON_CHARACTER);
672 }
673 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT);
674 int content_elements_length = content_elements.getLength();
675 // Don't output anything if no indexes are set
676 if(content_elements_length == 0) {
677 return null;
678 }
679 for(int k = 0; k < content_elements_length; k++) {
680 Element content_element = (Element) content_elements.item(k);
681 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
682 if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
683 name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
684 }
685 text.append(name_str);
686 name_str = null;
687 if(k < content_elements_length - 1) {
688 text.append(StaticStrings.COMMA_CHARACTER);
689 }
690 content_element = null;
691 }
692 if(j < index_elements_length - 1) {
693 text.append(SPACE_CHARACTER);
694 }
695 content_elements = null;
696 index_element = null;
697 }
698 index_elements = null;
699 return text.toString();
700 }
701
702 static private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
703 StringBuffer text = new StringBuffer("");
704 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
705 text.append("#");
706 }
707 text.append(INDEX_DEFAULT_STR);
708 text.append(TAB_CHARACTER);
709 text.append(command_element.getAttribute(LEVEL_ATTRIBUTE));
710 text.append(StaticStrings.COLON_CHARACTER);
711 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
712 int content_elements_length = content_elements.getLength();
713 for(int j = 0; j < content_elements_length; j++) {
714 Element content_element = (Element) content_elements.item(j);
715 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
716 if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
717 name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
718 }
719 text.append(name_str);
720 name_str = null;
721 if(j < content_elements_length - 1) {
722 text.append(StaticStrings.COMMA_CHARACTER);
723 }
724 content_element = null;
725 }
726 content_elements = null;
727 return text.toString();
728 }
729
730 static private String languagesToString(Element command_element) {
731 StringBuffer text = new StringBuffer(LANGUAGES_STR);
732 text.append(TAB_CHARACTER);
733 // Retrieve all the languages and write them out in a space separated list
734 NodeList language_elements = command_element.getElementsByTagName(LANGUAGE_ELEMENT);
735 int language_elements_length = language_elements.getLength();
736 if(language_elements_length == 0) {
737 return null;
738 }
739 for(int j = 0; j < language_elements_length; j++) {
740 Element language_element = (Element) language_elements.item(j);
741 text.append(language_element.getAttribute(NAME_ATTRIBUTE));
742 if(j < language_elements_length - 1) {
743 text.append(SPACE_CHARACTER);
744 }
745 }
746 return text.toString();
747 }
748
749 static private String languageDefaultToString(Element command_element) {
750 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR);
751 text.append(TAB_CHARACTER);
752 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
753 return text.toString();
754 }
755
756 static private String levelsToString(Element command_element) {
757 StringBuffer text = new StringBuffer("");
758 if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
759 text.append("#");
760 }
761 text.append(LEVELS_STR);
762 text.append(TAB_CHARACTER);
763 text.append(TAB_CHARACTER);
764 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
765 int content_elements_length = content_elements.getLength();
766 // Don't output anything if no levels are set.
767 if(content_elements_length == 0) {
768 return null;
769 }
770 for(int i = 0; i < content_elements_length; i++) {
771 Element content_element = (Element) content_elements.item(i);
772 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
773 text.append(SPACE_CHARACTER);
774 }
775 return text.substring(0, text.length() - 1);
776 }
777
778 static private String metadataToString(Element command_element, boolean text_value) {
779 // lets first check the value - if its empty, don't bother sticking it in the config file
780 String value_str = XMLTools.getValue(command_element);
781 if (value_str.equals("")) {
782 return "";
783 }
784 boolean special = false;
785
786 StringBuffer text = new StringBuffer("");
787 String name_str = command_element.getAttribute(NAME_ATTRIBUTE);
788 // 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.
789 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)|| name_str.equals(BUILDTYPE_STR) ) {
790 text.append(name_str);
791 text.append(TAB_CHARACTER);
792 special = true;
793 }
794 else if (name_str.equals(COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(COLLECTIONMETADATA_PUBLIC_STR) ) {
795 text.append(name_str);
796 text.append(TAB_CHARACTER);
797 text.append(TAB_CHARACTER);
798 special = true;
799 }
800 else {
801 text.append(COLLECTIONMETADATA_STR);
802 text.append(TAB_CHARACTER);
803 text.append(name_str);
804 text.append(SPACE_CHARACTER);
805 String language_str = command_element.getAttribute(LANGUAGE_ATTRIBUTE);
806 text.append(LBRACKET_CHARACTER);
807 text.append(LANGUAGE_ARGUMENT);
808 text.append(language_str);
809 text.append(RBRACKET_CHARACTER);
810 text.append(SPACE_CHARACTER);
811
812 if(known_metadata != null) {
813 known_metadata.add(name_str);
814 }
815 language_str = null;
816 }
817 name_str = null;
818
819 // 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
820 if(text_value == CollectionMeta.TEXT) {
821 value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT);
822 }
823 else {
824 value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE);
825 }
826
827 // We don't wrap the email addresses in quotes, nor the other special metadata
828 if(special) {
829 text.append(value_str);
830 }
831 else {
832 text.append(SPEECH_CHARACTER);
833 text.append(value_str);
834 text.append(SPEECH_CHARACTER);
835 }
836 value_str = null;
837 return text.toString();
838 }
839
840 /** Parse a collect.cfg into a DOM model representation.
841 * note we are ignoring 2.39 compatibility now. */
842 private void parse(File collect_cfg_file) {
843 try {
844
845 Element collect_cfg_element = document.getDocumentElement();
846 // Read in the file one command at a time.
847 InputStream istream = new FileInputStream(collect_cfg_file);
848 Reader in_reader = new InputStreamReader(istream, ENCODING);
849 BufferedReader in = new BufferedReader(in_reader);
850 String command_str = null;
851 while((command_str = in.readLine()) != null) {
852 boolean append_element = true;
853 Element command_element = null;
854 // A command may be broken over several lines.
855 command_str = command_str.trim();
856 boolean eof = false;
857 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) {
858 String next_line = in.readLine();
859 if(next_line != null) {
860 next_line = next_line.trim();
861 if(next_line.length() > 0) {
862 // Remove the new line character
863 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
864 // And append the next line, which due to the test above must be non-zero length
865 command_str = command_str + next_line;
866 }
867 next_line = null;
868 }
869 // If we've reached the end of the file theres nothing more we can do
870 else {
871 eof = true;
872 }
873 }
874 // If there is still a new line character, then we remove it and hope for the best
875 if(command_str.endsWith(NEWLINE_CHARACTER)) {
876 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER));
877 }
878 // Now we've either got a command to parse...
879 if(command_str.length() != 0) {
880 // Start trying to figure out what it is
881 //StringTokenizer tokenizer = new StringTokenizer(command_str);
882 // 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.
883 CommandTokenizer tokenizer = new CommandTokenizer(command_str, in);
884 String command_type = tokenizer.nextToken().toLowerCase();
885 // 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
886 if(command_element == null && command_type.equals(CLASSIFY_STR)) {
887 command_element = parseClassify(command_str);
888 }
889 if(command_element == null && command_type.equals(FORMAT_STR)) {
890 command_element = parseFormat(tokenizer); // Revised to handle multiple lines
891 }
892 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) {
893 command_element = parseIndex(command_str);
894 }
895 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) {
896
897 command_element = parseIndexDefault(command_str);
898 }
899 if(command_element == null && command_type.equals(LANGUAGES_STR)) {
900 command_element = parseLanguage(command_str);
901 }
902 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) {
903 command_element = parseLanguageDefault(command_str);
904 }
905 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) {
906 command_element = parseLevels(command_str);
907 }
908 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) {
909 command_element = parseMetadata(tokenizer); // Revised to handle multiple lines
910 }
911 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))) {
912 command_element = parseMetadataSpecial(command_str);
913 }
914 if(command_element == null && command_type.equals(PLUGIN_STR)) {
915 command_element = parsePlugIn(command_str);
916 }
917 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) {
918 command_element = parseSearchType(command_str);
919 }
920 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) {
921 command_element = parseSubCollection(command_str);
922 }
923 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) {
924 command_element = parseSubCollectionDefaultIndex(command_str);
925 }
926 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) {
927 command_element = parseSubCollectionIndex(command_str);
928 }
929 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) {
930 command_element = parseSuperCollection(command_str);
931 }
932 // Doesn't match any known type
933 command_type = null;
934 if(command_element == null) {
935 // No-one knows what to do with this command, so we create an Unknown command element
936 command_element = document.createElement(UNKNOWN_ELEMENT);
937 XMLTools.setValue(command_element, command_str);
938 }
939 }
940 // Or an empty line to remember for later
941 else {
942 command_element = document.createElement(NEWLINE_ELEMENT);
943 }
944 // 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
945 //if(append_element) {
946 collect_cfg_element.appendChild(command_element);
947 //}
948 }
949
950 }
951 catch(Exception exception) {
952 DebugStream.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
953 DebugStream.printStackTrace(exception);
954 }
955 }
956
957 private Element parseClassify(String command_str) {
958 Element command_element = null;
959 try {
960 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
961 // 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).
962 if(tokenizer.countTokens() >= 2) { // Must support "classify Phind" (no args)
963 command_element = document.createElement(CLASSIFY_ELEMENT);
964 // First token is classify
965 tokenizer.nextToken();
966 // The next token is the classifier type
967 command_element.setAttribute(TYPE_ATTRIBUTE, tokenizer.nextToken());
968 // Now we parse out the remaining arguments into a hashmapping from name to value
969 HashMap arguments = parseArguments(tokenizer);
970 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
971 Iterator names = arguments.keySet().iterator();
972 while(names.hasNext()) {
973 String name = (String) names.next();
974 String value = (String) arguments.get(name); // Can be null
975 // The metadata argument gets added as the content attribute
976 if (name.equals(METADATA_ARGUMENT) && value != null) {
977 // Add the extracted namespace onto un-namespaced metadata names
978 StringTokenizer string_tokenizer = new StringTokenizer(value, ",");
979 value = "";
980 while (string_tokenizer.hasMoreElements()) {
981 String token = (String) string_tokenizer.nextElement();
982
983 if (token.indexOf(StaticStrings.NS_SEP) == -1) {
984 token = StaticStrings.EXTRACTED_NAMESPACE + token;
985 }
986 else {
987 MetadataElement metadata_element = MetadataTools.getMetadataElementWithName(token);
988 if (metadata_element != null) {
989 token = metadata_element.getDisplayName();
990 }
991 }
992
993 if (!value.equals("")) {
994 value = value + ",";
995 }
996 value = value + token;
997 }
998 }
999 // Everything else is an Option Element
1000 Element option_element = document.createElement(OPTION_ELEMENT);
1001 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1002 if(value != null) {
1003 // Remove any speech marks appended in strings containing whitespace
1004 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1005 value = value.substring(1, value.length() - 1);
1006 }
1007 XMLTools.setValue(option_element, value);
1008 }
1009 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1010 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1011 command_element.appendChild(option_element);
1012 option_element = null;
1013 name = null;
1014 value = null;
1015 }
1016 names = null;
1017 arguments = null;
1018 }
1019 tokenizer = null;
1020 }
1021 catch(Exception error) {
1022 }
1023 return command_element;
1024 }
1025
1026 private Element parseFormat(CommandTokenizer tokenizer) {
1027 Element command_element = null;
1028 try {
1029 command_element = document.createElement(FORMAT_ELEMENT);
1030 String name_str = tokenizer.nextToken();
1031 String value_str = tokenizer.nextToken();
1032 if(name_str != null && value_str != null) {
1033 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1034 // If the value is true or false we add it as an attribute
1035 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
1036 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
1037 }
1038 // Otherwise it gets added as a text node
1039 else {
1040 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1041 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1042 XMLTools.setValue(command_element, value_str);
1043 }
1044 }
1045 else {
1046 command_element = null;
1047 }
1048 name_str = null;
1049 value_str = null;
1050 }
1051 catch (Exception exception) {
1052 DebugStream.printStackTrace(exception);
1053 command_element = null;
1054 }
1055 return command_element;
1056 }
1057
1058 private Element parseIndex(String command_str) {
1059 Element command_element = null;
1060 try {
1061 StringTokenizer tokenizer = new StringTokenizer(command_str);
1062 String command = tokenizer.nextToken();
1063 command_element = document.createElement(INDEXES_ELEMENT);
1064 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1065 command = null;
1066 if(!tokenizer.hasMoreTokens()) {
1067
1068 // there are no indexes
1069 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1070 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1071 tokenizer = null;
1072 return command_element;
1073 }
1074
1075 while(tokenizer.hasMoreTokens()) {
1076 Element index_element = document.createElement(INDEX_ELEMENT);
1077 String index_str = tokenizer.nextToken();
1078 // 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.
1079 boolean old_index;
1080 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1081 old_index = true;
1082 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1083 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1084 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1085 }
1086 else {
1087 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1088 old_index = false;
1089 }
1090 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1091 while(content_tokenizer.hasMoreTokens()) {
1092 Element content_element = document.createElement(CONTENT_ELEMENT);
1093 String content_str = content_tokenizer.nextToken();
1094 // 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.
1095 if(content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1096 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1097 // Our special strings are OK.
1098 }
1099 else {
1100 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1101 }
1102 }
1103 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1104 index_element.appendChild(content_element);
1105 content_element = null;
1106 }
1107 content_tokenizer = null;
1108 index_str = null;
1109 command_element.appendChild(index_element);
1110 index_element = null;
1111 }
1112 tokenizer = null;
1113 }
1114 catch (Exception exception) {
1115 exception.printStackTrace();
1116 }
1117 return command_element;
1118 }
1119
1120 private Element parseIndexDefault(String command_str) {
1121 Element command_element = null;
1122 try {
1123 StringTokenizer tokenizer = new StringTokenizer(command_str);
1124 if(tokenizer.countTokens() >= 2) {
1125 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1126 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1127 String index_str = tokenizer.nextToken();
1128 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1129 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1130 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1131 while(content_tokenizer.hasMoreTokens()) {
1132 Element content_element = document.createElement(CONTENT_ELEMENT);
1133 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1134 command_element.appendChild(content_element);
1135 content_element = null;
1136 }
1137 content_tokenizer = null;
1138 content_str = null;
1139 content_str = null;
1140 index_str = null;
1141 }
1142 tokenizer = null;
1143 }
1144 catch (Exception exception) {
1145 }
1146 return command_element;
1147 }
1148 private Element parseBuildType(String command_str) {
1149 Element command_element = null;
1150 try {
1151 StringTokenizer tokenizer = new StringTokenizer(command_str);
1152 if(tokenizer.countTokens() >= 2) {
1153 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1154 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1155 String index_str = tokenizer.nextToken();
1156 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1157 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1158 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1159 while(content_tokenizer.hasMoreTokens()) {
1160 Element content_element = document.createElement(CONTENT_ELEMENT);
1161 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1162 command_element.appendChild(content_element);
1163 content_element = null;
1164 }
1165 content_tokenizer = null;
1166 content_str = null;
1167 content_str = null;
1168 index_str = null;
1169 }
1170 tokenizer = null;
1171 }
1172 catch (Exception exception) {
1173 }
1174 return command_element;
1175 }
1176
1177 private Element parseLanguage(String command_str) {
1178 Element command_element = null;
1179 try {
1180 StringTokenizer tokenizer = new StringTokenizer(command_str);
1181 tokenizer.nextToken();
1182 if(tokenizer.hasMoreTokens()) {
1183 command_element = document.createElement(LANGUAGES_ELEMENT);
1184 while(tokenizer.hasMoreTokens()) {
1185 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1186 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1187 command_element.appendChild(language_element);
1188 language_element = null;
1189 }
1190 }
1191 tokenizer = null;
1192 }
1193 catch (Exception exception) {
1194 }
1195 return command_element;
1196 }
1197
1198 private Element parseLanguageDefault(String command_str) {
1199 Element command_element = null;
1200 try {
1201 StringTokenizer tokenizer = new StringTokenizer(command_str);
1202 if(tokenizer.countTokens() >= 2) {
1203 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1204 tokenizer.nextToken();
1205 String default_language_str = tokenizer.nextToken();
1206 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1207 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1208 default_language_str = null;
1209 }
1210 tokenizer = null;
1211 }
1212 catch (Exception exception) {
1213 }
1214 return command_element;
1215 }
1216
1217 private Element parseLevels(String command_str) {
1218 Element command_element = null;
1219 try {
1220 StringTokenizer tokenizer = new StringTokenizer(command_str);
1221 // First token is command type (levels)
1222 String command = tokenizer.nextToken();
1223 if(tokenizer.hasMoreTokens()) {
1224 command_element = document.createElement(LEVELS_ELEMENT);
1225 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1226 while(tokenizer.hasMoreTokens()) {
1227 Element level_element = document.createElement(CONTENT_ELEMENT);
1228 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1229 command_element.appendChild(level_element);
1230 level_element = null;
1231 }
1232 }
1233 command = null;
1234 }
1235 catch(Exception exception) {
1236 }
1237 return command_element;
1238 }
1239
1240 private Element parseMetadata(CommandTokenizer tokenizer) {
1241 Element command_element = null;
1242 try {
1243 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1244 String name_str = tokenizer.nextToken();
1245 String value_str = tokenizer.nextToken();
1246 if(name_str != null && value_str != null) {
1247 String language_str = Configuration.getLanguage();
1248 // Check if the value string is actually a language string
1249 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1250 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1251 value_str = tokenizer.nextToken();
1252 }
1253 if(value_str != null) {
1254 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1255 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1256 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1257 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1258 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1259 XMLTools.setValue(command_element, value_str);
1260 }
1261 else {
1262 command_element = null;
1263 }
1264 language_str = null;
1265 }
1266 else {
1267 command_element = null;
1268 }
1269 name_str = null;
1270 value_str = null;
1271 }
1272 catch (Exception exception) {
1273 DebugStream.printStackTrace(exception);
1274 command_element = null;
1275 }
1276 return command_element;
1277 }
1278
1279 private Element parseMetadataSpecial(String command_str) {
1280 Element command_element = null;
1281 try {
1282 StringTokenizer tokenizer = new StringTokenizer(command_str);
1283 if(tokenizer.countTokens() >= 2) {
1284 String name_str = tokenizer.nextToken();
1285 String value_str = tokenizer.nextToken();
1286 if (name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1287 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1288 }
1289 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1290 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1291 }
1292 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1293 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1294 }
1295 else if (name_str.equals(BUILDTYPE_STR)) {
1296 command_element = document.createElement(BUILDTYPE_ELEMENT);
1297 }
1298 if(command_element != null) {
1299 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1300 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1301 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1302 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1303 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1304 value_str = value_str.substring(1, value_str.length() - 1);
1305 }
1306 XMLTools.setValue(command_element, value_str);
1307 }
1308 value_str = null;
1309 name_str = null;
1310 }
1311 tokenizer = null;
1312 }
1313 catch (Exception exception) {
1314 }
1315 return command_element;
1316 }
1317
1318 private Element parsePlugIn(String command_str) {
1319 Element command_element = null;
1320 boolean use_metadata_files = false;
1321 try {
1322 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1323 // 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).
1324 if(tokenizer.countTokens() >= 2) {
1325 command_element = document.createElement(PLUGIN_ELEMENT);
1326 // First token is plugin
1327 tokenizer.nextToken();
1328 // The next token is the type
1329 String type = tokenizer.nextToken();
1330 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1331 // Now we parse out the remaining arguments into a hashmapping from name to value
1332 HashMap arguments = parseArguments(tokenizer);
1333 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1334 Iterator names = arguments.keySet().iterator();
1335 while(names.hasNext()) {
1336 String name = (String) names.next();
1337 String value = (String) arguments.get(name); // Can be null
1338 Element option_element = document.createElement(OPTION_ELEMENT);
1339 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1340 use_metadata_files = true;
1341 }
1342 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1343 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1344 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1345 if(value != null) {
1346 // Remove any speech marks appended in strings containing whitespace
1347 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1348 value = value.substring(1, value.length() - 1);
1349 }
1350 if(name.equals(METADATA_ARGUMENT)) {
1351 // 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.
1352 if(value.indexOf(StaticStrings.NS_SEP) == -1) {
1353 value = StaticStrings.EXTRACTED_NAMESPACE + value;
1354 }
1355 }
1356 XMLTools.setValue(option_element, value);
1357 }
1358 command_element.appendChild(option_element);
1359 option_element = null;
1360 name = null;
1361 value = null;
1362 }
1363
1364 // We must have some RecPlug options: use_metadata_files
1365 if (type.equals(RECPLUG_STR)) {
1366 if (!use_metadata_files) {
1367 Element option_element = document.createElement(OPTION_ELEMENT);
1368 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1369 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1370 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1371 command_element.appendChild(option_element);
1372 option_element = null;
1373 }
1374 }
1375 type = null;
1376 names = null;
1377 arguments = null;
1378 }
1379 tokenizer = null;
1380 }
1381 catch(Exception exception) {
1382 }
1383 return command_element;
1384 }
1385
1386 private Element parseSearchType(String command_str) {
1387 Element command_element = null;
1388 try {
1389 StringTokenizer tokenizer = new StringTokenizer(command_str);
1390 // First token is command type (levels)
1391 tokenizer.nextToken();
1392 if(tokenizer.hasMoreTokens()) {
1393 command_element = document.createElement(SEARCHTYPE_ELEMENT);
1394 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1395 while(tokenizer.hasMoreTokens()) {
1396 Element search_element = document.createElement(CONTENT_ELEMENT);
1397 search_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1398 command_element.appendChild(search_element);
1399 search_element = null;
1400 }
1401 }
1402 }
1403 catch(Exception exception) {
1404 }
1405 return command_element;
1406 }
1407
1408 private Element parseSubCollection(String command_str) {
1409 Element command_element = null;
1410 try {
1411 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1412 if(tokenizer.countTokens() >= 3) {
1413 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1414 // First token is command type
1415 tokenizer.nextToken();
1416 // Then subcollection identifier
1417 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1418 // Then finally the pattern used to build the subcollection partition
1419 String full_pattern_str = tokenizer.nextToken();
1420 // Set inclusion/exclusion flag and remove any exclamation mark
1421 boolean exclusion = full_pattern_str.startsWith(EXCLAMATION_CHARACTER);
1422 if (exclusion) {
1423 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length());
1424 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1425 }
1426 else {
1427 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1428 }
1429 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1430 if(pattern_tokenizer.countTokens() >= 2) {
1431 String content_str = pattern_tokenizer.nextToken();
1432 // 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.
1433 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(StaticStrings.NS_SEP) == -1) {
1434 content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
1435 }
1436 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1437 XMLTools.setValue(command_element, pattern_tokenizer.nextToken());
1438 if(pattern_tokenizer.hasMoreTokens()) {
1439 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1440 }
1441 }
1442 pattern_tokenizer = null;
1443 }
1444 }
1445 catch(Exception exception) {
1446 exception.printStackTrace();
1447 }
1448 return command_element;
1449 }
1450
1451 private Element parseSubCollectionDefaultIndex(String command_str) {
1452 Element command_element = null;
1453 try {
1454 StringTokenizer tokenizer = new StringTokenizer(command_str);
1455 if(tokenizer.countTokens() == 2) {
1456 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1457 tokenizer.nextToken();
1458 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1459 String content_str = tokenizer.nextToken();
1460 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1461 while(content_tokenizer.hasMoreTokens()) {
1462 Element content_element = document.createElement(CONTENT_ELEMENT);
1463 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1464 command_element.appendChild(content_element);
1465 content_element = null;
1466 }
1467 content_tokenizer = null;
1468 content_str = null;
1469 }
1470 tokenizer = null;
1471 }
1472 catch(Exception exception) {
1473 }
1474 return command_element;
1475 }
1476
1477 private Element parseSubCollectionIndex(String command_str) {
1478 Element command_element = null;
1479 try {
1480 StringTokenizer tokenizer = new StringTokenizer(command_str);
1481 tokenizer.nextToken();
1482 if(tokenizer.hasMoreTokens()) {
1483 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1484 }
1485 while(tokenizer.hasMoreTokens()) {
1486 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1487 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1488 String content_str = tokenizer.nextToken();
1489 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1490 while(content_tokenizer.hasMoreTokens()) {
1491 Element content_element = document.createElement(CONTENT_ELEMENT);
1492 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1493 subcollectionindex_element.appendChild(content_element);
1494 content_element = null;
1495 }
1496 content_tokenizer = null;
1497 content_str = null;
1498 command_element.appendChild(subcollectionindex_element);
1499 subcollectionindex_element = null;
1500 }
1501 tokenizer = null;
1502 }
1503 catch (Exception exception) {
1504 }
1505 return command_element;
1506 }
1507
1508 private Element parseSuperCollection(String command_str) {
1509 Element command_element = null;
1510 try {
1511 StringTokenizer tokenizer = new StringTokenizer(command_str);
1512 if(tokenizer.countTokens() >= 3) {
1513 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1514 tokenizer.nextToken();
1515 while(tokenizer.hasMoreTokens()) {
1516 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1517 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1518 command_element.appendChild(collection_element);
1519 collection_element = null;
1520 }
1521 }
1522 tokenizer = null;
1523 }
1524 catch(Exception exception) {
1525 }
1526 return command_element;
1527 }
1528
1529 static private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1530 StringBuffer text = new StringBuffer();
1531 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1532 text.append(PLUGIN_STR);
1533 text.append(TAB_CHARACTER);
1534 text.append(TAB_CHARACTER);
1535 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1536 // Retrieve, and output, the arguments
1537 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1538 int option_elements_length = option_elements.getLength();
1539 if(option_elements_length > 0) {
1540 text.append(SPACE_CHARACTER);
1541 for(int j = 0; j < option_elements_length; j++) {
1542 Element option_element = (Element) option_elements.item(j);
1543 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1544 text.append(StaticStrings.MINUS_CHARACTER);
1545 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1546 String value_str = XMLTools.getValue(option_element);
1547 if(!show_extracted_namespace && value_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1548 value_str = value_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1549 }
1550 if(value_str.length() > 0) {
1551 text.append(SPACE_CHARACTER);
1552 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1553 text.append(value_str);
1554 }
1555 else {
1556 text.append(SPEECH_CHARACTER);
1557 text.append(value_str);
1558 text.append(SPEECH_CHARACTER);
1559 }
1560 }
1561 value_str = null;
1562 if(j < option_elements_length - 1) {
1563 text.append(SPACE_CHARACTER);
1564 }
1565 }
1566 option_element = null;
1567 }
1568 }
1569 option_elements = null;
1570 }
1571 return text.toString();
1572 }
1573
1574 static private String searchtypeToString(Element command_element) {
1575 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1576 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1577 text.append(TAB_CHARACTER);
1578 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1579 int search_elements_length = search_elements.getLength();
1580 for(int i = 0; i < search_elements_length; i++) {
1581 Element search_element = (Element) search_elements.item(i);
1582 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1583 text.append(SPACE_CHARACTER);
1584 }
1585 return text.substring(0, text.length() - 1);
1586 }
1587 else {
1588 return null;
1589 }
1590 }
1591
1592 static private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1593 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1594 text.append(SPACE_CHARACTER);
1595 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1596 text.append(SPACE_CHARACTER);
1597 text.append(TAB_CHARACTER);
1598 text.append(SPEECH_CHARACTER);
1599 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1600 text.append(EXCLAMATION_CHARACTER);
1601 }
1602 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1603 if(!show_extracted_namespace && content_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
1604 content_str = content_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
1605 }
1606 text.append(content_str);
1607 content_str = null;
1608 text.append(SEPARATOR_CHARACTER);
1609 text.append(XMLTools.getValue(command_element));
1610 text.append(SEPARATOR_CHARACTER);
1611 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1612 if(options_str.length() > 0) {
1613 text.append(options_str);
1614 }
1615 options_str = null;
1616 text.append(SPEECH_CHARACTER);
1617 return text.toString();
1618 }
1619
1620 static private String subcollectionDefaultIndexToString(Element command_element) {
1621 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1622 text.append(TAB_CHARACTER);
1623 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1624 int content_elements_length = content_elements.getLength();
1625 for(int j = 0; j < content_elements_length; j++) {
1626 Element content_element = (Element) content_elements.item(j);
1627 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1628 if(j < content_elements_length - 1) {
1629 text.append(StaticStrings.COMMA_CHARACTER);
1630 }
1631 }
1632 return text.toString();
1633 }
1634
1635 static private String subcollectionIndexesToString(Element command_element) {
1636 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1637 text.append(TAB_CHARACTER);
1638 // Retrieve all of the subcollection index partitions
1639 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1640 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1641 if(subcollectionindex_elements_length == 0) {
1642 return null;
1643 }
1644 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1645 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1646 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1647 int content_elements_length = content_elements.getLength();
1648 for(int k = 0; k < content_elements_length; k++) {
1649 Element content_element = (Element) content_elements.item(k);
1650 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1651 if(k < content_elements_length - 1) {
1652 text.append(StaticStrings.COMMA_CHARACTER);
1653 }
1654 }
1655 if(j < subcollectionindex_elements_length - 1) {
1656 text.append(SPACE_CHARACTER);
1657 }
1658 }
1659 return text.toString();
1660 }
1661
1662 static private String supercollectionToString(Element command_element) {
1663 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1664 int content_elements_length = content_elements.getLength();
1665 if(content_elements_length > 1) {
1666 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1667 text.append(TAB_CHARACTER);
1668 for(int j = 0; j < content_elements_length; j++) {
1669 Element content_element = (Element) content_elements.item(j);
1670 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1671 if(j < content_elements_length - 1) {
1672 text.append(SPACE_CHARACTER);
1673 }
1674 }
1675 return text.toString();
1676 }
1677 return null;
1678 }
1679
1680 static private String unknownToString(Element command_element) {
1681 return XMLTools.getValue(command_element);
1682 }
1683
1684 /** 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.
1685 * @param writer the BufferedWriter to which the str will be written
1686 * @param str the String to be written
1687 */
1688 private void write(BufferedWriter writer, String str)
1689 throws IOException {
1690 writer.write(str, 0, str.length());
1691 }
1692}
Note: See TracBrowser for help on using the repository browser.