reintroduced StringUtil.regexpReplace
[mir.git] / source / mir / producer / reader / ProducerConfigReader.java
1 /*
2  * Copyright (C) 2001-2006 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
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.
10  *
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.
15  *
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
19  *
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.
27  */
28 package  mir.producer.reader;
29
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;
38
39 import java.io.File;
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;
46 import java.util.Map;
47 import java.util.Set;
48
49 public class ProducerConfigReader {
50   private ProducerNodeBuilderLibrary builderLibrary;
51   private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
52
53   public ProducerConfigReader() {
54     super();
55   }
56
57   public void parse(Reader aReader, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
58     try {
59       builderLibrary = aBuilderLibrary;
60       scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
61
62       XMLParserEngine.getInstance().parse("", aReader, new RootSectionHandler(aProducerFactories));
63
64     }
65     catch (Throwable e) {
66       Throwable root = ExceptionRoutines.traceCauseException(e);
67
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);
71       }
72       throw new ProducerConfigFailure(root);
73     }
74   }
75   public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
76     try {
77       builderLibrary = aBuilderLibrary;
78       scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
79
80       XMLParserEngine.getInstance().parse("", aFile, new RootSectionHandler(aProducerFactories));
81
82     }
83     catch (Throwable e) {
84       Throwable root = ExceptionRoutines.traceCauseException(e);
85
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);
89       }
90       throw new ProducerConfigFailure(root);
91     }
92   }
93
94   public class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
95     private List producers;
96
97     public RootSectionHandler(List aProducers) {
98       producers = aProducers;
99     }
100
101     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
102       if (aTag.equals("producers")) {
103         return new ProducersSectionHandler(producers);
104       }
105                         throw new XMLParserExc("Tag 'producers' expected, tag '"+aTag+"' found");
106     }
107
108     public void endElement(mir.util.xml.SectionHandler aHandler) {
109     }
110
111     public void finishSection() {
112     }
113   }
114
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 = { };
118
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 = {  };
122
123   public class ProducersSectionHandler extends mir.util.xml.AbstractSectionHandler {
124     private List producers;
125     private Set producerNames;
126     private String name;
127
128     public ProducersSectionHandler(List aProducers) {
129       producers = aProducers;
130       producerNames = new HashSet();
131     }
132
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);
138
139         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
140         mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
141
142         if (producerNames.contains(name))
143           throw new XMLParserExc("Duplicate producer name: '" +
144                                            name + "'");
145
146         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
147
148         return new ProducerSectionHandler(name);
149       }
150       else if (aTag.equals("nodedefinition")) {
151         mir.util.xml.XMLReaderTool.checkAttributes(anAttributes,
152                                       NODE_DEFINITION_REQUIRED_ATTRIBUTES,
153                                       NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
154
155         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
156         mir.util.xml.XMLReaderTool.checkValidIdentifier(name);
157
158         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
159
160         return new NodeDefinitionSectionHandler(name);
161       }
162       throw new XMLParserExc("Unexpected tag: " + aTag);
163     }
164
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());
169       }
170       else if (aHandler instanceof NodeDefinitionSectionHandler) {
171         scriptedNodeBuilderLibrary.registerFactory(name,
172             new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
173                 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
174       }
175       else throw new XMLParserExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
176     }
177
178     public void finishSection() {
179     }
180   }
181
182   public class ProducerSectionHandler extends mir.util.xml.AbstractSectionHandler {
183     private ProducerFactory producerFactory;
184     private String factoryName;
185
186     private ProducerNode body;
187     private Map verbNodes;
188     private List verbs;
189     private String defaultVerb;
190
191     public ProducerSectionHandler(String aName) {
192       factoryName = aName;
193     }
194
195     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
196       if (aTag.equals("verbs")) {
197         if (verbs!=null)
198           throw new XMLParserExc("Verbs already processed");
199         if (body!=null)
200           throw new XMLParserExc("Verbs should come before body");
201                                 return new ProducerVerbsSectionHandler();
202       }
203       else if (aTag.equals("body")) {
204         if (body==null)
205           return new ProducerNodeSectionHandler();
206                                 throw new XMLParserExc("Body already processed");
207       }
208       throw new XMLParserExc("Unexpected tag: '"+aTag+"'");
209     }
210
211     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
212       if (aHandler instanceof ProducerNodeSectionHandler) {
213         body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
214       }
215       else if (aHandler instanceof ProducerVerbsSectionHandler)
216       {
217         verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
218         verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
219         defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
220       }
221       else throw new XMLParserExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
222     }
223
224     public void finishSection() throws XMLParserExc {
225       if (verbs==null)
226         throw new XMLParserExc("No verbs defined");
227
228       if (body==null)
229         throw new XMLParserExc("No body defined");
230
231       producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
232     }
233
234     public ProducerFactory getProducerFactory() {
235       return producerFactory;
236     }
237   }
238
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 };
244
245   public class ProducerVerbsSectionHandler extends mir.util.xml.AbstractSectionHandler {
246     private Map verbNodes;
247     private List verbs;
248     private String defaultVerb;
249     private String currentVerb;
250     private String currentVerbDescription;
251
252     public ProducerVerbsSectionHandler() {
253       verbNodes = new HashMap();
254       verbs = new ArrayList();
255       defaultVerb = null;
256     }
257
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);
264
265         mir.util.xml.XMLReaderTool.checkValidIdentifier(currentVerb);
266
267         if (verbNodes.containsKey(currentVerb))
268           throw new XMLParserExc("Duplicate definition of verb '" +
269                                            currentVerb + "'");
270
271         if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
272           if (defaultVerb != null)
273             throw new XMLParserExc("Default verb already declared");
274
275           defaultVerb = currentVerb;
276         }
277
278         if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
279           currentVerbDescription = (String) anAttributes.get(
280               PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
281         else
282           currentVerbDescription = "";
283
284         return new ProducerNodeSectionHandler();
285       }
286                         throw new XMLParserExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
287     }
288
289     public void endElement(mir.util.xml.SectionHandler aHandler) {
290       verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
291       verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
292     }
293
294     public void finishSection() {
295     }
296
297     public String getDefaultVerb() {
298       return defaultVerb;
299     }
300
301     public List getVerbs() {
302       return verbs;
303     }
304
305     public Map getVerbNodes() {
306       return verbNodes;
307     }
308   }
309
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");
313     }
314
315     public void endElement(mir.util.xml.SectionHandler aHandler) {
316     }
317
318     public void finishSection() {
319     }
320   }
321
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;
328
329     public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
330       allowedNodeParameterReferences = anAllowedNodeParameterReferences;
331       scriptedNodeName = aScriptedNodeName;
332       validNodeParameters = aValidNodeParameters;
333       nodeParameters = new HashMap();
334     }
335     public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
336       this("", new HashSet(), aValidNodeParameters);
337     }
338
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");
346
347       currentNodeParameter = aTag;
348
349       return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
350     }
351
352     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc  {
353       if (aHandler instanceof ProducerNodeSectionHandler) {
354         nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
355       }
356       else {
357         throw new XMLParserExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
358       }
359     }
360
361     public Map getNodeParameters() {
362       return nodeParameters;
363     }
364
365     public void finishSection() {
366     }
367   }
368
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;
374
375     public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
376       producerNode = new CompositeProducerNode();
377       scriptedNodeName = aScriptedNodeName;
378       allowedNodeParameterReferences = anAllowedNodeParameterReferences;
379     }
380
381     public ProducerNodeSectionHandler() {
382       this("", new HashSet());
383     }
384
385     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
386       try {
387         if (allowedNodeParameterReferences.contains( (aTag))) {
388           if (!anAttributes.isEmpty()) {
389             throw new XMLParserExc("No attributes allowed");
390           }
391
392           currentBuilder = new DefaultProducerNodeBuilders.
393               ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
394           return new EmptySectionHandler();
395         }
396         else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
397                  builderLibrary.hasBuilderForName( (aTag))) {
398
399           if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
400             currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
401           else
402             currentBuilder = builderLibrary.constructBuilder(aTag);
403
404           currentBuilder.setAttributes(anAttributes);
405           if (currentBuilder.getAvailableSubNodes().isEmpty()) {
406             return new EmptySectionHandler();
407           }
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();
414           else {
415             return new ProducerNodeSectionHandler(scriptedNodeName,
416                 allowedNodeParameterReferences);
417           }
418         }
419         else
420           throw new XMLParserExc("Unknown producer node tag: '" + aTag + "'");
421       }
422       catch (Throwable t) {
423         throw new XMLParserFailure(t);
424       }
425     }
426
427     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc  {
428       try {
429         if (aHandler instanceof ProducerNodeSectionHandler) {
430           currentBuilder.setSubNode(
431                 (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
432                 ((ProducerNodeSectionHandler) aHandler).getProducerNode());
433         }
434         else if (aHandler instanceof MultiProducerNodeSectionHandler) {
435           Iterator i;
436           Map nodeParameters;
437           Map.Entry entry;
438
439           nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
440               getNodeParameters();
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());
446           }
447         }
448         else if (aHandler instanceof EmptySectionHandler) {
449           // deliberately empty: nothing expected, so nothing to process
450         }
451         else {
452           throw new XMLParserExc(
453               "Internal error: unknown section handler '" +
454               aHandler.getClass().getName() + "'");
455         }
456
457         producerNode.addSubNode(currentBuilder.constructNode());
458         currentBuilder = null;
459       }
460       catch (Throwable t) {
461         throw new XMLParserFailure(t);
462       }
463     }
464
465     public ProducerNode getProducerNode() {
466       if (producerNode.getNrSubNodes()==1) {
467         return producerNode.getSubNode(0);
468       }
469                         return producerNode;
470     }
471
472     public void finishSection() {
473     }
474   }
475
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;
482     private String name;
483
484     public NodeDefinitionSectionHandler(String aName) {
485       body = null;
486       nodeParameters = null;
487       stringParameters = null;
488       integerParameters = null;
489       name = aName;
490     }
491
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'" );
496         }
497         if (nodeParameters!=null) {
498           throw new XMLParserExc( "Parameters have already been declared" );
499         }
500         if (body!=null) {
501           throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
502         }
503
504         return new NodeDefinitionParametersSectionHandler();
505       }
506       else if (aTag.equals("definition")) {
507         if (nodeParameters==null)
508           throw new XMLParserExc( "Parameters should come before definition in nodedefinition '" + name +"'"  );
509
510         return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
511       }
512       else throw new XMLParserExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
513     }
514
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();
520       }
521       else if (aHandler instanceof ProducerNodeSectionHandler) {
522         body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
523       }
524     }
525
526     public void finishSection() throws XMLParserExc {
527       Iterator i;
528       if (body == null)
529         throw new XMLParserExc( "Definition missing" );
530
531       nodeDefinition = new ScriptedProducerNodeDefinition(name);
532
533       nodeDefinition.setBody(body);
534
535       i = nodeParameters.keySet().iterator();
536       while (i.hasNext()) {
537         nodeDefinition.addNodeParameter((String) i.next());
538       }
539
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());
544       }
545
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());
550       }
551     }
552
553     public ScriptedProducerNodeDefinition getDefinition() {
554       return nodeDefinition;
555     }
556   }
557
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 = { };
563
564   public class NodeDefinitionParametersSectionHandler extends mir.util.xml.AbstractSectionHandler {
565     private Map nodeParameters;
566     private Map stringParameters;
567     private Map integerParameters;
568
569     public NodeDefinitionParametersSectionHandler() {
570       nodeParameters = new HashMap();
571       stringParameters = new HashMap();
572       integerParameters = new HashMap();
573     }
574
575     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
576       String parameterName;
577       String defaultValue;
578
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);
585
586         if (nodeParameters.containsKey(parameterName))
587           throw new XMLParserExc("Duplicate parameter name: '" +
588                                            parameterName + "'");
589
590         mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
591
592         nodeParameters.put(parameterName, parameterName);
593
594         return new EmptySectionHandler();
595       }
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);
602
603         if (stringParameters.containsKey(parameterName) ||
604             integerParameters.containsKey(parameterName))
605           throw new XMLParserExc("Duplicate parameter name: '" +
606                                            parameterName + "'");
607
608         mir.util.xml.XMLReaderTool.checkValidIdentifier(parameterName);
609
610         defaultValue = (String) anAttributes.get(
611             NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
612
613         if (aTag.equals("string"))
614           stringParameters.put(parameterName, defaultValue);
615         else
616           integerParameters.put(parameterName, defaultValue);
617
618         return new EmptySectionHandler();
619       }
620       else
621         throw new XMLParserExc(
622             "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
623     }
624
625     public void endElement(mir.util.xml.SectionHandler aHandler) {
626     }
627
628     public void finishSection() {
629     }
630
631     public Map getNodeParameters() {
632       return nodeParameters;
633     }
634
635     public Map getStringParameters() {
636       return stringParameters;
637     }
638
639     public Map getIntegerParameters() {
640       return integerParameters;
641     }
642   }
643 }