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

Last change on this file since 5930 was 5930, checked in by jmt12, 20 years ago

Metadata is now only written to collect.cfg if assigned. It used to instead return an empty string if no value was set - which of course meant that any two different collection meta which just happened to have no strings set were taken as the same object by the equals method in the DOMProxyListModel

  • Property svn:keywords set to Author Date Id Revision
File size: 70.0 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 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 if (index_elements.getLength() == 0) { // no indexes
620 return "";
621 }
622 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
623 int index_elements_length = index_elements.getLength();
624 for(int j = 0; j < index_elements_length; j++) {
625 Element index_element = (Element) index_elements.item(j);
626 String level_str = index_element.getAttribute(LEVEL_ATTRIBUTE);
627 if(level_str.length() > 0) {
628 text.append(level_str);
629 text.append(StaticStrings.COLON_CHARACTER);
630 }
631 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT);
632 int content_elements_length = content_elements.getLength();
633 // Don't output anything if no indexes are set
634 if(content_elements_length == 0) {
635 return null;
636 }
637 for(int k = 0; k < content_elements_length; k++) {
638 Element content_element = (Element) content_elements.item(k);
639 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
640 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
641 name_str = name_str.substring(EXTRACTED_PREFIX.length());
642 }
643 text.append(name_str);
644 name_str = null;
645 if(k < content_elements_length - 1) {
646 text.append(StaticStrings.COMMA_CHARACTER);
647 }
648 content_element = null;
649 }
650 if(j < index_elements_length - 1) {
651 text.append(SPACE_CHARACTER);
652 }
653 content_elements = null;
654 index_element = null;
655 }
656 index_elements = null;
657 return text.toString();
658 }
659
660 private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
661 StringBuffer text = new StringBuffer("");
662 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) {
663 text.append("#");
664 }
665 text.append(INDEX_DEFAULT_STR);
666 text.append(TAB_CHARACTER);
667 text.append(command_element.getAttribute(LEVEL_ATTRIBUTE));
668 text.append(StaticStrings.COLON_CHARACTER);
669 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
670 int content_elements_length = content_elements.getLength();
671 for(int j = 0; j < content_elements_length; j++) {
672 Element content_element = (Element) content_elements.item(j);
673 String name_str = content_element.getAttribute(NAME_ATTRIBUTE);
674 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) {
675 name_str = name_str.substring(EXTRACTED_PREFIX.length());
676 }
677 text.append(name_str);
678 name_str = null;
679 if(j < content_elements_length - 1) {
680 text.append(StaticStrings.COMMA_CHARACTER);
681 }
682 content_element = null;
683 }
684 content_elements = null;
685 return text.toString();
686 }
687
688 private String languagesToString(Element command_element) {
689 StringBuffer text = new StringBuffer(LANGUAGES_STR);
690 text.append(TAB_CHARACTER);
691 // Retrieve all the languages and write them out in a space separated list
692 NodeList language_elements = command_element.getElementsByTagName(LANGUAGE_ELEMENT);
693 int language_elements_length = language_elements.getLength();
694 if(language_elements_length == 0) {
695 return null;
696 }
697 for(int j = 0; j < language_elements_length; j++) {
698 Element language_element = (Element) language_elements.item(j);
699 text.append(language_element.getAttribute(NAME_ATTRIBUTE));
700 if(j < language_elements_length - 1) {
701 text.append(SPACE_CHARACTER);
702 }
703 }
704 return text.toString();
705 }
706
707 private String languageDefaultToString(Element command_element) {
708 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR);
709 text.append(TAB_CHARACTER);
710 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
711 return text.toString();
712 }
713
714 private String levelsToString(Element command_element) {
715 StringBuffer text = new StringBuffer("");
716 if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
717 text.append("#");
718 }
719 text.append(LEVELS_STR);
720 text.append(TAB_CHARACTER);
721 text.append(TAB_CHARACTER);
722 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
723 int content_elements_length = content_elements.getLength();
724 // Don't output anything if no levels are set.
725 if(content_elements_length == 0) {
726 return null;
727 }
728 for(int i = 0; i < content_elements_length; i++) {
729 Element content_element = (Element) content_elements.item(i);
730 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
731 text.append(SPACE_CHARACTER);
732 }
733 return text.substring(0, text.length() - 1);
734 }
735
736 static public String metadataToString(Element command_element, boolean text_value) {
737 boolean special = false;
738 // If there is no value attribute, then we don't write anything
739 StringBuffer text = new StringBuffer("");
740 String name_str = command_element.getAttribute(NAME_ATTRIBUTE);
741 // 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.
742 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
743 text.append(name_str);
744 text.append(TAB_CHARACTER);
745 special = true;
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 special = true;
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 //if(!language_str.equals(ENGLISH_LANGUAGE_STR) || known_metadata == null || known_metadata.contains(name_str)) {
761 // changed so that we always write the language string
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 String value_str = MSMUtils.getValue(command_element);
776 // 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
777 if(text_value == CollectionMeta.TEXT) {
778 value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT);
779 }
780 else {
781 value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE);
782 }
783
784 // We don't wrap the email addresses in quotes, nor the other special metadata
785 if(special) {
786 text.append(value_str);
787 }
788 else {
789 text.append(SPEECH_CHARACTER);
790 text.append(value_str);
791 text.append(SPEECH_CHARACTER);
792 }
793 value_str = null;
794 return text.toString();
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, in);
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() >= 2) { // Must support "classify Phind" (no args)
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, BufferedReader in) {
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 value_str = tokenizer.nextToken();
970 // If the value is true or false we add it as an attribute
971 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) {
972 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase());
973 }
974 // Otherwise it gets added as a text node
975 else {
976
977 // now we need to handle the case where the value is enclosed in quotes (single or double) and may extend across multiple lines
978 String start_string = value_str.substring(0,1);
979 if (start_string.equals("\"") || start_string.equals("\'")) {
980 if (value_str.endsWith(start_string) && value_str.length()!=1) {
981 // we remove the quotes from the ends
982 value_str = value_str.substring(1, value_str.length() - 1);
983 } else {
984
985 // remove the first quote
986 StringBuffer value_raw = new StringBuffer(value_str.substring(1));
987 // add the new line back in
988 value_raw.append(StaticStrings.NEW_LINE_CHAR);
989 int pos = value_raw.indexOf(start_string);
990 int old_pos = 0;
991 while (pos != -1 && value_raw.charAt(pos-1)=='\\') {
992 old_pos = pos+1;
993 pos = value_raw.indexOf(start_string, old_pos);
994 }
995 while(pos == -1) {
996 String next_line = in.readLine();
997 if(next_line != null) {
998 value_raw.append(next_line);
999 value_raw.append(StaticStrings.NEW_LINE_CHAR);
1000 }
1001 next_line = null;
1002 pos = value_raw.indexOf(start_string, old_pos);
1003 while (pos != -1 && value_raw.charAt(pos-1)=='\\') {
1004 old_pos = pos+1;
1005 pos = value_raw.indexOf(start_string, old_pos);
1006 }
1007 }
1008
1009 value_str = value_raw.substring(0, value_raw.lastIndexOf(start_string));
1010 value_raw = null;
1011
1012 } // else
1013 } // if starts with a quote
1014
1015 if(value_str != null) {
1016 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1017 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1018 MSMUtils.setValue(command_element, value_str);
1019 }
1020 else {
1021 command_element = null;
1022 }
1023 start_string = null;
1024 }
1025 value_str = null;
1026
1027 }
1028 tokenizer = null;
1029 }
1030 catch (Exception exception) {
1031 }
1032 return command_element;
1033 }
1034
1035 private Element parseIndex(String command_str) {
1036 Element command_element = null;
1037 try {
1038 StringTokenizer tokenizer = new StringTokenizer(command_str);
1039 String command = tokenizer.nextToken();
1040 command_element = document.createElement(INDEXES_ELEMENT);
1041 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR));
1042 command = null;
1043 if(!tokenizer.hasMoreTokens()) {
1044
1045 // there are no indexes
1046 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR);
1047 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); // for now
1048 tokenizer = null;
1049 return command_element;
1050 }
1051
1052 while(tokenizer.hasMoreTokens()) {
1053 Element index_element = document.createElement(INDEX_ELEMENT);
1054 String index_str = tokenizer.nextToken();
1055 // 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.
1056 boolean old_index;
1057 if(index_str.indexOf(COLON_CHARACTER) != -1) {
1058 old_index = true;
1059 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1060 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1061 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR);
1062 }
1063 else {
1064 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR);
1065 old_index = false;
1066 }
1067 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
1068 while(content_tokenizer.hasMoreTokens()) {
1069 Element content_element = document.createElement(CONTENT_ELEMENT);
1070 String content_str = content_tokenizer.nextToken();
1071 // 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.
1072 if(content_str.indexOf(MSMUtils.NS_SEP) == -1) {
1073 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
1074 // Our special strings are OK.
1075 }
1076 else {
1077 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
1078 }
1079 }
1080 content_element.setAttribute(NAME_ATTRIBUTE, content_str);
1081 index_element.appendChild(content_element);
1082 content_element = null;
1083 }
1084 content_tokenizer = null;
1085 index_str = null;
1086 command_element.appendChild(index_element);
1087 index_element = null;
1088 }
1089 tokenizer = null;
1090 }
1091 catch (Exception exception) {
1092 exception.printStackTrace();
1093 }
1094 return command_element;
1095 }
1096
1097 private Element parseIndexDefault(String command_str) {
1098 Element command_element = null;
1099 try {
1100 StringTokenizer tokenizer = new StringTokenizer(command_str);
1101 if(tokenizer.countTokens() >= 2) {
1102 command_element = document.createElement(INDEX_DEFAULT_ELEMENT);
1103 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR));
1104 String index_str = tokenizer.nextToken();
1105 command_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
1106 String content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
1107 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1108 while(content_tokenizer.hasMoreTokens()) {
1109 Element content_element = document.createElement(CONTENT_ELEMENT);
1110 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1111 command_element.appendChild(content_element);
1112 content_element = null;
1113 }
1114 content_tokenizer = null;
1115 content_str = null;
1116 content_str = null;
1117 index_str = null;
1118 }
1119 tokenizer = null;
1120 }
1121 catch (Exception exception) {
1122 }
1123 return command_element;
1124 }
1125
1126 private Element parseLanguage(String command_str) {
1127 Element command_element = null;
1128 try {
1129 StringTokenizer tokenizer = new StringTokenizer(command_str);
1130 tokenizer.nextToken();
1131 if(tokenizer.hasMoreTokens()) {
1132 command_element = document.createElement(LANGUAGES_ELEMENT);
1133 while(tokenizer.hasMoreTokens()) {
1134 Element language_element = document.createElement(LANGUAGE_ELEMENT);
1135 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1136 command_element.appendChild(language_element);
1137 language_element = null;
1138 }
1139 }
1140 tokenizer = null;
1141 }
1142 catch (Exception exception) {
1143 }
1144 return command_element;
1145 }
1146
1147 private Element parseLanguageDefault(String command_str) {
1148 Element command_element = null;
1149 try {
1150 StringTokenizer tokenizer = new StringTokenizer(command_str);
1151 if(tokenizer.countTokens() >= 2) {
1152 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT);
1153 tokenizer.nextToken();
1154 String default_language_str = tokenizer.nextToken();
1155 command_element.setAttribute(NAME_ATTRIBUTE, default_language_str);
1156 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
1157 default_language_str = null;
1158 }
1159 tokenizer = null;
1160 }
1161 catch (Exception exception) {
1162 }
1163 return command_element;
1164 }
1165
1166 private Element parseLevels(String command_str) {
1167 Element command_element = null;
1168 try {
1169 StringTokenizer tokenizer = new StringTokenizer(command_str);
1170 // First token is command type (levels)
1171 String command = tokenizer.nextToken();
1172 if(tokenizer.hasMoreTokens()) {
1173 command_element = document.createElement(LEVELS_ELEMENT);
1174 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR));
1175 while(tokenizer.hasMoreTokens()) {
1176 Element level_element = document.createElement(CONTENT_ELEMENT);
1177 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1178 command_element.appendChild(level_element);
1179 level_element = null;
1180 }
1181 }
1182 command = null;
1183 }
1184 catch(Exception exception) {
1185 }
1186 return command_element;
1187 }
1188
1189 private Element parseMetadata(String command_str, BufferedReader in) {
1190 Element command_element = null;
1191 try {
1192 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1193 if(tokenizer.countTokens() >= 3) {
1194 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT);
1195 // First token is command type
1196 tokenizer.nextToken();
1197 String name_str = tokenizer.nextToken();
1198 String value_str = tokenizer.nextToken();
1199 String language_str = "en"; // By default - why do we assume English???
1200 // Check if the value string is actually a language string
1201 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) {
1202 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
1203 value_str = tokenizer.nextToken();
1204 }
1205
1206 // now we need to handle the case where the value is enclosed in quotes (single or double) and may extend across multiple lines
1207 String start_string = value_str.substring(0,1);
1208 if (start_string.equals("\"") || start_string.equals("\'")) {
1209
1210 if (value_str.endsWith(start_string) && value_str.length()!=1) {
1211 // we remove the quotes from the ends
1212 value_str = value_str.substring(1, value_str.length() - 1);
1213 } else {
1214
1215 // remove the first quote
1216 StringBuffer value_raw = new StringBuffer(value_str.substring(1));
1217 // add the new line back in
1218 value_raw.append(StaticStrings.NEW_LINE_CHAR);
1219
1220 int pos = value_raw.indexOf(start_string);
1221 int old_pos = 0;
1222 while (pos != -1 && value_raw.charAt(pos-1)=='\\') {
1223 old_pos = pos+1;
1224 pos = value_raw.indexOf(start_string, old_pos);
1225 }
1226 while(pos == -1) {
1227 String next_line = in.readLine();
1228 if(next_line != null) {
1229 value_raw.append(next_line);
1230 value_raw.append(StaticStrings.NEW_LINE_CHAR);
1231 }
1232 next_line = null;
1233 pos = value_raw.indexOf(start_string, old_pos);
1234 while (pos != -1 && value_raw.charAt(pos-1)=='\\') {
1235 old_pos = pos+1;
1236 pos = value_raw.indexOf(start_string, old_pos);
1237 }
1238 }
1239
1240 value_str = value_raw.substring(0, value_raw.lastIndexOf(start_string));
1241 value_raw = null;
1242
1243 } // else
1244 } // if starts with a quote
1245
1246 if(value_str != null) {
1247 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
1248 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
1249 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1250 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str);
1251 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1252 MSMUtils.setValue(command_element, value_str);
1253 }
1254 else {
1255 command_element = null;
1256 }
1257 language_str = null;
1258 value_str = null;
1259 name_str = null;
1260 }
1261 tokenizer = null;
1262 }
1263 catch (Exception exception) {
1264 }
1265 return command_element;
1266 }
1267
1268 private Element parseMetadataSpecial(String command_str) {
1269 Element command_element = null;
1270 try {
1271 StringTokenizer tokenizer = new StringTokenizer(command_str);
1272 if(tokenizer.countTokens() >= 2) {
1273 String name_str = tokenizer.nextToken();
1274 String value_str = tokenizer.nextToken();
1275 if(name_str.equals(COLLECTIONMETADATA_BETA_STR)) {
1276 command_element = document.createElement(COLLECTIONMETADATA_BETA_ELEMENT);
1277 }
1278 else if(name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) {
1279 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT);
1280 }
1281 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) {
1282 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT);
1283 }
1284 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) {
1285 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT);
1286 }
1287 if(command_element != null) {
1288 command_element.setAttribute(NAME_ATTRIBUTE, name_str);
1289 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR);
1290 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR);
1291 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1292 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) {
1293 value_str = value_str.substring(1, value_str.length() - 1);
1294 }
1295 MSMUtils.setValue(command_element, value_str);
1296 }
1297 value_str = null;
1298 name_str = null;
1299 }
1300 tokenizer = null;
1301 }
1302 catch (Exception exception) {
1303 }
1304 return command_element;
1305 }
1306
1307 private Element parsePlugIn(String command_str) {
1308 Element command_element = null;
1309 boolean use_metadata_files = false;
1310 boolean show_progress = false;
1311 try {
1312 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1313 // 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).
1314 if(tokenizer.countTokens() >= 2) {
1315 command_element = document.createElement(PLUGIN_ELEMENT);
1316 // First token is plugin
1317 tokenizer.nextToken();
1318 // The next token is the type
1319 String type = tokenizer.nextToken();
1320 command_element.setAttribute(TYPE_ATTRIBUTE, type);
1321 // Now we parse out the remaining arguments into a hashmapping from name to value
1322 HashMap arguments = parseArguments(tokenizer);
1323 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
1324 Iterator names = arguments.keySet().iterator();
1325 while(names.hasNext()) {
1326 String name = (String) names.next();
1327 String value = (String) arguments.get(name); // Can be null
1328 Element option_element = document.createElement(OPTION_ELEMENT);
1329 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) {
1330 use_metadata_files = true;
1331 }
1332 else if(name.substring(1).equals(SHOW_PROGRESS_ARGUMENT)) {
1333 show_progress = true;
1334 }
1335 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1));
1336 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1337 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments
1338 if(value != null) {
1339 // Remove any speech marks appended in strings containing whitespace
1340 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) {
1341 value = value.substring(1, value.length() - 1);
1342 }
1343 if(name.equals(METADATA_ARGUMENT)) {
1344 // 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.
1345 if(value.indexOf(MSMUtils.NS_SEP) == -1) {
1346 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value;
1347 }
1348 }
1349 MSMUtils.setValue(option_element, value);
1350 }
1351 command_element.appendChild(option_element);
1352 option_element = null;
1353 name = null;
1354 value = null;
1355 }
1356
1357 // We must have some RecPlug options: use_metadata_files, and show_progress
1358 if (type.equals(RECPLUG_STR)) {
1359 if (!use_metadata_files) {
1360 Element option_element = document.createElement(OPTION_ELEMENT);
1361 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT);
1362 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1363 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1364 command_element.appendChild(option_element);
1365 option_element = null;
1366 }
1367 if(!show_progress) {
1368 Element option_element = document.createElement(OPTION_ELEMENT);
1369 option_element.setAttribute(NAME_ATTRIBUTE, SHOW_PROGRESS_ARGUMENT);
1370 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1371 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR);
1372 command_element.appendChild(option_element);
1373 option_element = null;
1374 }
1375 }
1376 type = null;
1377 names = null;
1378 arguments = null;
1379 }
1380 tokenizer = null;
1381 }
1382 catch(Exception exception) {
1383 }
1384 return command_element;
1385 }
1386
1387 private Element parseSearchType(String command_str) {
1388 Element command_element = null;
1389 try {
1390 StringTokenizer tokenizer = new StringTokenizer(command_str);
1391 // First token is command type (levels)
1392 tokenizer.nextToken();
1393 if(tokenizer.hasMoreTokens()) {
1394 command_element = document.createElement(SEARCHTYPE_ELEMENT);
1395 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR);
1396 while(tokenizer.hasMoreTokens()) {
1397 Element search_element = document.createElement(CONTENT_ELEMENT);
1398 search_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1399 command_element.appendChild(search_element);
1400 search_element = null;
1401 }
1402 }
1403 }
1404 catch(Exception exception) {
1405 }
1406 return command_element;
1407 }
1408
1409 private Element parseSubCollection(String command_str) {
1410 Element command_element = null;
1411 try {
1412 CommandTokenizer tokenizer = new CommandTokenizer(command_str);
1413 if(tokenizer.countTokens() >= 3) {
1414 command_element = document.createElement(SUBCOLLECTION_ELEMENT);
1415 // First token is command type
1416 tokenizer.nextToken();
1417 // Then subcollection identifier
1418 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1419 // Then finally the pattern used to build the subcollection partition
1420 String full_pattern_str = tokenizer.nextToken();
1421 // To make life easier I'm going to parse this up now.
1422 boolean exclusion = (full_pattern_str.substring(1, 2).equals(EXCLAIMATION_CHARACTER));
1423 // Set inclusion/exclusion flag, remove any exclaimation mark and the speech marks
1424 if(exclusion) {
1425 full_pattern_str = full_pattern_str.substring(2, full_pattern_str.length() - 1);
1426 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR);
1427 }
1428 else {
1429 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length() - 1);
1430 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR);
1431 }
1432 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER);
1433 if(pattern_tokenizer.countTokens() >= 2) {
1434 String content_str = pattern_tokenizer.nextToken();
1435 // 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.
1436 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(MSMUtils.NS_SEP) == -1) {
1437 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str;
1438 }
1439 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str);
1440 MSMUtils.setValue(command_element, pattern_tokenizer.nextToken());
1441 if(pattern_tokenizer.hasMoreTokens()) {
1442 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
1443 }
1444 }
1445 pattern_tokenizer = null;
1446 }
1447 }
1448 catch(Exception exception) {
1449 exception.printStackTrace();
1450 }
1451 return command_element;
1452 }
1453
1454 private Element parseSubCollectionDefaultIndex(String command_str) {
1455 Element command_element = null;
1456 try {
1457 StringTokenizer tokenizer = new StringTokenizer(command_str);
1458 if(tokenizer.countTokens() == 2) {
1459 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
1460 tokenizer.nextToken();
1461 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1462 String content_str = tokenizer.nextToken();
1463 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1464 while(content_tokenizer.hasMoreTokens()) {
1465 Element content_element = document.createElement(CONTENT_ELEMENT);
1466 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1467 command_element.appendChild(content_element);
1468 content_element = null;
1469 }
1470 content_tokenizer = null;
1471 content_str = null;
1472 }
1473 tokenizer = null;
1474 }
1475 catch(Exception exception) {
1476 }
1477 return command_element;
1478 }
1479
1480 private Element parseSubCollectionIndex(String command_str) {
1481 Element command_element = null;
1482 try {
1483 StringTokenizer tokenizer = new StringTokenizer(command_str);
1484 tokenizer.nextToken();
1485 if(tokenizer.hasMoreTokens()) {
1486 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT);
1487 }
1488 while(tokenizer.hasMoreTokens()) {
1489 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT);
1490 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
1491 String content_str = tokenizer.nextToken();
1492 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
1493 while(content_tokenizer.hasMoreTokens()) {
1494 Element content_element = document.createElement(CONTENT_ELEMENT);
1495 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken());
1496 subcollectionindex_element.appendChild(content_element);
1497 content_element = null;
1498 }
1499 content_tokenizer = null;
1500 content_str = null;
1501 command_element.appendChild(subcollectionindex_element);
1502 subcollectionindex_element = null;
1503 }
1504 tokenizer = null;
1505 }
1506 catch (Exception exception) {
1507 }
1508 return command_element;
1509 }
1510
1511 private Element parseSuperCollection(String command_str) {
1512 Element command_element = null;
1513 try {
1514 StringTokenizer tokenizer = new StringTokenizer(command_str);
1515 if(tokenizer.countTokens() >= 3) {
1516 command_element = document.createElement(SUPERCOLLECTION_ELEMENT);
1517 tokenizer.nextToken();
1518 while(tokenizer.hasMoreTokens()) {
1519 Element collection_element = document.createElement(COLLECTION_ELEMENT);
1520 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken());
1521 command_element.appendChild(collection_element);
1522 collection_element = null;
1523 }
1524 }
1525 tokenizer = null;
1526 }
1527 catch(Exception exception) {
1528 }
1529 return command_element;
1530 }
1531
1532 private String pluginToString(Element command_element, boolean show_extracted_namespace) {
1533 StringBuffer text = new StringBuffer();
1534 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) {
1535 text.append(PLUGIN_STR);
1536 text.append(TAB_CHARACTER);
1537 text.append(TAB_CHARACTER);
1538 text.append(command_element.getAttribute(TYPE_ATTRIBUTE));
1539 // Retrieve, and output, the arguments
1540 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT);
1541 int option_elements_length = option_elements.getLength();
1542 if(option_elements_length > 0) {
1543 text.append(SPACE_CHARACTER);
1544 for(int j = 0; j < option_elements_length; j++) {
1545 Element option_element = (Element) option_elements.item(j);
1546 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1547 text.append(StaticStrings.MINUS_CHARACTER);
1548 text.append(option_element.getAttribute(NAME_ATTRIBUTE));
1549 String value_str = MSMUtils.getValue(option_element);
1550 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) {
1551 value_str = value_str.substring(EXTRACTED_PREFIX.length());
1552 }
1553 if(value_str.length() > 0) {
1554 text.append(SPACE_CHARACTER);
1555 if(value_str.indexOf(SPACE_CHARACTER) == -1) {
1556 text.append(value_str);
1557 }
1558 else {
1559 text.append(SPEECH_CHARACTER);
1560 text.append(value_str);
1561 text.append(SPEECH_CHARACTER);
1562 }
1563 }
1564 value_str = null;
1565 if(j < option_elements_length - 1) {
1566 text.append(SPACE_CHARACTER);
1567 }
1568 }
1569 option_element = null;
1570 }
1571 }
1572 option_elements = null;
1573 }
1574 return text.toString();
1575 }
1576
1577 private String searchtypeToString(Element command_element) {
1578 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) {
1579 StringBuffer text = new StringBuffer(SEARCHTYPE_STR);
1580 text.append(TAB_CHARACTER);
1581 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1582 int search_elements_length = search_elements.getLength();
1583 for(int i = 0; i < search_elements_length; i++) {
1584 Element search_element = (Element) search_elements.item(i);
1585 text.append(search_element.getAttribute(NAME_ATTRIBUTE));
1586 text.append(SPACE_CHARACTER);
1587 }
1588 return text.substring(0, text.length() - 1);
1589 }
1590 else {
1591 return null;
1592 }
1593 }
1594
1595 private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
1596 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR);
1597 text.append(SPACE_CHARACTER);
1598 text.append(command_element.getAttribute(NAME_ATTRIBUTE));
1599 text.append(SPACE_CHARACTER);
1600 text.append(TAB_CHARACTER);
1601 text.append(SPEECH_CHARACTER);
1602 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) {
1603 text.append(EXCLAIMATION_CHARACTER);
1604 }
1605 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE);
1606 if(!show_extracted_namespace && content_str.startsWith(EXTRACTED_PREFIX)) {
1607 content_str = content_str.substring(EXTRACTED_PREFIX.length());
1608 }
1609 text.append(content_str);
1610 content_str = null;
1611 text.append(SEPARATOR_CHARACTER);
1612 text.append(MSMUtils.getValue(command_element));
1613 text.append(SEPARATOR_CHARACTER);
1614 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE);
1615 if(options_str.length() > 0) {
1616 text.append(options_str);
1617 }
1618 options_str = null;
1619 text.append(SPEECH_CHARACTER);
1620 return text.toString();
1621 }
1622
1623 private String subcollectionDefaultIndexToString(Element command_element) {
1624 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR);
1625 text.append(TAB_CHARACTER);
1626 NodeList content_elements = command_element.getElementsByTagName(CONTENT_ELEMENT);
1627 int content_elements_length = content_elements.getLength();
1628 for(int j = 0; j < content_elements_length; j++) {
1629 Element content_element = (Element) content_elements.item(j);
1630 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1631 if(j < content_elements_length - 1) {
1632 text.append(StaticStrings.COMMA_CHARACTER);
1633 }
1634 }
1635 return text.toString();
1636 }
1637
1638 private String subcollectionIndexesToString(Element command_element) {
1639 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR);
1640 text.append(TAB_CHARACTER);
1641 // Retrieve all of the subcollection index partitions
1642 NodeList subcollectionindex_elements = command_element.getElementsByTagName(INDEX_ELEMENT);
1643 int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
1644 if(subcollectionindex_elements_length == 0) {
1645 return null;
1646 }
1647 for(int j = 0; j < subcollectionindex_elements_length; j++) {
1648 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
1649 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT);
1650 int content_elements_length = content_elements.getLength();
1651 for(int k = 0; k < content_elements_length; k++) {
1652 Element content_element = (Element) content_elements.item(k);
1653 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1654 if(k < content_elements_length - 1) {
1655 text.append(StaticStrings.COMMA_CHARACTER);
1656 }
1657 }
1658 if(j < subcollectionindex_elements_length - 1) {
1659 text.append(SPACE_CHARACTER);
1660 }
1661 }
1662 return text.toString();
1663 }
1664
1665 private String supercollectionToString(Element command_element) {
1666 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT);
1667 int content_elements_length = content_elements.getLength();
1668 if(content_elements_length > 1) {
1669 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR);
1670 text.append(TAB_CHARACTER);
1671 for(int j = 0; j < content_elements_length; j++) {
1672 Element content_element = (Element) content_elements.item(j);
1673 text.append(content_element.getAttribute(NAME_ATTRIBUTE));
1674 if(j < content_elements_length - 1) {
1675 text.append(SPACE_CHARACTER);
1676 }
1677 }
1678 return text.toString();
1679 }
1680 return null;
1681 }
1682
1683 private String unknownToString(Element command_element) {
1684 return MSMUtils.getValue(command_element);
1685 }
1686
1687 /** 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.
1688 * @param writer the BufferedWriter to which the str will be written
1689 * @param str the String to be written
1690 */
1691 private void write(BufferedWriter writer, String str)
1692 throws IOException {
1693 writer.write(str, 0, str.length());
1694 }
1695}
Note: See TracBrowser for help on using the repository browser.