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

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

changed a bit of parsing - buildtypes, levels, searchtypes have changed

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