2 * Copyright (C) 2001-2006 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 * and distribute linked combinations including the two. You must obey the
23 * GNU General Public License in all respects for all of the code used other than
24 * the above mentioned libraries. If you modify this file, you may extend this
25 * exception to your version of the file, but you are not obligated to do so.
26 * If you do not wish to do so, delete this exception statement from your version.
28 package mir.producer.reader;
30 import mir.producer.CompositeProducerNode;
31 import mir.producer.ProducerFactory;
32 import mir.producer.ProducerNode;
33 import mir.producer.SimpleProducerVerb;
34 import mir.util.ExceptionRoutines;
35 import mir.util.xml.XMLParserEngine;
36 import mir.util.xml.XMLParserExc;
37 import mir.util.xml.XMLParserFailure;
40 import java.io.Reader;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.List;
49 public class ProducerConfigReader {
50 private ProducerNodeBuilderLibrary builderLibrary;
51 private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
53 public ProducerConfigReader() {
57 public void parse(Reader aReader, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
59 builderLibrary = aBuilderLibrary;
60 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
62 XMLParserEngine.getInstance().parse("", aReader, new RootSectionHandler(aProducerFactories));
66 Throwable root = ExceptionRoutines.traceCauseException(e);
68 if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
69 XMLParserExc f = (XMLParserExc) root;
70 throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
72 throw new ProducerConfigFailure(root);
75 public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
77 builderLibrary = aBuilderLibrary;
78 scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
80 XMLParserEngine.getInstance().parse("", aFile, new RootSectionHandler(aProducerFactories));
84 Throwable root = ExceptionRoutines.traceCauseException(e);
86 if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) {
87 XMLParserExc f = (XMLParserExc) root;
88 throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e);
90 throw new ProducerConfigFailure(root);
94 public class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
95 private List producers;
97 public RootSectionHandler(List aProducers) {
98 producers = aProducers;
101 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
102 if (aTag.equals("producers")) {
103 return new ProducersSectionHandler(producers);
105 throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
108 public void endElement(mir.util.xml.SectionHandler aHandler) {
111 public void finishSection() {
115 private final static String PRODUCER_NAME_ATTRIBUTE = "name";
116 private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
117 private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
119 private final static String NODE_DEFINITION_NAME_ATTRIBUTE = "name";
120 private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
121 private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = { };
123 public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
124 private List producers;
125 private Set producerNames;
128 public ProducersSectionHandler(List aProducers) {
129 producers = aProducers;
130 producerNames = new HashSet();
133 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
134 if (aTag.equals("producer")) {
135 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
136 PRODUCER_REQUIRED_ATTRIBUTES,
137 PRODUCER_OPTIONAL_ATTRIBUTES);
139 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
140 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
142 if (producerNames.contains(name))
143 throw new XMLParserExc("Duplicate producer name: '" +
146 name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
148 return new ProducerSectionHandler(name);
150 else if (aTag.equals("nodedefinition")) {
151 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
152 NODE_DEFINITION_REQUIRED_ATTRIBUTES,
153 NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
155 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
156 mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
158 name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
160 return new NodeDefinitionSectionHandler(name);
162 throw new XMLParserExc("Unexpected tag: " + aTag);
165 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
166 if (aHandler instanceof ProducerSectionHandler) {
167 producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
168 producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
170 else if (aHandler instanceof NodeDefinitionSectionHandler) {
171 scriptedNodeBuilderLibrary.registerFactory(name,
172 new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
173 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
175 else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
178 public void finishSection() {
182 public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
183 private ProducerFactory producerFactory;
184 private String factoryName;
186 private ProducerNode body;
187 private Map verbNodes;
189 private String defaultVerb;
191 public ProducerSectionHandler(String aName) {
195 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
196 if (aTag.equals("verbs")) {
198 throw new XMLParserExc("Verbs already processed");
200 throw new XMLParserExc("Verbs should come before body");
201 return new ProducerVerbsSectionHandler();
203 else if (aTag.equals("body")) {
205 return new ProducerNodeSectionHandler();
206 throw new XMLParserExc("Body already processed");
208 throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
211 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
212 if (aHandler instanceof ProducerNodeSectionHandler) {
213 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
215 else if (aHandler instanceof ProducerVerbsSectionHandler)
217 verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
218 verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
219 defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
221 else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
224 public void finishSection() throws XMLParserExc {
226 throw new XMLParserExc("No verbs defined");
229 throw new XMLParserExc("No body defined");
231 producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
234 public ProducerFactory getProducerFactory() {
235 return producerFactory;
239 private final static String PRODUCER_VERB_NAME_ATTRIBUTE = "name";
240 private final static String PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";
241 private final static String PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
242 private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
243 private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
245 public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
246 private Map verbNodes;
248 private String defaultVerb;
249 private String currentVerb;
250 private String currentVerbDescription;
252 public ProducerVerbsSectionHandler() {
253 verbNodes = new HashMap();
254 verbs = new ArrayList();
258 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
259 if (aTag.equals("verb")) {
260 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
261 PRODUCER_VERB_REQUIRED_ATTRIBUTES,
262 PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
263 currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
265 mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
267 if (verbNodes.containsKey(currentVerb))
268 throw new XMLParserExc("Duplicate definition of verb '" +
271 if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
272 if (defaultVerb != null)
273 throw new XMLParserExc("Default verb already declared");
275 defaultVerb = currentVerb;
278 if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
279 currentVerbDescription = (String) anAttributes.get(
280 PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
282 currentVerbDescription = "";
284 return new ProducerNodeSectionHandler();
286 throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
289 public void endElement(mir.util.xml.SectionHandler aHandler) {
290 verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
291 verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
294 public void finishSection() {
297 public String getDefaultVerb() {
301 public List getVerbs() {
305 public Map getVerbNodes() {
310 public class EmptySectionHandler extends mir.util.xml.AbstractSectionHandler {
311 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
312 throw new XMLParserExc("No tags are allowed here");
315 public void endElement(mir.util.xml.SectionHandler aHandler) {
318 public void finishSection() {
322 public class MultiProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
323 private Map nodeParameters;
324 private Set validNodeParameters;
325 private String currentNodeParameter;
326 private String scriptedNodeName;
327 private Set allowedNodeParameterReferences;
329 public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
330 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
331 scriptedNodeName = aScriptedNodeName;
332 validNodeParameters = aValidNodeParameters;
333 nodeParameters = new HashMap();
335 public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
336 this("", new HashSet(), aValidNodeParameters);
339 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
340 if (!validNodeParameters.contains(aTag))
341 throw new XMLParserExc("Invalid node parameter: '" + aTag + "'");
342 else if (nodeParameters.containsKey(aTag))
343 throw new XMLParserExc("Node parameter: '" + aTag + "' already specified");
344 else if (anAttributes.size()>0)
345 throw new XMLParserExc("No parameters are allowed here");
347 currentNodeParameter = aTag;
349 return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
352 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
353 if (aHandler instanceof ProducerNodeSectionHandler) {
354 nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
357 throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
361 public Map getNodeParameters() {
362 return nodeParameters;
365 public void finishSection() {
369 public class ProducerNodeSectionHandler extends mir.util.xml.AbstractSectionHandler {
370 private CompositeProducerNode producerNode;
371 private ProducerNodeBuilder currentBuilder;
372 private String scriptedNodeName;
373 private Set allowedNodeParameterReferences;
375 public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
376 producerNode = new CompositeProducerNode();
377 scriptedNodeName = aScriptedNodeName;
378 allowedNodeParameterReferences = anAllowedNodeParameterReferences;
381 public ProducerNodeSectionHandler() {
382 this("", new HashSet());
385 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
387 if (allowedNodeParameterReferences.contains( (aTag))) {
388 if (!anAttributes.isEmpty()) {
389 throw new XMLParserExc("No attributes allowed");
392 currentBuilder = new DefaultProducerNodeBuilders.
393 ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
394 return new EmptySectionHandler();
396 else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
397 builderLibrary.hasBuilderForName( (aTag))) {
399 if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
400 currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
402 currentBuilder = builderLibrary.constructBuilder(aTag);
404 currentBuilder.setAttributes(anAttributes);
405 if (currentBuilder.getAvailableSubNodes().isEmpty()) {
406 return new EmptySectionHandler();
408 if (currentBuilder.getAvailableSubNodes().size() > 1)
409 return new MultiProducerNodeSectionHandler(scriptedNodeName,
410 allowedNodeParameterReferences,
411 currentBuilder.getAvailableSubNodes());
412 else if (currentBuilder.getAvailableSubNodes().size() < 1)
413 return new EmptySectionHandler();
415 return new ProducerNodeSectionHandler(scriptedNodeName,
416 allowedNodeParameterReferences);
420 throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
422 catch (Throwable t) {
423 throw new XMLParserFailure(t);
427 public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
429 if (aHandler instanceof ProducerNodeSectionHandler) {
430 currentBuilder.setSubNode(
431 (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
432 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
434 else if (aHandler instanceof MultiProducerNodeSectionHandler) {
439 nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
441 i = nodeParameters.entrySet().iterator();
442 while (i.hasNext()) {
443 entry = (Map.Entry) i.next();
444 currentBuilder.setSubNode( (String) entry.getKey(),
445 (ProducerNode) entry.getValue());
448 else if (aHandler instanceof EmptySectionHandler) {
449 // deliberately empty: nothing expected, so nothing to process
452 throw new XMLParserExc(
453 "Internal error: unknown section handler '" +
454 aHandler.getClass().getName() + "'");
457 producerNode.addSubNode(currentBuilder.constructNode());
458 currentBuilder = null;
460 catch (Throwable t) {
461 throw new XMLParserFailure(t);
465 public ProducerNode getProducerNode() {
466 if (producerNode.getNrSubNodes()==1) {
467 return producerNode.getSubNode(0);
472 public void finishSection() {
476 public class NodeDefinitionSectionHandler extends mir.util.xml.AbstractSectionHandler {
477 private ScriptedProducerNodeDefinition nodeDefinition;
478 private ProducerNode body;
479 private Map stringParameters;
480 private Map integerParameters;
481 private Map nodeParameters;
484 public NodeDefinitionSectionHandler(String aName) {
486 nodeParameters = null;
487 stringParameters = null;
488 integerParameters = null;
492 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
493 if (aTag.equals("parameters")) {
494 if (!anAttributes.isEmpty()) {
495 throw new XMLParserExc( "No attributes allowed for tag 'parameters'" );
497 if (nodeParameters!=null) {
498 throw new XMLParserExc( "Parameters have already been declared" );
501 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
504 return new NodeDefinitionParametersSectionHandler();
506 else if (aTag.equals("definition")) {
507 if (nodeParameters==null)
508 throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
510 return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
512 else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
515 public void endElement(mir.util.xml.SectionHandler aHandler) {
516 if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
517 stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
518 integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
519 nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
521 else if (aHandler instanceof ProducerNodeSectionHandler) {
522 body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
526 public void finishSection() throws XMLParserExc {
529 throw new XMLParserExc( "Definition missing" );
531 nodeDefinition = new ScriptedProducerNodeDefinition(name);
533 nodeDefinition.setBody(body);
535 i = nodeParameters.keySet().iterator();
536 while (i.hasNext()) {
537 nodeDefinition.addNodeParameter((String) i.next());
540 i = stringParameters.entrySet().iterator();
541 while (i.hasNext()) {
542 Map.Entry entry = (Map.Entry) i.next();
543 nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());
546 i = integerParameters.entrySet().iterator();
547 while (i.hasNext()) {
548 Map.Entry entry = (Map.Entry) i.next();
549 nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());
553 public ScriptedProducerNodeDefinition getDefinition() {
554 return nodeDefinition;
558 private final static String NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
559 private final static String NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
560 private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
561 private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
562 private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
564 public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
565 private Map nodeParameters;
566 private Map stringParameters;
567 private Map integerParameters;
569 public NodeDefinitionParametersSectionHandler() {
570 nodeParameters = new HashMap();
571 stringParameters = new HashMap();
572 integerParameters = new HashMap();
575 public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
576 String parameterName;
579 if (aTag.equals("node")) {
580 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
581 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
582 NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
583 parameterName = (String) anAttributes.get(
584 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
586 if (nodeParameters.containsKey(parameterName))
587 throw new XMLParserExc("Duplicate parameter name: '" +
588 parameterName + "'");
590 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
592 nodeParameters.put(parameterName, parameterName);
594 return new EmptySectionHandler();
596 else if (aTag.equals("string") || aTag.equals("integer")) {
597 mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
598 NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
599 NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
600 parameterName = (String) anAttributes.get(
601 NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
603 if (stringParameters.containsKey(parameterName) ||
604 integerParameters.containsKey(parameterName))
605 throw new XMLParserExc("Duplicate parameter name: '" +
606 parameterName + "'");
608 mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
610 defaultValue = (String) anAttributes.get(
611 NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
613 if (aTag.equals("string"))
614 stringParameters.put(parameterName, defaultValue);
616 integerParameters.put(parameterName, defaultValue);
618 return new EmptySectionHandler();
621 throw new XMLParserExc(
622 "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
625 public void endElement(mir.util.xml.SectionHandler aHandler) {
628 public void finishSection() {
631 public Map getNodeParameters() {
632 return nodeParameters;
635 public Map getStringParameters() {
636 return stringParameters;
639 public Map getIntegerParameters() {
640 return integerParameters;