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;
32 import mir.producer.CompositeProducerNode;
33 import mir.producer.ProducerFactory;
34 import mir.producer.ProducerNode;
35 import mir.producer.SimpleProducerVerb;
36 import mir.util.ExceptionRoutines;
37 import mir.util.xml.XMLParserEngine;
38 import mir.util.xml.XMLParserExc;
39 import mir.util.xml.XMLParserFailure;
42 import java.io.Reader;
43 import java.util.ArrayList;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.List;
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 = ExceptionRoutines.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 = ExceptionRoutines.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);
107 throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
110 public void endElement(mir.util.xml.SectionHandler aHandler) {
113 public void finishSection() {
117 private final static String PRODUCER_NAME_ATTRIBUTE = "name";
118 private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
119 private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
121 private final static String NODE_DEFINITION_NAME_ATTRIBUTE = "name";
122 private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
123 private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = { };
125 public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
126 private List producers;
127 private Set producerNames;
130 public ProducersSectionHandler(List aProducers) {
131 producers = aProducers;
132 producerNames = new HashSet();
135 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
136 if (aTag.equals("producer")) {
137 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
138 PRODUCER_REQUIRED_ATTRIBUTES,
139 PRODUCER_OPTIONAL_ATTRIBUTES);
141 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
142 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
144 if (producerNames.contains(name))
145 throw new XMLParserExc("Duplicate producer name: '" +
148 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
150 return new ProducerSectionHandler(name);
152 else if (aTag.equals("nodedefinition")) {
153 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
154 NODE_DEFINITION_REQUIRED_ATTRIBUTES,
155 NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
157 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
158 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
160 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
162 return new NodeDefinitionSectionHandler(name);
164 throw new XMLParserExc("Unexpected tag: " + aTag);
167 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
168 if (aHandler instanceof ProducerSectionHandler) {
169 producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
170 producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
172 else if (aHandler instanceof NodeDefinitionSectionHandler) {
173 scriptedNodeBuilderLibrary.registerFactory(name,
174 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
175 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
177 else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
180 public void finishSection() {
184 public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
185 private ProducerFactory producerFactory;
186 private String factoryName;
188 private ProducerNode body;
189 private Map verbNodes;
191 private String defaultVerb;
193 public ProducerSectionHandler(String aName) {
197 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
198 if (aTag.equals("verbs")) {
200 throw new XMLParserExc("Verbs already processed");
202 throw new XMLParserExc("Verbs should come before body");
203 return new ProducerVerbsSectionHandler();
205 else if (aTag.equals("body")) {
207 return new ProducerNodeSectionHandler();
208 throw new XMLParserExc("Body already processed");
210 throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
213 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
214 if (aHandler instanceof ProducerNodeSectionHandler) {
215 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
217 else if (aHandler instanceof ProducerVerbsSectionHandler)
219 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
220 verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
221 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
223 else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
226 public void finishSection() throws XMLParserExc {
228 throw new XMLParserExc("No verbs defined");
231 throw new XMLParserExc("No body defined");
233 producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
236 public ProducerFactory getProducerFactory() {
237 return producerFactory;
241 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
242 private final static String PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";
243 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
244 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
245 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
247 public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
248 private Map verbNodes;
250 private String defaultVerb;
251 private String currentVerb;
252 private String currentVerbDescription;
254 public ProducerVerbsSectionHandler() {
255 verbNodes = new HashMap();
256 verbs = new ArrayList();
260 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
261 if (aTag.equals("verb")) {
262 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
263 PRODUCER_VERB_REQUIRED_ATTRIBUTES,
264 PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
265 currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
267 mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
269 if (verbNodes.containsKey(currentVerb))
270 throw new XMLParserExc("Duplicate definition of verb '" +
273 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
274 if (defaultVerb != null)
275 throw new XMLParserExc("Default verb already declared");
277 defaultVerb = currentVerb;
280 if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
281 currentVerbDescription = (String) anAttributes.get(
282 PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
284 currentVerbDescription = "";
286 return new ProducerNodeSectionHandler();
288 throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
291 public void endElement(mir.util.xml.SectionHandler aHandler) {
292 verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
293 verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
296 public void finishSection() {
299 public String getDefaultVerb() {
303 public List getVerbs() {
307 public Map getVerbNodes() {
312 public class EmptySectionHandler extends mir.util.xml.AbstractSectionHandler {
313 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
314 throw new XMLParserExc("No tags are allowed here");
317 public void endElement(mir.util.xml.SectionHandler aHandler) {
320 public void finishSection() {
324 public class MultiProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
325 private Map nodeParameters;
326 private Set validNodeParameters;
327 private String currentNodeParameter;
328 private String scriptedNodeName;
329 private Set allowedNodeParameterReferences;
331 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
332 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
333 scriptedNodeName = aScriptedNodeName;
334 validNodeParameters = aValidNodeParameters;
335 nodeParameters = new HashMap();
337 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
338 this("", new HashSet(), aValidNodeParameters);
341 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
342 if (!validNodeParameters.contains(aTag))
343 throw new XMLParserExc("Invalid node parameter: '" + aTag + "'");
344 else if (nodeParameters.containsKey(aTag))
345 throw new XMLParserExc("Node parameter: '" + aTag + "' already specified");
346 else if (anAttributes.size()>0)
347 throw new XMLParserExc("No parameters are allowed here");
349 currentNodeParameter = aTag;
351 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
354 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
355 if (aHandler instanceof ProducerNodeSectionHandler) {
356 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
359 throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
363 public Map getNodeParameters() {
364 return nodeParameters;
367 public void finishSection() {
371 public class ProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
372 private CompositeProducerNode producerNode;
373 private ProducerNodeBuilder currentBuilder;
374 private String scriptedNodeName;
375 private Set allowedNodeParameterReferences;
377 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
378 producerNode = new CompositeProducerNode();
379 scriptedNodeName = aScriptedNodeName;
380 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
383 public ProducerNodeSectionHandler() {
384 this("", new HashSet());
387 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
389 if (allowedNodeParameterReferences.contains( (aTag))) {
390 if (!anAttributes.isEmpty()) {
391 throw new XMLParserExc("No attributes allowed");
394 currentBuilder = new DefaultProducerNodeBuilders.
395 ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
396 return new EmptySectionHandler();
398 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
399 builderLibrary.hasBuilderForName( (aTag))) {
401 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
402 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
404 currentBuilder = builderLibrary.constructBuilder(aTag);
406 currentBuilder.setAttributes(anAttributes);
407 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
408 return new EmptySectionHandler();
410 if (currentBuilder.getAvailableSubNodes().size() > 1)
411 return new MultiProducerNodeSectionHandler(scriptedNodeName,
412 allowedNodeParameterReferences,
413 currentBuilder.getAvailableSubNodes());
414 else if (currentBuilder.getAvailableSubNodes().size() < 1)
415 return new EmptySectionHandler();
417 return new ProducerNodeSectionHandler(scriptedNodeName,
418 allowedNodeParameterReferences);
422 throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
424 catch (Throwable t) {
425 throw new XMLParserFailure(t);
429 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
431 if (aHandler instanceof ProducerNodeSectionHandler) {
432 currentBuilder.setSubNode(
433 (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
434 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
436 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
441 nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
443 i = nodeParameters.entrySet().iterator();
444 while (i.hasNext()) {
445 entry = (Map.Entry) i.next();
446 currentBuilder.setSubNode( (String) entry.getKey(),
447 (ProducerNode) entry.getValue());
450 else if (aHandler instanceof EmptySectionHandler) {
451 // deliberately empty: nothing expected, so nothing to process
454 throw new XMLParserExc(
455 "Internal error: unknown section handler '" +
456 aHandler.getClass().getName() + "'");
459 producerNode.addSubNode(currentBuilder.constructNode());
460 currentBuilder = null;
462 catch (Throwable t) {
463 throw new XMLParserFailure(t);
467 public ProducerNode getProducerNode() {
468 if (producerNode.getNrSubNodes()==1) {
469 return producerNode.getSubNode(0);
474 public void finishSection() {
478 public class NodeDefinitionSectionHandler extends mir.util.xml.AbstractSectionHandler {
479 private ScriptedProducerNodeDefinition nodeDefinition;
480 private ProducerNode body;
481 private Map stringParameters;
482 private Map integerParameters;
483 private Map nodeParameters;
486 public NodeDefinitionSectionHandler(String aName) {
488 nodeParameters = null;
489 stringParameters = null;
490 integerParameters = null;
494 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
495 if (aTag.equals("parameters")) {
496 if (!anAttributes.isEmpty()) {
497 throw new XMLParserExc( "No attributes allowed for tag 'parameters'" );
499 if (nodeParameters!=null) {
500 throw new XMLParserExc( "Parameters have already been declared" );
503 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
506 return new NodeDefinitionParametersSectionHandler();
508 else if (aTag.equals("definition")) {
509 if (nodeParameters==null)
510 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
512 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
514 else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
517 public void endElement(mir.util.xml.SectionHandler aHandler) {
518 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
519 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
520 integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
521 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
523 else if (aHandler instanceof ProducerNodeSectionHandler) {
524 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
528 public void finishSection() throws XMLParserExc {
531 throw new XMLParserExc( "Definition missing" );
533 nodeDefinition = new ScriptedProducerNodeDefinition(name);
535 nodeDefinition.setBody(body);
537 i = nodeParameters.keySet().iterator();
538 while (i.hasNext()) {
539 nodeDefinition.addNodeParameter((String) i.next());
542 i = stringParameters.entrySet().iterator();
543 while (i.hasNext()) {
544 Map.Entry entry = (Map.Entry) i.next();
545 nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());
548 i = integerParameters.entrySet().iterator();
549 while (i.hasNext()) {
550 Map.Entry entry = (Map.Entry) i.next();
551 nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());
555 public ScriptedProducerNodeDefinition getDefinition() {
556 return nodeDefinition;
560 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
561 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
562 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
563 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
564 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
566 public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
567 private Map nodeParameters;
568 private Map stringParameters;
569 private Map integerParameters;
571 public NodeDefinitionParametersSectionHandler() {
572 nodeParameters = new HashMap();
573 stringParameters = new HashMap();
574 integerParameters = new HashMap();
577 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
578 String parameterName;
581 if (aTag.equals("node")) {
582 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
583 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
584 NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
585 parameterName = (String) anAttributes.get(
586 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
588 if (nodeParameters.containsKey(parameterName))
589 throw new XMLParserExc("Duplicate parameter name: '" +
590 parameterName + "'");
592 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
594 nodeParameters.put(parameterName, parameterName);
596 return new EmptySectionHandler();
598 else if (aTag.equals("string") || aTag.equals("integer")) {
599 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
600 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
601 NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
602 parameterName = (String) anAttributes.get(
603 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
605 if (stringParameters.containsKey(parameterName) ||
606 integerParameters.containsKey(parameterName))
607 throw new XMLParserExc("Duplicate parameter name: '" +
608 parameterName + "'");
610 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
612 defaultValue = (String) anAttributes.get(
613 NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
615 if (aTag.equals("string"))
616 stringParameters.put(parameterName, defaultValue);
618 integerParameters.put(parameterName, defaultValue);
620 return new EmptySectionHandler();
623 throw new XMLParserExc(
624 "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
627 public void endElement(mir.util.xml.SectionHandler aHandler) {
630 public void finishSection() {
633 public Map getNodeParameters() {
634 return nodeParameters;
637 public Map getStringParameters() {
638 return stringParameters;
641 public Map getIntegerParameters() {
642 return integerParameters;