- experimental opensessions
[mir.git] / source / mir / producer / reader / ProducerConfigReader.java
index 407eca6..f71c5b1 100755 (executable)
 
 package  mir.producer.reader;
 
-import java.io.*;
-import java.util.*;
-import java.lang.System;
-import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.*;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import mir.util.*;
-import mir.config.exceptions.*;
-import mir.producer.*;
-
-//import mir.producer.exceptions.*;
-import mir.misc.Location;
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import mir.producer.CompositeProducerNode;
+import mir.producer.ProducerFactory;
+import mir.producer.ProducerNode;
+import mir.producer.SimpleProducerVerb;
+import mir.util.XMLReader;
+import mir.util.XMLReaderTool;
 
 public class ProducerConfigReader {
   private ProducerNodeBuilderLibrary builderLibrary;
@@ -55,221 +55,50 @@ public class ProducerConfigReader {
     super();
   };
 
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, Map aProducerFactories) throws ConfigFailure {
+  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
     parseFile(aFileName, aBuilderLibrary, aProducerFactories, new Vector());
-
   }
 
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, Map aProducerFactories, List aUsedFiles) throws ConfigFailure {
+  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories, List aUsedFiles) throws ProducerConfigFailure {
     try {
+      XMLReader reader = new XMLReader();
+      aUsedFiles.add(new File(aFileName));
+
       builderLibrary = aBuilderLibrary;
       scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
 
-      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-
-      parserFactory.setNamespaceAware(false);
-      parserFactory.setValidating(true);
+      reader.parseFile(aFileName, new RootSectionHandler(aProducerFactories));
 
-      ProducerConfigHandler handler = new ProducerConfigHandler(parserFactory, aProducerFactories, aUsedFiles);
-
-      handler.includeFile(aFileName);
     }
     catch (Throwable e) {
-      if (e instanceof SAXParseException && ((SAXParseException) e).getException() instanceof ConfigFailure) {
-        throw (ConfigFailure) ((SAXParseException) e).getException();
-      }
-      else {
-        e.printStackTrace();
-        throw new ConfigFailure( e.getMessage() );
-      }
-    }
-  }
-
-  private class ProducerConfigHandler extends DefaultHandler {
-    private Locator locator;
-    private Stack includeFileStack;
-    private SAXParserFactory parserFactory;
-    private SectionsManager manager;
-    private List usedFiles;
-    private InputSource inputSource;
-
-    public ProducerConfigHandler(SAXParserFactory aParserFactory, Map aProducers, List aUsedFiles) {
-      super();
-
-      includeFileStack=new Stack();
-      parserFactory=aParserFactory;
-      includeFileStack = new Stack();
-      manager = new SectionsManager();
-      usedFiles = aUsedFiles;
-
-      manager.pushHandler(new RootSectionHandler(aProducers));
-   }
-
-    public String getLocatorDescription(Locator aLocator) {
-      return aLocator.getPublicId()+" ("+aLocator.getLineNumber()+")";
-    }
-
-    public void setDocumentLocator(Locator aLocator) {
-      locator=aLocator;
-    }
-
-    private void includeFile(String aFileName) throws ConfigFailure, SAXParseException, SAXException {
-      File file;
-      SAXParser parser;
-
-      try {
-        if (!includeFileStack.empty())
-          file = new File(new File((String) includeFileStack.peek()).getParent(), aFileName);
-        else
-          file = new File(aFileName);
-
-        System.err.println("about to include "+file.getCanonicalPath());
-
-        if (includeFileStack.contains(file.getCanonicalPath())) {
-          throw new ConfigFailure("recursive inclusion of file "+file.getCanonicalPath(), getLocatorDescription(locator));
-        }
-
-        usedFiles.add(file);
-
-        parser=parserFactory.newSAXParser();
-
-        inputSource = new InputSource(new FileInputStream(file));
-        inputSource.setPublicId(file.getCanonicalPath());
-
-        includeFileStack.push(file.getCanonicalPath());
-        try {
-          parser.parse(inputSource, this);
-        }
-        finally {
-          includeFileStack.pop();
-        }
-      }
-      catch (ParserConfigurationException e) {
-        throw new ConfigFailure("Internal exception while including \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));
-      }
-      catch (SAXParseException e) {
-        throw e;
-      }
-      catch (ConfigFailure e) {
-        throw e;
-      }
-      catch (FileNotFoundException e) {
-        throw new ConfigFailure("Include file \""+aFileName+"\" not found: "+e.getMessage(), e, getLocatorDescription(locator));
-      }
-      catch (IOException e) {
-        throw new ConfigFailure("unable to open include file \""+aFileName+"\": "+e.getMessage(), e, getLocatorDescription(locator));
+      if ((e instanceof XMLReader.XMLReaderExc) && ((XMLReader.XMLReaderExc) e).getHasLocation()) {
+        XMLReader.XMLReaderExc f = (XMLReader.XMLReaderExc) e;
+        throw new ProducerConfigFailure("'" + f.getMessage()+"' in " + f.getFilename()+"(line " + f.getLineNr()+", column " + f.getColumnNr() + ")", e);
       }
-    }
-
-    public void startElement(String aUri, String aTag, String aQualifiedName, Attributes anAttributes) throws SAXException {
-      Map attributesMap;
-      int i;
-
-      try {
-        if (aQualifiedName.equals("include")) {
-          String fileName=anAttributes.getValue("file");
-
-          if (fileName==null) {
-            throw new ConfigFailure("include has no file attribute", getLocatorDescription(locator));
-          }
-
-          includeFile(fileName);
-        }
-        else {
-          attributesMap = new HashMap();
-          for (i=0; i<anAttributes.getLength(); i++)
-            attributesMap.put(anAttributes.getQName(i), anAttributes.getValue(i));
-
-          manager.pushHandler( manager.currentHandler().startElement(aQualifiedName, attributesMap) );
-        }
-      }
-      catch (Exception e) {
-        e.printStackTrace(System.out);
-        throw new SAXException(e);
-      }
-    }
-
-    public void endElement(String aUri, String aTag, String aQualifiedName) throws SAXException {
-      try
-      {
-        if (!aQualifiedName.equals("include")) {
-          SectionHandler handler = manager.popHandler();
-
-          handler.finishSection();
-
-          if (!manager.isEmpty()) {
-            manager.currentHandler().endElement(handler);
-          }
-        }
-      }
-      catch (Exception e) {
-        e.printStackTrace(System.out);
-        throw new SAXException(e);
-      }
-    }
-
-    public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXParseException {
-      String text = new String(aBuffer, aStart, anEnd).trim();
-      if ( text.length() > 0) {
-        throw new SAXParseException("Text not allowed", locator, new ConfigFailure("text not allowed", getLocatorDescription(locator)));
-      }
-    }
-
-  }
-  public class SectionsManager {
-    Stack handlerStack;
-
-    public SectionsManager() {
-      handlerStack = new Stack();
-    }
-
-    public void pushHandler(SectionHandler aSectionHandler) {
-      handlerStack.push(aSectionHandler);
-    }
-
-    public SectionHandler popHandler() {
-      return (SectionHandler) handlerStack.pop();
-    }
-
-    public SectionHandler currentHandler() {
-      return (SectionHandler) handlerStack.peek();
-    }
-
-    public boolean isEmpty() {
-      return handlerStack.isEmpty();
+      throw new ProducerConfigFailure( e );
     }
   }
 
-  public abstract class SectionHandler {
-    public abstract SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc;
 
-    public abstract void endElement(SectionHandler aHandler) throws ProducerConfigExc;
-//    {
-//    }
+  public class RootSectionHandler extends XMLReader.AbstractSectionHandler {
+    private List producers;
 
-    public void finishSection() throws ProducerConfigExc {
-    }
-  }
-
-  public class RootSectionHandler extends SectionHandler {
-    private Map producers;
-
-    public RootSectionHandler(Map aProducers) {
+    public RootSectionHandler(List aProducers) {
       producers = aProducers;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (aTag.equals("producers")) {
         return new ProducersSectionHandler(producers);
       }
       else
-        throw new ProducerConfigExc ("Tag 'producers' expected, tag '"+aTag+"' found");
+        throw new XMLReader.XMLReaderExc("Tag 'producers' expected, tag '"+aTag+"' found");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(XMLReader.SectionHandler aHandler) {
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() {
     }
   }
 
@@ -282,75 +111,84 @@ public class ProducerConfigReader {
   private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };
   private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = {  };
 
-  public class ProducersSectionHandler extends SectionHandler {
-    private Map producers;
+  public class ProducersSectionHandler extends XMLReader.AbstractSectionHandler {
+    private List producers;
+    private Set producerNames;
     private String name;
 
-    public ProducersSectionHandler(Map aProducers) {
+    public ProducersSectionHandler(List aProducers) {
       producers = aProducers;
+      producerNames = new HashSet();
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (aTag.equals("producer")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_REQUIRED_ATTRIBUTES, PRODUCER_OPTIONAL_ATTRIBUTES);
+        XMLReaderTool.checkAttributes(anAttributes,
+                                      PRODUCER_REQUIRED_ATTRIBUTES,
+                                      PRODUCER_OPTIONAL_ATTRIBUTES);
 
         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
-        ReaderTool.checkValidIdentifier( name );
+        XMLReaderTool.checkValidIdentifier(name);
 
-        if (producers.containsKey(name))
-          throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
+        if (producerNames.contains(name))
+          throw new XMLReader.XMLReaderExc("Duplicate producer name: '" +
+                                           name + "'");
 
         name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
 
-        return new ProducerSectionHandler();
+        return new ProducerSectionHandler(name);
       }
       else if (aTag.equals("nodedefinition")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_REQUIRED_ATTRIBUTES, NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
+        XMLReaderTool.checkAttributes(anAttributes,
+                                      NODE_DEFINITION_REQUIRED_ATTRIBUTES,
+                                      NODE_DEFINITION_OPTIONAL_ATTRIBUTES);
 
         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
-        ReaderTool.checkValidIdentifier( name );
-
-//        if (producers.containsKey(name))
-//          throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
+        XMLReaderTool.checkValidIdentifier(name);
 
         name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
 
         return new NodeDefinitionSectionHandler(name);
       }
-
-      throw new ProducerConfigExc("Unexpected tag: "+aTag );
+      throw new XMLReader.XMLReaderExc("Unexpected tag: " + aTag);
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
       if (aHandler instanceof ProducerSectionHandler) {
-        producers.put(name, ((ProducerSectionHandler) aHandler).getProducerFactory());
+        producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());
+        producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());
       }
       else if (aHandler instanceof NodeDefinitionSectionHandler) {
         scriptedNodeBuilderLibrary.registerFactory(name,
             new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(
                 ((NodeDefinitionSectionHandler) aHandler).getDefinition()));
       }
-      else throw new ProducerConfigExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
+      else throw new XMLReader.XMLReaderExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() {
     }
   }
 
-  public class ProducerSectionHandler extends SectionHandler {
+  public class ProducerSectionHandler extends XMLReader.AbstractSectionHandler {
     private ProducerFactory producerFactory;
+    private String factoryName;
 
     private ProducerNode body;
-    private Map verbs;
+    private Map verbNodes;
+    private List verbs;
     private String defaultVerb;
 
-    public SectionHandler startElement(String aTag, Map anAttributes)  throws ProducerConfigExc {
+    public ProducerSectionHandler(String aName) {
+      factoryName = aName;
+    }
+
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (aTag.equals("verbs")) {
         if (verbs!=null)
-          throw new ProducerConfigExc("Verbs already processed");
+          throw new XMLReader.XMLReaderExc("Verbs already processed");
         if (body!=null)
-          throw new ProducerConfigExc("Verbs should come before body");
+          throw new XMLReader.XMLReaderExc("Verbs should come before body");
         else
           return new ProducerVerbsSectionHandler();
       }
@@ -358,31 +196,32 @@ public class ProducerConfigReader {
         if (body==null)
           return new ProducerNodeSectionHandler();
         else
-          throw new ProducerConfigExc("Body already processed");
+          throw new XMLReader.XMLReaderExc("Body already processed");
       }
-      throw new ProducerConfigExc("Unexpected tag: '"+aTag+"'");
+      throw new XMLReader.XMLReaderExc("Unexpected tag: '"+aTag+"'");
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
       if (aHandler instanceof ProducerNodeSectionHandler) {
         body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
       }
       else if (aHandler instanceof ProducerVerbsSectionHandler)
       {
         verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();
+        verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();
         defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();
       }
-      else throw new ProducerConfigExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
+      else throw new XMLReader.XMLReaderExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() throws XMLReader.XMLReaderExc {
       if (verbs==null)
-        throw new ProducerConfigExc("No verbs defined");
+        throw new XMLReader.XMLReaderExc("No verbs defined");
 
       if (body==null)
-        throw new ProducerConfigExc("No body defined");
+        throw new XMLReader.XMLReaderExc("No body defined");
 
-      producerFactory = new ScriptedProducerFactory(verbs, body, defaultVerb);
+      producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
     }
 
     public ProducerFactory getProducerFactory() {
@@ -391,44 +230,59 @@ public class ProducerConfigReader {
   }
 
   private final static String   PRODUCER_VERB_NAME_ATTRIBUTE = "name";
+  private final static String   PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";
   private final static String   PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";
   private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };
-  private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE };
+  private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
 
-  public class ProducerVerbsSectionHandler extends SectionHandler {
-    private Map verbs;
+  public class ProducerVerbsSectionHandler extends XMLReader.AbstractSectionHandler {
+    private Map verbNodes;
+    private List verbs;
     private String defaultVerb;
     private String currentVerb;
+    private String currentVerbDescription;
 
     public ProducerVerbsSectionHandler() {
-      verbs = new HashMap();
+      verbNodes = new HashMap();
+      verbs = new Vector();
       defaultVerb = null;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (aTag.equals("verb")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_VERB_REQUIRED_ATTRIBUTES, PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
-        currentVerb = (String) anAttributes.get( PRODUCER_VERB_NAME_ATTRIBUTE );
+        XMLReaderTool.checkAttributes(anAttributes,
+                                      PRODUCER_VERB_REQUIRED_ATTRIBUTES,
+                                      PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
+        currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);
 
-        ReaderTool.checkValidIdentifier( currentVerb );
+        XMLReaderTool.checkValidIdentifier(currentVerb);
 
-        if (verbs.containsKey(currentVerb))
-          throw new ProducerConfigExc( "Duplicate definition of verb '" + currentVerb + "'" );
+        if (verbNodes.containsKey(currentVerb))
+          throw new XMLReader.XMLReaderExc("Duplicate definition of verb '" +
+                                           currentVerb + "'");
 
         if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
-          if (defaultVerb!=null)
-            throw new ProducerConfigExc( "Default verb already declared" );
+          if (defaultVerb != null)
+            throw new XMLReader.XMLReaderExc("Default verb already declared");
 
           defaultVerb = currentVerb;
         }
 
+        if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))
+          currentVerbDescription = (String) anAttributes.get(
+              PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);
+        else
+          currentVerbDescription = "";
+
         return new ProducerNodeSectionHandler();
       }
-      else throw new ProducerConfigExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
+      else
+        throw new XMLReader.XMLReaderExc("Only 'verb' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
-      verbs.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
+    public void endElement(XMLReader.SectionHandler aHandler) {
+      verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
+      verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
     }
 
     public void finishSection() {
@@ -438,22 +292,28 @@ public class ProducerConfigReader {
       return defaultVerb;
     }
 
-    public Map getVerbs() {
+    public List getVerbs() {
       return verbs;
     }
+
+    public Map getVerbNodes() {
+      return verbNodes;
+    }
   }
 
-  public class EmptySectionHandler extends SectionHandler {
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      throw new ProducerConfigExc("No tags are allowed here");
+  public class EmptySectionHandler extends XMLReader.AbstractSectionHandler {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
+      throw new XMLReader.XMLReaderExc("No tags are allowed here");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(XMLReader.SectionHandler aHandler) {
     }
 
+    public void finishSection() {
+    }
   }
 
-  public class MultiProducerNodeSectionHandler extends SectionHandler {
+  public class MultiProducerNodeSectionHandler extends XMLReader.AbstractSectionHandler {
     private Map nodeParameters;
     private Set validNodeParameters;
     private String currentNodeParameter;
@@ -470,34 +330,37 @@ public class ProducerConfigReader {
       this("", new HashSet(), aValidNodeParameters);
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (!validNodeParameters.contains(aTag))
-        throw new ProducerConfigExc("Invalid node parameter: '" + aTag + "'");
+        throw new XMLReader.XMLReaderExc("Invalid node parameter: '" + aTag + "'");
       else if (nodeParameters.containsKey(aTag))
-        throw new ProducerConfigExc("Node parameter: '" + aTag + "' already specified");
+        throw new XMLReader.XMLReaderExc("Node parameter: '" + aTag + "' already specified");
       else if (anAttributes.size()>0)
-        throw new ProducerConfigExc("No parameters are allowed here");
+        throw new XMLReader.XMLReaderExc("No parameters are allowed here");
 
       currentNodeParameter = aTag;
 
       return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);
     }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc  {
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc  {
       if (aHandler instanceof ProducerNodeSectionHandler) {
         nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
       }
       else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
+        throw new XMLReader.XMLReaderExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
       }
     }
 
     public Map getNodeParameters() {
       return nodeParameters;
     }
+
+    public void finishSection() {
+    }
   }
 
-  public class ProducerNodeSectionHandler extends SectionHandler {
+  public class ProducerNodeSectionHandler extends XMLReader.AbstractSectionHandler {
     private CompositeProducerNode producerNode;
     private ProducerNodeBuilder currentBuilder;
     private String scriptedNodeName;
@@ -513,66 +376,85 @@ public class ProducerConfigReader {
       this("", new HashSet());
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (allowedNodeParameterReferences.contains((aTag))) {
-        if (!anAttributes.isEmpty()) {
-          throw new ProducerConfigExc( "No attributes allowed" );
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
+      try {
+        if (allowedNodeParameterReferences.contains( (aTag))) {
+          if (!anAttributes.isEmpty()) {
+            throw new XMLReader.XMLReaderExc("No attributes allowed");
+          }
+
+          currentBuilder = new DefaultProducerNodeBuilders.
+              ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
+          return new EmptySectionHandler();
         }
+        else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||
+                 builderLibrary.hasBuilderForName( (aTag))) {
 
-        currentBuilder = new DefaultProducerNodeBuilders.ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);
-//        producerNode.addSubNode(
-//        new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, aTag));
-        return new EmptySectionHandler();
-      }
-      else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) || builderLibrary.hasBuilderForName((aTag))) {
+          if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
+            currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
+          else
+            currentBuilder = builderLibrary.constructBuilder(aTag);
 
-        if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))
-          currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);
+          currentBuilder.setAttributes(anAttributes);
+          if (currentBuilder.getAvailableSubNodes().isEmpty()) {
+            return new EmptySectionHandler();
+          }
+          if (currentBuilder.getAvailableSubNodes().size() > 1)
+            return new MultiProducerNodeSectionHandler(scriptedNodeName,
+                allowedNodeParameterReferences,
+                currentBuilder.getAvailableSubNodes());
+          else if (currentBuilder.getAvailableSubNodes().size() < 1)
+            return new EmptySectionHandler();
+          else {
+            return new ProducerNodeSectionHandler(scriptedNodeName,
+                allowedNodeParameterReferences);
+          }
+        }
         else
-          currentBuilder = builderLibrary.constructBuilder(aTag);
+          throw new XMLReader.XMLReaderExc("Unknown producer node tag: '" +
+                                           aTag + "'");
+      }
+      catch (Throwable t) {
+        throw new XMLReader.XMLReaderFailure(t);
+      }
+    }
 
-        currentBuilder.setAttributes(anAttributes);
-        if (currentBuilder.getAvailableSubNodes().isEmpty())  {
-          return new EmptySectionHandler();
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc  {
+      try {
+        if (aHandler instanceof ProducerNodeSectionHandler) {
+          currentBuilder.setSubNode(
+                (String) (currentBuilder.getAvailableSubNodes().iterator().next()),
+                ((ProducerNodeSectionHandler) aHandler).getProducerNode());
+        }
+        else if (aHandler instanceof MultiProducerNodeSectionHandler) {
+          Iterator i;
+          Map nodeParameters;
+          Map.Entry entry;
+
+          nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).
+              getNodeParameters();
+          i = nodeParameters.entrySet().iterator();
+          while (i.hasNext()) {
+            entry = (Map.Entry) i.next();
+            currentBuilder.setSubNode( (String) entry.getKey(),
+                                      (ProducerNode) entry.getValue());
+          }
+        }
+        else if (aHandler instanceof EmptySectionHandler) {
+          // deliberately empty: nothing expected, so nothing to process
         }
-        if (currentBuilder.getAvailableSubNodes().size()>1)
-          return new MultiProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences, currentBuilder.getAvailableSubNodes());
-        else if (currentBuilder.getAvailableSubNodes().size()<1)
-          return new EmptySectionHandler();
         else {
-          return new ProducerNodeSectionHandler(scriptedNodeName, allowedNodeParameterReferences);
+          throw new XMLReader.XMLReaderExc(
+              "Internal error: unknown section handler '" +
+              aHandler.getClass().getName() + "'");
         }
-      }
-      else
-        throw new ProducerConfigExc("Unknown producer node tag: '" + aTag + "'");
-    }
 
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc  {
-      if (aHandler instanceof ProducerNodeSectionHandler) {
-        currentBuilder.setSubNode((String) (currentBuilder.getAvailableSubNodes().iterator().next()),
-                    ((ProducerNodeSectionHandler) aHandler).getProducerNode());
-      }
-      else if (aHandler instanceof MultiProducerNodeSectionHandler) {
-        Iterator i;
-        Map nodeParameters;
-        Map.Entry entry;
-
-        nodeParameters = ((MultiProducerNodeSectionHandler) aHandler).getNodeParameters();
-        i = nodeParameters.entrySet().iterator();
-        while (i.hasNext()) {
-          entry = (Map.Entry) i.next();
-          currentBuilder.setSubNode((String) entry.getKey(), (ProducerNode) entry.getValue());
-        }
-      }
-      else if (aHandler instanceof EmptySectionHandler) {
-        // deliberately empty: nothing expected, so nothing to process
+        producerNode.addSubNode(currentBuilder.constructNode());
+        currentBuilder = null;
       }
-      else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
+      catch (Throwable t) {
+        throw new XMLReader.XMLReaderFailure(t);
       }
-
-      producerNode.addSubNode(currentBuilder.constructNode());
-      currentBuilder = null;
     }
 
     public ProducerNode getProducerNode() {
@@ -583,12 +465,16 @@ public class ProducerConfigReader {
         return producerNode;
       }
     }
+
+    public void finishSection() {
+    }
   }
 
-  public class NodeDefinitionSectionHandler extends SectionHandler {
+  public class NodeDefinitionSectionHandler extends XMLReader.AbstractSectionHandler {
     private ScriptedProducerNodeDefinition nodeDefinition;
     private ProducerNode body;
     private Map stringParameters;
+    private Map integerParameters;
     private Map nodeParameters;
     private String name;
 
@@ -596,32 +482,37 @@ public class ProducerConfigReader {
       body = null;
       nodeParameters = null;
       stringParameters = null;
+      integerParameters = null;
       name = aName;
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       if (aTag.equals("parameters")) {
         if (!anAttributes.isEmpty()) {
-          throw new ProducerConfigExc( "No attributes allowed for tag 'parameters'" );
+          throw new XMLReader.XMLReaderExc( "No attributes allowed for tag 'parameters'" );
         }
         if (nodeParameters!=null) {
-          throw new ProducerConfigExc( "Parameters have already been declared" );
+          throw new XMLReader.XMLReaderExc( "Parameters have already been declared" );
         }
         if (body!=null) {
-          throw new ProducerConfigExc( "Parameters should come before definition" );
+          throw new XMLReader.XMLReaderExc( "Parameters should come before definition in nodedefinition '" + name +"'" );
         }
 
         return new NodeDefinitionParametersSectionHandler();
       }
       else if (aTag.equals("definition")) {
+        if (nodeParameters==null)
+          throw new XMLReader.XMLReaderExc( "Parameters should come before definition in nodedefinition '" + name +"'"  );
+
         return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
       }
-      else throw new ProducerConfigExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
+      else throw new XMLReader.XMLReaderExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(XMLReader.SectionHandler aHandler) {
       if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
         stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
+        integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
         nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
       }
       else if (aHandler instanceof ProducerNodeSectionHandler) {
@@ -629,10 +520,10 @@ public class ProducerConfigReader {
       }
     }
 
-    public void finishSection() throws ProducerConfigExc {
+    public void finishSection() throws XMLReader.XMLReaderExc {
       Iterator i;
       if (body == null)
-        throw new ProducerConfigExc( "Definition missing" );
+        throw new XMLReader.XMLReaderExc( "Definition missing" );
 
       nodeDefinition = new ScriptedProducerNodeDefinition(name);
 
@@ -646,7 +537,13 @@ public class ProducerConfigReader {
       i = stringParameters.entrySet().iterator();
       while (i.hasNext()) {
         Map.Entry entry = (Map.Entry) i.next();
-        nodeDefinition.addParameter((String) entry.getKey(), (String) entry.getValue());
+        nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());
+      }
+
+      i = integerParameters.entrySet().iterator();
+      while (i.hasNext()) {
+        Map.Entry entry = (Map.Entry) i.next();
+        nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());
       }
     }
 
@@ -661,52 +558,68 @@ public class ProducerConfigReader {
   private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };
   private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };
 
-  public class NodeDefinitionParametersSectionHandler extends SectionHandler {
+  public class NodeDefinitionParametersSectionHandler extends XMLReader.AbstractSectionHandler {
     private Map nodeParameters;
     private Map stringParameters;
+    private Map integerParameters;
 
     public NodeDefinitionParametersSectionHandler() {
       nodeParameters = new HashMap();
       stringParameters = new HashMap();
+      integerParameters = new HashMap();
     }
 
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
       String parameterName;
       String defaultValue;
 
       if (aTag.equals("node")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
-        parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
+        XMLReaderTool.checkAttributes(anAttributes,
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
+            NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);
+        parameterName = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
 
         if (nodeParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
+          throw new XMLReader.XMLReaderExc("Duplicate parameter name: '" +
+                                           parameterName + "'");
 
-        ReaderTool.checkValidIdentifier( parameterName );
+        XMLReaderTool.checkValidIdentifier(parameterName);
 
         nodeParameters.put(parameterName, parameterName);
 
         return new EmptySectionHandler();
       }
-      else if (aTag.equals("string")) {
-        ReaderTool.checkAttributes(anAttributes, NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES, NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
-        parameterName = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE );
+      else if (aTag.equals("string") || aTag.equals("integer")) {
+        XMLReaderTool.checkAttributes(anAttributes,
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,
+            NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);
+        parameterName = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);
 
-        if (stringParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
+        if (stringParameters.containsKey(parameterName) ||
+            integerParameters.containsKey(parameterName))
+          throw new XMLReader.XMLReaderExc("Duplicate parameter name: '" +
+                                           parameterName + "'");
 
-        ReaderTool.checkValidIdentifier( parameterName );
+        XMLReaderTool.checkValidIdentifier(parameterName);
 
-        defaultValue = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE );
+        defaultValue = (String) anAttributes.get(
+            NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);
 
-        stringParameters.put(parameterName, defaultValue);
+        if (aTag.equals("string"))
+          stringParameters.put(parameterName, defaultValue);
+        else
+          integerParameters.put(parameterName, defaultValue);
 
         return new EmptySectionHandler();
       }
-      else throw new ProducerConfigExc("Only 'string' and 'node' tags allowed here, '" + aTag + "' encountered.");
-
+      else
+        throw new XMLReader.XMLReaderExc(
+            "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
     }
 
-    public void endElement(SectionHandler aHandler) {
+    public void endElement(XMLReader.SectionHandler aHandler) {
     }
 
     public void finishSection() {
@@ -719,15 +632,9 @@ public class ProducerConfigReader {
     public Map getStringParameters() {
       return stringParameters;
     }
+
+    public Map getIntegerParameters() {
+      return integerParameters;
+    }
   }
 }
-
-
-/*
- /                 (expecting producers)
- producers/        (expecting nodedefinition, producer)
-   nodedefinition  (expecting parameters, definition)
-     parameters    (expecting parameter declarations)
-     definition    (expecting nodes, subnodes)
-*/
-