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

Last change on this file since 5817 was 5817, checked in by kjdon, 20 years ago

changed the metadata parsing to look over multiple lines if starts with a quote but doesn't end with a quote - needed for legacy collections. also made it always write out a [l=en] qualifier for metadata even if its english.

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