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 java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.List;
38 import java.util.Vector;
41 import mir.producer.CompositeProducerNode;
42 import mir.producer.ProducerFactory;
43 import mir.producer.ProducerNode;
44 import mir.producer.SimpleProducerVerb;
45 import mir.util.ExceptionFunctions;
46 import mir.util.xml.XMLParserEngine;
47 import mir.util.xml.XMLParserExc;
48 import mir.util.xml.XMLParserFailure;
50 public class ProducerConfigReader {
51 private ProducerNodeBuilderLibrary builderLibrary;
52 private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
54 public ProducerConfigReader() {
58 public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
60 builderLibrary = aBuilderLibrary;
61 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
63 XMLParserEngine.getInstance().parse("", aFile, new RootSectionHandler(aProducerFactories));
67 Throwable root = ExceptionFunctions.traceCauseException(e);
69 if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
70 XMLParserExc f = (XMLParserExc) root;
71 throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
73 throw new ProducerConfigFailure(root);
77 public class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
78 private List producers;
80 public RootSectionHandler(List aProducers) {
81 producers = aProducers;
84 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
85 if (aTag.equals("producers")) {
86 return new ProducersSectionHandler(producers);
89 throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
92 public void endElement(mir.util.xml.SectionHandler aHandler) {
95 public void finishSection() {
99 private final static String PRODUCER_NAME_ATTRIBUTE = "name";
100 private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
101 private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
103 private final static String NODE_DEFINITION_NAME_ATTRIBUTE = "name";
104 private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
105 private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = { };
107 public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
108 private List producers;
109 private Set producerNames;
112 public ProducersSectionHandler(List aProducers) {
113 producers = aProducers;
114 producerNames = new HashSet();
117 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
118 if (aTag.equals("producer")) {
119 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
120 PRODUCER_REQUIRED_ATTRIBUTES,
121 PRODUCER_OPTIONAL_ATTRIBUTES);
123 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
124 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
126 if (producerNames.contains(name))
127 throw new XMLParserExc("Duplicate producer name: '" +
130 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
132 return new ProducerSectionHandler(name);
134 else if (aTag.equals("nodedefinition")) {
135 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
136 NODE_DEFINITION_REQUIRED_ATTRIBUTES,
137 NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
139 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
140 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
142 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
144 return new NodeDefinitionSectionHandler(name);
146 throw new XMLParserExc("Unexpected tag: " + aTag);
149 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
150 if (aHandler instanceof ProducerSectionHandler) {
151 producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
152 producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
154 else if (aHandler instanceof NodeDefinitionSectionHandler) {
155 scriptedNodeBuilderLibrary.registerFactory(name,
156 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
157 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
159 else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
162 public void finishSection() {
166 public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
167 private ProducerFactory producerFactory;
168 private String factoryName;
170 private ProducerNode body;
171 private Map verbNodes;
173 private String defaultVerb;
175 public ProducerSectionHandler(String aName) {
179 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
180 if (aTag.equals("verbs")) {
182 throw new XMLParserExc("Verbs already processed");
184 throw new XMLParserExc("Verbs should come before body");
186 return new ProducerVerbsSectionHandler();
188 else if (aTag.equals("body")) {
190 return new ProducerNodeSectionHandler();
192 throw new XMLParserExc("Body already processed");
194 throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
197 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
198 if (aHandler instanceof ProducerNodeSectionHandler) {
199 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
201 else if (aHandler instanceof ProducerVerbsSectionHandler)
203 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
204 verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
205 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
207 else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
210 public void finishSection() throws XMLParserExc {
212 throw new XMLParserExc("No verbs defined");
215 throw new XMLParserExc("No body defined");
217 producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
220 public ProducerFactory getProducerFactory() {
221 return producerFactory;
225 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
226 private final static String PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";
227 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
228 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
229 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
231 public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
232 private Map verbNodes;
234 private String defaultVerb;
235 private String currentVerb;
236 private String currentVerbDescription;
238 public ProducerVerbsSectionHandler() {
239 verbNodes = new HashMap();
240 verbs = new Vector();
244 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
245 if (aTag.equals("verb")) {
246 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
247 PRODUCER_VERB_REQUIRED_ATTRIBUTES,
248 PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
249 currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
251 mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
253 if (verbNodes.containsKey(currentVerb))
254 throw new XMLParserExc("Duplicate definition of verb '" +
257 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
258 if (defaultVerb != null)
259 throw new XMLParserExc("Default verb already declared");
261 defaultVerb = currentVerb;
264 if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
265 currentVerbDescription = (String) anAttributes.get(
266 PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
268 currentVerbDescription = "";
270 return new ProducerNodeSectionHandler();
273 throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
276 public void endElement(mir.util.xml.SectionHandler aHandler) {
277 verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
278 verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
281 public void finishSection() {
284 public String getDefaultVerb() {
288 public List getVerbs() {
292 public Map getVerbNodes() {
297 public class EmptySectionHandler extends mir.util.xml.AbstractSectionHandler {
298 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
299 throw new XMLParserExc("No tags are allowed here");
302 public void endElement(mir.util.xml.SectionHandler aHandler) {
305 public void finishSection() {
309 public class MultiProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
310 private Map nodeParameters;
311 private Set validNodeParameters;
312 private String currentNodeParameter;
313 private String scriptedNodeName;
314 private Set allowedNodeParameterReferences;
316 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
317 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
318 scriptedNodeName = aScriptedNodeName;
319 validNodeParameters = aValidNodeParameters;
320 nodeParameters = new HashMap();
322 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
323 this("", new HashSet(), aValidNodeParameters);
326 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
327 if (!validNodeParameters.contains(aTag))
328 throw new XMLParserExc("Invalid node parameter: '" + aTag + "'");
329 else if (nodeParameters.containsKey(aTag))
330 throw new XMLParserExc("Node parameter: '" + aTag + "' already specified");
331 else if (anAttributes.size()>0)
332 throw new XMLParserExc("No parameters are allowed here");
334 currentNodeParameter = aTag;
336 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
339 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
340 if (aHandler instanceof ProducerNodeSectionHandler) {
341 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
344 throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
348 public Map getNodeParameters() {
349 return nodeParameters;
352 public void finishSection() {
356 public class ProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
357 private CompositeProducerNode producerNode;
358 private ProducerNodeBuilder currentBuilder;
359 private String scriptedNodeName;
360 private Set allowedNodeParameterReferences;
362 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
363 producerNode = new CompositeProducerNode();
364 scriptedNodeName = aScriptedNodeName;
365 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
368 public ProducerNodeSectionHandler() {
369 this("", new HashSet());
372 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
374 if (allowedNodeParameterReferences.contains( (aTag))) {
375 if (!anAttributes.isEmpty()) {
376 throw new XMLParserExc("No attributes allowed");
379 currentBuilder = new DefaultProducerNodeBuilders.
380 ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
381 return new EmptySectionHandler();
383 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
384 builderLibrary.hasBuilderForName( (aTag))) {
386 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
387 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
389 currentBuilder = builderLibrary.constructBuilder(aTag);
391 currentBuilder.setAttributes(anAttributes);
392 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
393 return new EmptySectionHandler();
395 if (currentBuilder.getAvailableSubNodes().size() > 1)
396 return new MultiProducerNodeSectionHandler(scriptedNodeName,
397 allowedNodeParameterReferences,
398 currentBuilder.getAvailableSubNodes());
399 else if (currentBuilder.getAvailableSubNodes().size() < 1)
400 return new EmptySectionHandler();
402 return new ProducerNodeSectionHandler(scriptedNodeName,
403 allowedNodeParameterReferences);
407 throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
409 catch (Throwable t) {
410 throw new XMLParserFailure(t);
414 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
416 if (aHandler instanceof ProducerNodeSectionHandler) {
417 currentBuilder.setSubNode(
418 (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
419 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
421 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
426 nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
428 i = nodeParameters.entrySet().iterator();
429 while (i.hasNext()) {
430 entry = (Map.Entry) i.next();
431 currentBuilder.setSubNode( (String) entry.getKey(),
432 (ProducerNode) entry.getValue());
435 else if (aHandler instanceof EmptySectionHandler) {
436 // deliberately empty: nothing expected, so nothing to process
439 throw new XMLParserExc(
440 "Internal error: unknown section handler '" +
441 aHandler.getClass().getName() + "'");
444 producerNode.addSubNode(currentBuilder.constructNode());
445 currentBuilder = null;
447 catch (Throwable t) {
448 throw new XMLParserFailure(t);
452 public ProducerNode getProducerNode() {
453 if (producerNode.getNrSubNodes()==1) {
454 return producerNode.getSubNode(0);
461 public void finishSection() {
465 public class NodeDefinitionSectionHandler extends mir.util.xml.AbstractSectionHandler {
466 private ScriptedProducerNodeDefinition nodeDefinition;
467 private ProducerNode body;
468 private Map stringParameters;
469 private Map integerParameters;
470 private Map nodeParameters;
473 public NodeDefinitionSectionHandler(String aName) {
475 nodeParameters = null;
476 stringParameters = null;
477 integerParameters = null;
481 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
482 if (aTag.equals("parameters")) {
483 if (!anAttributes.isEmpty()) {
484 throw new XMLParserExc( "No attributes allowed for tag 'parameters'" );
486 if (nodeParameters!=null) {
487 throw new XMLParserExc( "Parameters have already been declared" );
490 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
493 return new NodeDefinitionParametersSectionHandler();
495 else if (aTag.equals("definition")) {
496 if (nodeParameters==null)
497 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
499 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
501 else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
504 public void endElement(mir.util.xml.SectionHandler aHandler) {
505 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
506 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
507 integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
508 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
510 else if (aHandler instanceof ProducerNodeSectionHandler) {
511 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
515 public void finishSection() throws XMLParserExc {
518 throw new XMLParserExc( "Definition missing" );
520 nodeDefinition = new ScriptedProducerNodeDefinition(name);
522 nodeDefinition.setBody(body);
524 i = nodeParameters.keySet().iterator();
525 while (i.hasNext()) {
526 nodeDefinition.addNodeParameter((String) i.next());
529 i = stringParameters.entrySet().iterator();
530 while (i.hasNext()) {
531 Map.Entry entry = (Map.Entry) i.next();
532 nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());
535 i = integerParameters.entrySet().iterator();
536 while (i.hasNext()) {
537 Map.Entry entry = (Map.Entry) i.next();
538 nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());
542 public ScriptedProducerNodeDefinition getDefinition() {
543 return nodeDefinition;
547 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
548 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
549 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
550 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
551 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
553 public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
554 private Map nodeParameters;
555 private Map stringParameters;
556 private Map integerParameters;
558 public NodeDefinitionParametersSectionHandler() {
559 nodeParameters = new HashMap();
560 stringParameters = new HashMap();
561 integerParameters = new HashMap();
564 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
565 String parameterName;
568 if (aTag.equals("node")) {
569 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
570 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
571 NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
572 parameterName = (String) anAttributes.get(
573 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
575 if (nodeParameters.containsKey(parameterName))
576 throw new XMLParserExc("Duplicate parameter name: '" +
577 parameterName + "'");
579 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
581 nodeParameters.put(parameterName, parameterName);
583 return new EmptySectionHandler();
585 else if (aTag.equals("string") || aTag.equals("integer")) {
586 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
587 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
588 NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
589 parameterName = (String) anAttributes.get(
590 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
592 if (stringParameters.containsKey(parameterName) ||
593 integerParameters.containsKey(parameterName))
594 throw new XMLParserExc("Duplicate parameter name: '" +
595 parameterName + "'");
597 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
599 defaultValue = (String) anAttributes.get(
600 NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
602 if (aTag.equals("string"))
603 stringParameters.put(parameterName, defaultValue);
605 integerParameters.put(parameterName, defaultValue);
607 return new EmptySectionHandler();
610 throw new XMLParserExc(
611 "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
614 public void endElement(mir.util.xml.SectionHandler aHandler) {
617 public void finishSection() {
620 public Map getNodeParameters() {
621 return nodeParameters;
624 public Map getStringParameters() {
625 return stringParameters;
628 public Map getIntegerParameters() {
629 return integerParameters;