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

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

added a comment

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