2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
30 package mir.producer.reader;
33 import java.io.Reader;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
42 import mir.producer.CompositeProducerNode;
43 import mir.producer.ProducerFactory;
44 import mir.producer.ProducerNode;
45 import mir.producer.SimpleProducerVerb;
46 import mir.util.ExceptionFunctions;
47 import mir.util.xml.XMLParserEngine;
48 import mir.util.xml.XMLParserExc;
49 import mir.util.xml.XMLParserFailure;
51 public class ProducerConfigReader {
52 private ProducerNodeBuilderLibrary builderLibrary;
53 private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
55 public ProducerConfigReader() {
59 public void parse(Reader aReader, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
61 builderLibrary = aBuilderLibrary;
62 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
64 XMLParserEngine.getInstance().parse("", aReader, new RootSectionHandler(aProducerFactories));
68 Throwable root = ExceptionFunctions.traceCauseException(e);
70 if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
71 XMLParserExc f = (XMLParserExc) root;
72 throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
74 throw new ProducerConfigFailure(root);
77 public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
79 builderLibrary = aBuilderLibrary;
80 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
82 XMLParserEngine.getInstance().parse("", aFile, new RootSectionHandler(aProducerFactories));
86 Throwable root = ExceptionFunctions.traceCauseException(e);
88 if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
89 XMLParserExc f = (XMLParserExc) root;
90 throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
92 throw new ProducerConfigFailure(root);
96 public class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
97 private List producers;
99 public RootSectionHandler(List aProducers) {
100 producers = aProducers;
103 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
104 if (aTag.equals("producers")) {
105 return new ProducersSectionHandler(producers);
108 throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
111 public void endElement(mir.util.xml.SectionHandler aHandler) {
114 public void finishSection() {
118 private final static String PRODUCER_NAME_ATTRIBUTE = "name";
119 private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
120 private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
122 private final static String NODE_DEFINITION_NAME_ATTRIBUTE = "name";
123 private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
124 private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = { };
126 public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
127 private List producers;
128 private Set producerNames;
131 public ProducersSectionHandler(List aProducers) {
132 producers = aProducers;
133 producerNames = new HashSet();
136 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
137 if (aTag.equals("producer")) {
138 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
139 PRODUCER_REQUIRED_ATTRIBUTES,
140 PRODUCER_OPTIONAL_ATTRIBUTES);
142 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
143 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
145 if (producerNames.contains(name))
146 throw new XMLParserExc("Duplicate producer name: '" +
149 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
151 return new ProducerSectionHandler(name);
153 else if (aTag.equals("nodedefinition")) {
154 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
155 NODE_DEFINITION_REQUIRED_ATTRIBUTES,
156 NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
158 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
159 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
161 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
163 return new NodeDefinitionSectionHandler(name);
165 throw new XMLParserExc("Unexpected tag: " + aTag);
168 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
169 if (aHandler instanceof ProducerSectionHandler) {
170 producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
171 producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
173 else if (aHandler instanceof NodeDefinitionSectionHandler) {
174 scriptedNodeBuilderLibrary.registerFactory(name,
175 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
176 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
178 else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
181 public void finishSection() {
185 public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
186 private ProducerFactory producerFactory;
187 private String factoryName;
189 private ProducerNode body;
190 private Map verbNodes;
192 private String defaultVerb;
194 public ProducerSectionHandler(String aName) {
198 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
199 if (aTag.equals("verbs")) {
201 throw new XMLParserExc("Verbs already processed");
203 throw new XMLParserExc("Verbs should come before body");
205 return new ProducerVerbsSectionHandler();
207 else if (aTag.equals("body")) {
209 return new ProducerNodeSectionHandler();
211 throw new XMLParserExc("Body already processed");
213 throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
216 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
217 if (aHandler instanceof ProducerNodeSectionHandler) {
218 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
220 else if (aHandler instanceof ProducerVerbsSectionHandler)
222 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
223 verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
224 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
226 else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
229 public void finishSection() throws XMLParserExc {
231 throw new XMLParserExc("No verbs defined");
234 throw new XMLParserExc("No body defined");
236 producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
239 public ProducerFactory getProducerFactory() {
240 return producerFactory;
244 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
245 private final static String PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";
246 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
247 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
248 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
250 public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
251 private Map verbNodes;
253 private String defaultVerb;
254 private String currentVerb;
255 private String currentVerbDescription;
257 public ProducerVerbsSectionHandler() {
258 verbNodes = new HashMap();
259 verbs = new ArrayList();
263 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
264 if (aTag.equals("verb")) {
265 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
266 PRODUCER_VERB_REQUIRED_ATTRIBUTES,
267 PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
268 currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
270 mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
272 if (verbNodes.containsKey(currentVerb))
273 throw new XMLParserExc("Duplicate definition of verb '" +
276 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
277 if (defaultVerb != null)
278 throw new XMLParserExc("Default verb already declared");
280 defaultVerb = currentVerb;
283 if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
284 currentVerbDescription = (String) anAttributes.get(
285 PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
287 currentVerbDescription = "";
289 return new ProducerNodeSectionHandler();
292 throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
295 public void endElement(mir.util.xml.SectionHandler aHandler) {
296 verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
297 verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
300 public void finishSection() {
303 public String getDefaultVerb() {
307 public List getVerbs() {
311 public Map getVerbNodes() {
316 public class EmptySectionHandler extends mir.util.xml.AbstractSectionHandler {
317 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
318 throw new XMLParserExc("No tags are allowed here");
321 public void endElement(mir.util.xml.SectionHandler aHandler) {
324 public void finishSection() {
328 public class MultiProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
329 private Map nodeParameters;
330 private Set validNodeParameters;
331 private String currentNodeParameter;
332 private String scriptedNodeName;
333 private Set allowedNodeParameterReferences;
335 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
336 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
337 scriptedNodeName = aScriptedNodeName;
338 validNodeParameters = aValidNodeParameters;
339 nodeParameters = new HashMap();
341 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
342 this("", new HashSet(), aValidNodeParameters);
345 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
346 if (!validNodeParameters.contains(aTag))
347 throw new XMLParserExc("Invalid node parameter: '" + aTag + "'");
348 else if (nodeParameters.containsKey(aTag))
349 throw new XMLParserExc("Node parameter: '" + aTag + "' already specified");
350 else if (anAttributes.size()>0)
351 throw new XMLParserExc("No parameters are allowed here");
353 currentNodeParameter = aTag;
355 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
358 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
359 if (aHandler instanceof ProducerNodeSectionHandler) {
360 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
363 throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
367 public Map getNodeParameters() {
368 return nodeParameters;
371 public void finishSection() {
375 public class ProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
376 private CompositeProducerNode producerNode;
377 private ProducerNodeBuilder currentBuilder;
378 private String scriptedNodeName;
379 private Set allowedNodeParameterReferences;
381 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
382 producerNode = new CompositeProducerNode();
383 scriptedNodeName = aScriptedNodeName;
384 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
387 public ProducerNodeSectionHandler() {
388 this("", new HashSet());
391 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
393 if (allowedNodeParameterReferences.contains( (aTag))) {
394 if (!anAttributes.isEmpty()) {
395 throw new XMLParserExc("No attributes allowed");
398 currentBuilder = new DefaultProducerNodeBuilders.
399 ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
400 return new EmptySectionHandler();
402 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
403 builderLibrary.hasBuilderForName( (aTag))) {
405 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
406 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
408 currentBuilder = builderLibrary.constructBuilder(aTag);
410 currentBuilder.setAttributes(anAttributes);
411 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
412 return new EmptySectionHandler();
414 if (currentBuilder.getAvailableSubNodes().size() > 1)
415 return new MultiProducerNodeSectionHandler(scriptedNodeName,
416 allowedNodeParameterReferences,
417 currentBuilder.getAvailableSubNodes());
418 else if (currentBuilder.getAvailableSubNodes().size() < 1)
419 return new EmptySectionHandler();
421 return new ProducerNodeSectionHandler(scriptedNodeName,
422 allowedNodeParameterReferences);
426 throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
428 catch (Throwable t) {
429 throw new XMLParserFailure(t);
433 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
435 if (aHandler instanceof ProducerNodeSectionHandler) {
436 currentBuilder.setSubNode(
437 (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
438 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
440 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
445 nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
447 i = nodeParameters.entrySet().iterator();
448 while (i.hasNext()) {
449 entry = (Map.Entry) i.next();
450 currentBuilder.setSubNode( (String) entry.getKey(),
451 (ProducerNode) entry.getValue());
454 else if (aHandler instanceof EmptySectionHandler) {
455 // deliberately empty: nothing expected, so nothing to process
458 throw new XMLParserExc(
459 "Internal error: unknown section handler '" +
460 aHandler.getClass().getName() + "'");
463 producerNode.addSubNode(currentBuilder.constructNode());
464 currentBuilder = null;
466 catch (Throwable t) {
467 throw new XMLParserFailure(t);
471 public ProducerNode getProducerNode() {
472 if (producerNode.getNrSubNodes()==1) {
473 return producerNode.getSubNode(0);
480 public void finishSection() {
484 public class NodeDefinitionSectionHandler extends mir.util.xml.AbstractSectionHandler {
485 private ScriptedProducerNodeDefinition nodeDefinition;
486 private ProducerNode body;
487 private Map stringParameters;
488 private Map integerParameters;
489 private Map nodeParameters;
492 public NodeDefinitionSectionHandler(String aName) {
494 nodeParameters = null;
495 stringParameters = null;
496 integerParameters = null;
500 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
501 if (aTag.equals("parameters")) {
502 if (!anAttributes.isEmpty()) {
503 throw new XMLParserExc( "No attributes allowed for tag 'parameters'" );
505 if (nodeParameters!=null) {
506 throw new XMLParserExc( "Parameters have already been declared" );
509 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
512 return new NodeDefinitionParametersSectionHandler();
514 else if (aTag.equals("definition")) {
515 if (nodeParameters==null)
516 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
518 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
520 else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
523 public void endElement(mir.util.xml.SectionHandler aHandler) {
524 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
525 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
526 integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
527 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
529 else if (aHandler instanceof ProducerNodeSectionHandler) {
530 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
534 public void finishSection() throws XMLParserExc {
537 throw new XMLParserExc( "Definition missing" );
539 nodeDefinition = new ScriptedProducerNodeDefinition(name);
541 nodeDefinition.setBody(body);
543 i = nodeParameters.keySet().iterator();
544 while (i.hasNext()) {
545 nodeDefinition.addNodeParameter((String) i.next());
548 i = stringParameters.entrySet().iterator();
549 while (i.hasNext()) {
550 Map.Entry entry = (Map.Entry) i.next();
551 nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());
554 i = integerParameters.entrySet().iterator();
555 while (i.hasNext()) {
556 Map.Entry entry = (Map.Entry) i.next();
557 nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());
561 public ScriptedProducerNodeDefinition getDefinition() {
562 return nodeDefinition;
566 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
567 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
568 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
569 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
570 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
572 public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
573 private Map nodeParameters;
574 private Map stringParameters;
575 private Map integerParameters;
577 public NodeDefinitionParametersSectionHandler() {
578 nodeParameters = new HashMap();
579 stringParameters = new HashMap();
580 integerParameters = new HashMap();
583 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
584 String parameterName;
587 if (aTag.equals("node")) {
588 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
589 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
590 NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
591 parameterName = (String) anAttributes.get(
592 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
594 if (nodeParameters.containsKey(parameterName))
595 throw new XMLParserExc("Duplicate parameter name: '" +
596 parameterName + "'");
598 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
600 nodeParameters.put(parameterName, parameterName);
602 return new EmptySectionHandler();
604 else if (aTag.equals("string") || aTag.equals("integer")) {
605 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
606 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
607 NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
608 parameterName = (String) anAttributes.get(
609 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
611 if (stringParameters.containsKey(parameterName) ||
612 integerParameters.containsKey(parameterName))
613 throw new XMLParserExc("Duplicate parameter name: '" +
614 parameterName + "'");
616 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
618 defaultValue = (String) anAttributes.get(
619 NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
621 if (aTag.equals("string"))
622 stringParameters.put(parameterName, defaultValue);
624 integerParameters.put(parameterName, defaultValue);
626 return new EmptySectionHandler();
629 throw new XMLParserExc(
630 "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
633 public void endElement(mir.util.xml.SectionHandler aHandler) {
636 public void finishSection() {
639 public Map getNodeParameters() {
640 return nodeParameters;
643 public Map getStringParameters() {
644 return stringParameters;
647 public Map getIntegerParameters() {
648 return integerParameters;