split the XML parser from the producer-config reader and improved XML parser error...
authorzapata <zapata>
Mon, 10 Feb 2003 16:50:17 +0000 (16:50 +0000)
committerzapata <zapata>
Mon, 10 Feb 2003 16:50:17 +0000 (16:50 +0000)
source/mir/producer/reader/DefaultProducerNodeBuilders.java
source/mir/producer/reader/ProducerConfigReader.java
source/mir/producer/reader/ProducerNodeBuilder.java
source/mir/producer/reader/ReaderTool.java [deleted file]
source/mir/util/XMLReader.java [new file with mode: 0755]
source/mir/util/XMLReaderTool.java [new file with mode: 0755]
source/mircoders/producer/reader/SupplementalProducerNodeBuilders.java

index 320d0dd..a551e28 100755 (executable)
@@ -57,6 +57,7 @@ import mir.producer.LoopProducerNode;
 import mir.producer.ProducerNode;
 import mir.producer.ResourceBundleProducerNode;
 import mir.producer.ScriptCallingProducerNode;
+import mir.util.*;
 
 public class DefaultProducerNodeBuilders {
 
@@ -137,8 +138,8 @@ public class DefaultProducerNodeBuilders {
       super(ASSIGNMENT_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
@@ -160,8 +161,8 @@ public class DefaultProducerNodeBuilders {
       super(ASSIGNMENT_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
@@ -200,13 +201,13 @@ public class DefaultProducerNodeBuilders {
       model = aModel;
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc  {
-      ReaderTool.checkAttributes(anAttributes, ENUMERATION_REQUIRED_ATTRIBUTES, ENUMERATION_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc  {
+      XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_REQUIRED_ATTRIBUTES, ENUMERATION_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE);
       definition = (String) anAttributes.get(ENUMERATION_DEFINITION_ATTRIBUTE);
-      selection = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
-      order = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
+      selection = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
+      order = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
       limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE);
       skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE);
     };
@@ -245,11 +246,11 @@ public class DefaultProducerNodeBuilders {
       super(LOOP_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc  {
-      ReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc  {
+      XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES);
 
       condition = (String) anAttributes.get(LOOP_CONDITION_ATTRIBUTE);
-      limit = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, "");
+      limit = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, "");
     };
 
     public ProducerNode constructNode() {
@@ -285,13 +286,13 @@ public class DefaultProducerNodeBuilders {
       model = aModel;
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE);
       definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE);
-      selection = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
-      order = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
+      selection = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
+      order = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
       limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE);
       skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE);
     };
@@ -329,10 +330,10 @@ public class DefaultProducerNodeBuilders {
       super(LOG_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
       String typeString;
 
-      ReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
+      XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
 
       message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE);
       if (anAttributes.containsKey(LOG_TYPE_ATTRIBUTE)) {
@@ -379,8 +380,8 @@ public class DefaultProducerNodeBuilders {
       super(RESOURCEBUNDLE_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(RESOURCEBUNDLE_KEY_ATTRIBUTE);
       bundle = (String) anAttributes.get(RESOURCEBUNDLE_BUNDLE_ATTRIBUTE);
@@ -408,8 +409,8 @@ public class DefaultProducerNodeBuilders {
       super(FILEDATESETTING_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES);
 
       fileNameKey = (String) anAttributes.get(FILEDATESETTING_FILE_ATTRIBUTE);
       dateKey = (String) anAttributes.get(FILEDATESETTING_DATE_ATTRIBUTE);
@@ -434,8 +435,8 @@ public class DefaultProducerNodeBuilders {
       super(FILEDELETING_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES);
 
       fileNameKey = (String) anAttributes.get(FILEDELETING_FILE_ATTRIBUTE);
     };
@@ -459,8 +460,8 @@ public class DefaultProducerNodeBuilders {
       super(SCRIPT_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES);
 
       command = (String) anAttributes.get(SCRIPT_COMMAND_ATTRIBUTE);
     };
@@ -491,8 +492,8 @@ public class DefaultProducerNodeBuilders {
       destinationBasePath = aDestinationBasePath;
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES);
 
       source = (String) anAttributes.get(DIRCOPY_SOURCE_ATTRIBUTE);
       destination = (String) anAttributes.get(DIRCOPY_DESTINATION_ATTRIBUTE);
@@ -540,12 +541,12 @@ public class DefaultProducerNodeBuilders {
       generatorLibrary = aGeneratorLibrary;
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
 
       generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE);
       destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE);
-      parameters = ReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
+      parameters = XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
     };
 
     public ProducerNode constructNode() {
@@ -608,19 +609,19 @@ public class DefaultProducerNodeBuilders {
       model = aModel;
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
 
-      batchDataKey = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
-      batchInfoKey = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
-      definition = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
-      selection = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
-      order = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
+      batchDataKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
+      batchInfoKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
+      definition = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
+      selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
+      order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
 
-      batchSize = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
-      minBatchSize = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
-      skip = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
-      process = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
+      batchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
+      minBatchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
+      skip = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
+      process = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
     };
 
     public ProducerNode constructNode() {
@@ -670,8 +671,8 @@ public class DefaultProducerNodeBuilders {
       super(IF_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
 
       condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE );
     };
@@ -742,8 +743,8 @@ public class DefaultProducerNodeBuilders {
       return definition.getNodeParameters();
     };
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
 
       Iterator i = anAttributes.entrySet().iterator();
       while (i.hasNext()) {
index 8ad2acf..f3683d4 100755 (executable)
-/*
- * Copyright (C) 2001, 2002  The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with the com.oreilly.servlet library, any library
- * licensed under the Apache Software License, The Sun (tm) Java Advanced
- * Imaging library (JAI), The Sun JIMI library (or with modified versions of
- * the above that use the same license as the above), and distribute linked
- * combinations including the two.  You must obey the GNU General Public
- * License in all respects for all of the code used other than the above
- * mentioned libraries.  If you modify this file, you may extend this exception
- * to your version of the file, but you are not obligated to do so.  If you do
- * not wish to do so, delete this exception statement from your version.
- */
-
-package  mir.producer.reader;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-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.Stack;
-import java.util.Vector;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import mir.producer.CompositeProducerNode;
-import mir.producer.ProducerFactory;
-import mir.producer.ProducerNode;
-import mir.producer.SimpleProducerVerb;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.helpers.DefaultHandler;
-
-public class ProducerConfigReader {
-  private ProducerNodeBuilderLibrary builderLibrary;
-  private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;
-
-  public ProducerConfigReader() {
-    super();
-  };
-
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {
-    parseFile(aFileName, aBuilderLibrary, aProducerFactories, new Vector());
-  }
-
-  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories, List aUsedFiles) throws ProducerConfigFailure {
-    try {
-      builderLibrary = aBuilderLibrary;
-      scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();
-
-      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-
-      parserFactory.setNamespaceAware(false);
-      parserFactory.setValidating(true);
-
-      ProducerConfigHandler handler = new ProducerConfigHandler(parserFactory, aProducerFactories, aUsedFiles);
-
-      handler.includeFile(aFileName);
-    }
-    catch (Throwable e) {
-      if (e instanceof SAXParseException && ((SAXParseException) e).getException() instanceof ProducerConfigFailure) {
-        throw (ProducerConfigFailure) ((SAXParseException) e).getException();
-      }
-      else {
-        throw new ProducerConfigFailure( e );
-      }
-    }
-  }
-
-  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, List 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 ProducerConfigExc, ProducerConfigFailure, 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 ProducerConfigExc("recursive inclusion of file "+file.getCanonicalPath());
-        }
-
-        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 ProducerConfigExc("Internal exception while including \""+aFileName+"\": "+e.getMessage());
-      }
-      catch (SAXParseException e) {
-        throw e;
-      }
-      catch (ProducerConfigFailure e) {
-        throw e;
-      }
-      catch (FileNotFoundException e) {
-        throw new ProducerConfigExc("Include file \""+aFileName+"\" not found: "+e.getMessage());
-      }
-      catch (IOException e) {
-        throw new ProducerConfigExc("unable to open include file \""+aFileName+"\": "+e.getMessage());
-      }
-    }
-
-    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 ProducerConfigExc("include has no file attribute");
-          }
-
-          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 (ProducerConfigExc e) {
-        throw new SAXParseException(e.getMessage(), locator, new ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: "+e.getMessage()));
-      }
-      catch (Exception e) {
-        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 (ProducerConfigExc e) {
-        throw new SAXParseException(e.getMessage(), locator, new ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: "+e.getMessage()));
-      }
-      catch (Exception e) {
-        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 ProducerConfigExc("Config error at ["+getLocatorDescription(locator)+"]: Text not allowed"));
-      }
-    }
-
-  }
-  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();
-    }
-  }
-
-  public abstract class SectionHandler {
-    public abstract SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc;
-
-    public abstract void endElement(SectionHandler aHandler) throws ProducerConfigExc;
-//    {
-//    }
-
-    public void finishSection() throws ProducerConfigExc {
-    }
-  }
-
-  public class RootSectionHandler extends SectionHandler {
-    private List producers;
-
-    public RootSectionHandler(List aProducers) {
-      producers = aProducers;
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (aTag.equals("producers")) {
-        return new ProducersSectionHandler(producers);
-      }
-      else
-        throw new ProducerConfigExc ("Tag 'producers' expected, tag '"+aTag+"' found");
-    }
-
-    public void endElement(SectionHandler aHandler) {
-    }
-
-    public void finishSection() throws ProducerConfigExc {
-    }
-  }
-
-
-  private final static String   PRODUCER_NAME_ATTRIBUTE = "name";
-  private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };
-  private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };
-
-  private final static String   NODE_DEFINITION_NAME_ATTRIBUTE = "name";
-  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 List producers;
-    private Set producerNames;
-    private String name;
-
-    public ProducersSectionHandler(List aProducers) {
-      producers = aProducers;
-      producerNames = new HashSet();
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-
-      if (aTag.equals("producer")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_REQUIRED_ATTRIBUTES, PRODUCER_OPTIONAL_ATTRIBUTES);
-
-        name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
-        ReaderTool.checkValidIdentifier( name );
-
-        if (producerNames.contains(name))
-          throw new ProducerConfigExc("Duplicate producer name: '" + name + "'");
-
-        name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);
-
-        return new ProducerSectionHandler(name);
-      }
-      else if (aTag.equals("nodedefinition")) {
-        ReaderTool.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 + "'");
-
-        name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);
-
-        return new NodeDefinitionSectionHandler(name);
-      }
-
-      throw new ProducerConfigExc("Unexpected tag: "+aTag );
-    }
-
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
-      if (aHandler instanceof ProducerSectionHandler) {
-        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());
-    }
-
-    public void finishSection() throws ProducerConfigExc {
-    }
-  }
-
-  public class ProducerSectionHandler extends SectionHandler {
-    private ProducerFactory producerFactory;
-    private String factoryName;
-
-    private ProducerNode body;
-    private Map verbNodes;
-    private List verbs;
-    private String defaultVerb;
-
-    public ProducerSectionHandler(String aName) {
-      factoryName = aName;
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes)  throws ProducerConfigExc {
-      if (aTag.equals("verbs")) {
-        if (verbs!=null)
-          throw new ProducerConfigExc("Verbs already processed");
-        if (body!=null)
-          throw new ProducerConfigExc("Verbs should come before body");
-        else
-          return new ProducerVerbsSectionHandler();
-      }
-      else if (aTag.equals("body")) {
-        if (body==null)
-          return new ProducerNodeSectionHandler();
-        else
-          throw new ProducerConfigExc("Body already processed");
-      }
-      throw new ProducerConfigExc("Unexpected tag: '"+aTag+"'");
-    }
-
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc {
-      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());
-    }
-
-    public void finishSection() throws ProducerConfigExc {
-      if (verbs==null)
-        throw new ProducerConfigExc("No verbs defined");
-
-      if (body==null)
-        throw new ProducerConfigExc("No body defined");
-
-      producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);
-    }
-
-    public ProducerFactory getProducerFactory() {
-      return producerFactory;
-    }
-  }
-
-  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, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };
-
-  public class ProducerVerbsSectionHandler extends SectionHandler {
-    private Map verbNodes;
-    private List verbs;
-    private String defaultVerb;
-    private String currentVerb;
-    private String currentVerbDescription;
-
-    public ProducerVerbsSectionHandler() {
-      verbNodes = new HashMap();
-      verbs = new Vector();
-      defaultVerb = null;
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (aTag.equals("verb")) {
-        ReaderTool.checkAttributes(anAttributes, PRODUCER_VERB_REQUIRED_ATTRIBUTES, PRODUCER_VERB_OPTIONAL_ATTRIBUTES);
-        currentVerb = (String) anAttributes.get( PRODUCER_VERB_NAME_ATTRIBUTE );
-
-        ReaderTool.checkValidIdentifier( currentVerb );
-
-        if (verbNodes.containsKey(currentVerb))
-          throw new ProducerConfigExc( "Duplicate definition of verb '" + currentVerb + "'" );
-
-        if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {
-          if (defaultVerb!=null)
-            throw new ProducerConfigExc( "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.");
-    }
-
-    public void endElement(SectionHandler aHandler) {
-      verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
-      verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));
-    }
-
-    public void finishSection() {
-    }
-
-    public String getDefaultVerb() {
-      return defaultVerb;
-    }
-
-    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 void endElement(SectionHandler aHandler) {
-    }
-
-  }
-
-  public class MultiProducerNodeSectionHandler extends SectionHandler {
-    private Map nodeParameters;
-    private Set validNodeParameters;
-    private String currentNodeParameter;
-    private String scriptedNodeName;
-    private Set allowedNodeParameterReferences;
-
-    public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {
-      allowedNodeParameterReferences = anAllowedNodeParameterReferences;
-      scriptedNodeName = aScriptedNodeName;
-      validNodeParameters = aValidNodeParameters;
-      nodeParameters = new HashMap();
-    }
-    public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {
-      this("", new HashSet(), aValidNodeParameters);
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (!validNodeParameters.contains(aTag))
-        throw new ProducerConfigExc("Invalid node parameter: '" + aTag + "'");
-      else if (nodeParameters.containsKey(aTag))
-        throw new ProducerConfigExc("Node parameter: '" + aTag + "' already specified");
-      else if (anAttributes.size()>0)
-        throw new ProducerConfigExc("No parameters are allowed here");
-
-      currentNodeParameter = aTag;
-
-      return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);
-    }
-
-    public void endElement(SectionHandler aHandler) throws ProducerConfigExc  {
-      if (aHandler instanceof ProducerNodeSectionHandler) {
-        nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());
-      }
-      else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
-      }
-    }
-
-    public Map getNodeParameters() {
-      return nodeParameters;
-    }
-  }
-
-  public class ProducerNodeSectionHandler extends SectionHandler {
-    private CompositeProducerNode producerNode;
-    private ProducerNodeBuilder currentBuilder;
-    private String scriptedNodeName;
-    private Set allowedNodeParameterReferences;
-
-    public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {
-      producerNode = new CompositeProducerNode();
-      scriptedNodeName = aScriptedNodeName;
-      allowedNodeParameterReferences = anAllowedNodeParameterReferences;
-    }
-
-    public ProducerNodeSectionHandler() {
-      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" );
-        }
-
-        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);
-
-        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
-        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
-      }
-      else {
-        throw new ProducerConfigExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );
-      }
-
-      producerNode.addSubNode(currentBuilder.constructNode());
-      currentBuilder = null;
-    }
-
-    public ProducerNode getProducerNode() {
-      if (producerNode.getNrSubNodes()==1) {
-        return producerNode.getSubNode(0);
-      }
-      else {
-        return producerNode;
-      }
-    }
-  }
-
-  public class NodeDefinitionSectionHandler extends SectionHandler {
-    private ScriptedProducerNodeDefinition nodeDefinition;
-    private ProducerNode body;
-    private Map stringParameters;
-    private Map integerParameters;
-    private Map nodeParameters;
-    private String name;
-
-    public NodeDefinitionSectionHandler(String aName) {
-      body = null;
-      nodeParameters = null;
-      stringParameters = null;
-      integerParameters = null;
-      name = aName;
-    }
-
-    public SectionHandler startElement(String aTag, Map anAttributes) throws ProducerConfigExc {
-      if (aTag.equals("parameters")) {
-        if (!anAttributes.isEmpty()) {
-          throw new ProducerConfigExc( "No attributes allowed for tag 'parameters'" );
-        }
-        if (nodeParameters!=null) {
-          throw new ProducerConfigExc( "Parameters have already been declared" );
-        }
-        if (body!=null) {
-          throw new ProducerConfigExc( "Parameters should come before definition" );
-        }
-
-        return new NodeDefinitionParametersSectionHandler();
-      }
-      else if (aTag.equals("definition")) {
-        return new ProducerNodeSectionHandler(name, nodeParameters.keySet());
-      }
-      else throw new ProducerConfigExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");
-    }
-
-    public void endElement(SectionHandler aHandler) {
-      if (aHandler instanceof NodeDefinitionParametersSectionHandler) {
-        stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();
-        integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();
-        nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();
-      }
-      else if (aHandler instanceof ProducerNodeSectionHandler) {
-        body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();
-      }
-    }
-
-    public void finishSection() throws ProducerConfigExc {
-      Iterator i;
-      if (body == null)
-        throw new ProducerConfigExc( "Definition missing" );
-
-      nodeDefinition = new ScriptedProducerNodeDefinition(name);
-
-      nodeDefinition.setBody(body);
-
-      i = nodeParameters.keySet().iterator();
-      while (i.hasNext()) {
-        nodeDefinition.addNodeParameter((String) i.next());
-      }
-
-      i = stringParameters.entrySet().iterator();
-      while (i.hasNext()) {
-        Map.Entry entry = (Map.Entry) i.next();
-        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());
-      }
-    }
-
-    public ScriptedProducerNodeDefinition getDefinition() {
-      return nodeDefinition;
-    }
-  }
-
-  private final static String   NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";
-  private final static String   NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";
-  private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };
-  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 {
-    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 {
-      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 );
-
-        if (nodeParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
-
-        ReaderTool.checkValidIdentifier( parameterName );
-
-        nodeParameters.put(parameterName, parameterName);
-
-        return new EmptySectionHandler();
-      }
-      else if (aTag.equals("string") || aTag.equals("integer")) {
-        ReaderTool.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) || integerParameters.containsKey(parameterName))
-          throw new ProducerConfigExc("Duplicate parameter name: '" + parameterName + "'");
-
-        ReaderTool.checkValidIdentifier( parameterName );
-
-        defaultValue = (String) anAttributes.get( NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE );
-
-        if (aTag.equals("string"))
-          stringParameters.put(parameterName, defaultValue);
-        else
-          integerParameters.put(parameterName, defaultValue);
-
-        return new EmptySectionHandler();
-      }
-      else throw new ProducerConfigExc("Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");
-
-    }
-
-    public void endElement(SectionHandler aHandler) {
-    }
-
-    public void finishSection() {
-    }
-
-    public Map getNodeParameters() {
-      return nodeParameters;
-    }
-
-    public Map getStringParameters() {
-      return stringParameters;
-    }
-
-    public Map getIntegerParameters() {
-      return integerParameters;
-    }
-  }
-}
+/*\r
+ * Copyright (C) 2001, 2002  The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with the com.oreilly.servlet library, any library\r
+ * licensed under the Apache Software License, The Sun (tm) Java Advanced\r
+ * Imaging library (JAI), The Sun JIMI library (or with modified versions of\r
+ * the above that use the same license as the above), and distribute linked\r
+ * combinations including the two.  You must obey the GNU General Public\r
+ * License in all respects for all of the code used other than the above\r
+ * mentioned libraries.  If you modify this file, you may extend this exception\r
+ * to your version of the file, but you are not obligated to do so.  If you do\r
+ * not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package  mir.producer.reader;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+import java.util.Vector;\r
+\r
+import mir.producer.CompositeProducerNode;\r
+import mir.producer.ProducerFactory;\r
+import mir.producer.ProducerNode;\r
+import mir.producer.SimpleProducerVerb;\r
+\r
+import mir.util.*;\r
+\r
+public class ProducerConfigReader {\r
+  private ProducerNodeBuilderLibrary builderLibrary;\r
+  private ProducerNodeBuilderLibrary scriptedNodeBuilderLibrary;\r
+\r
+  public ProducerConfigReader() {\r
+    super();\r
+  };\r
+\r
+  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure {\r
+    parseFile(aFileName, aBuilderLibrary, aProducerFactories, new Vector());\r
+  }\r
+\r
+  public void parseFile(String aFileName, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories, List aUsedFiles) throws ProducerConfigFailure {\r
+    try {\r
+      XMLReader reader = new XMLReader();\r
+\r
+      builderLibrary = aBuilderLibrary;\r
+      scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary();\r
+\r
+      reader.parseFile(aFileName, new RootSectionHandler(aProducerFactories), aUsedFiles);\r
+    }\r
+    catch (Throwable e) {\r
+      if ((e instanceof XMLReader.XMLReaderExc) && ((XMLReader.XMLReaderExc) e).getHasLocation()) {\r
+        XMLReader.XMLReaderExc f = (XMLReader.XMLReaderExc) e;\r
+        throw new ProducerConfigFailure("'" + f.getMessage()+"' in " + f.getFilename()+"(line " + f.getLineNr()+", column " + f.getColumnNr() + ")", e);\r
+      }\r
+      throw new ProducerConfigFailure( e );\r
+    }\r
+  }\r
+\r
+\r
+  public class RootSectionHandler implements XMLReader.SectionHandler {\r
+    private List producers;\r
+\r
+    public RootSectionHandler(List aProducers) {\r
+      producers = aProducers;\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (aTag.equals("producers")) {\r
+        return new ProducersSectionHandler(producers);\r
+      }\r
+      else\r
+        throw new XMLReader.XMLReaderExc("Tag 'producers' expected, tag '"+aTag+"' found");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) {\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+  }\r
+\r
+\r
+  private final static String   PRODUCER_NAME_ATTRIBUTE = "name";\r
+  private final static String[] PRODUCER_REQUIRED_ATTRIBUTES = { PRODUCER_NAME_ATTRIBUTE };\r
+  private final static String[] PRODUCER_OPTIONAL_ATTRIBUTES = { };\r
+\r
+  private final static String   NODE_DEFINITION_NAME_ATTRIBUTE = "name";\r
+  private final static String[] NODE_DEFINITION_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_NAME_ATTRIBUTE };\r
+  private final static String[] NODE_DEFINITION_OPTIONAL_ATTRIBUTES = {  };\r
+\r
+  public class ProducersSectionHandler implements XMLReader.SectionHandler {\r
+    private List producers;\r
+    private Set producerNames;\r
+    private String name;\r
+\r
+    public ProducersSectionHandler(List aProducers) {\r
+      producers = aProducers;\r
+      producerNames = new HashSet();\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (aTag.equals("producer")) {\r
+        XMLReaderTool.checkAttributes(anAttributes,\r
+                                      PRODUCER_REQUIRED_ATTRIBUTES,\r
+                                      PRODUCER_OPTIONAL_ATTRIBUTES);\r
+\r
+        name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);\r
+        XMLReaderTool.checkValidIdentifier(name);\r
+\r
+        if (producerNames.contains(name))\r
+          throw new XMLReader.XMLReaderExc("Duplicate producer name: '" +\r
+                                           name + "'");\r
+\r
+        name = (String) anAttributes.get(PRODUCER_NAME_ATTRIBUTE);\r
+\r
+        return new ProducerSectionHandler(name);\r
+      }\r
+      else if (aTag.equals("nodedefinition")) {\r
+        XMLReaderTool.checkAttributes(anAttributes,\r
+                                      NODE_DEFINITION_REQUIRED_ATTRIBUTES,\r
+                                      NODE_DEFINITION_OPTIONAL_ATTRIBUTES);\r
+\r
+        name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);\r
+        XMLReaderTool.checkValidIdentifier(name);\r
+\r
+        name = (String) anAttributes.get(NODE_DEFINITION_NAME_ATTRIBUTE);\r
+\r
+        return new NodeDefinitionSectionHandler(name);\r
+      }\r
+      throw new XMLReader.XMLReaderExc("Unexpected tag: " + aTag);\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {\r
+      if (aHandler instanceof ProducerSectionHandler) {\r
+        producers.add(((ProducerSectionHandler) aHandler).getProducerFactory());\r
+        producerNames.add(((ProducerSectionHandler) aHandler).getProducerFactory().getName());\r
+      }\r
+      else if (aHandler instanceof NodeDefinitionSectionHandler) {\r
+        scriptedNodeBuilderLibrary.registerFactory(name,\r
+            new DefaultProducerNodeBuilders.ScriptedProducerNodeBuilder.factory(\r
+                ((NodeDefinitionSectionHandler) aHandler).getDefinition()));\r
+      }\r
+      else throw new XMLReader.XMLReaderExc("ProducersSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+  }\r
+\r
+  public class ProducerSectionHandler implements XMLReader.SectionHandler {\r
+    private ProducerFactory producerFactory;\r
+    private String factoryName;\r
+\r
+    private ProducerNode body;\r
+    private Map verbNodes;\r
+    private List verbs;\r
+    private String defaultVerb;\r
+\r
+    public ProducerSectionHandler(String aName) {\r
+      factoryName = aName;\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (aTag.equals("verbs")) {\r
+        if (verbs!=null)\r
+          throw new XMLReader.XMLReaderExc("Verbs already processed");\r
+        if (body!=null)\r
+          throw new XMLReader.XMLReaderExc("Verbs should come before body");\r
+        else\r
+          return new ProducerVerbsSectionHandler();\r
+      }\r
+      else if (aTag.equals("body")) {\r
+        if (body==null)\r
+          return new ProducerNodeSectionHandler();\r
+        else\r
+          throw new XMLReader.XMLReaderExc("Body already processed");\r
+      }\r
+      throw new XMLReader.XMLReaderExc("Unexpected tag: '"+aTag+"'");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {\r
+      if (aHandler instanceof ProducerNodeSectionHandler) {\r
+        body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();\r
+      }\r
+      else if (aHandler instanceof ProducerVerbsSectionHandler)\r
+      {\r
+        verbs = ((ProducerVerbsSectionHandler) aHandler).getVerbs();\r
+        verbNodes = ((ProducerVerbsSectionHandler) aHandler).getVerbNodes();\r
+        defaultVerb = ((ProducerVerbsSectionHandler) aHandler).getDefaultVerb();\r
+      }\r
+      else throw new XMLReader.XMLReaderExc("ProducerSectionHandler.endElement Internal error: Unexpected handler: " + aHandler.getClass().getName());\r
+    }\r
+\r
+    public void finishSection() throws XMLReader.XMLReaderExc {\r
+      if (verbs==null)\r
+        throw new XMLReader.XMLReaderExc("No verbs defined");\r
+\r
+      if (body==null)\r
+        throw new XMLReader.XMLReaderExc("No body defined");\r
+\r
+      producerFactory = new ScriptedProducerFactory(factoryName, verbs, verbNodes, body, defaultVerb);\r
+    }\r
+\r
+    public ProducerFactory getProducerFactory() {\r
+      return producerFactory;\r
+    }\r
+  }\r
+\r
+  private final static String   PRODUCER_VERB_NAME_ATTRIBUTE = "name";\r
+  private final static String   PRODUCER_VERB_DESCRIPTION_ATTRIBUTE = "description";\r
+  private final static String   PRODUCER_VERB_DEFAULT_ATTRIBUTE = "default";\r
+  private final static String[] PRODUCER_VERB_REQUIRED_ATTRIBUTES = { PRODUCER_VERB_NAME_ATTRIBUTE };\r
+  private final static String[] PRODUCER_VERB_OPTIONAL_ATTRIBUTES = { PRODUCER_VERB_DEFAULT_ATTRIBUTE, PRODUCER_VERB_DESCRIPTION_ATTRIBUTE };\r
+\r
+  public class ProducerVerbsSectionHandler implements XMLReader.SectionHandler {\r
+    private Map verbNodes;\r
+    private List verbs;\r
+    private String defaultVerb;\r
+    private String currentVerb;\r
+    private String currentVerbDescription;\r
+\r
+    public ProducerVerbsSectionHandler() {\r
+      verbNodes = new HashMap();\r
+      verbs = new Vector();\r
+      defaultVerb = null;\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (aTag.equals("verb")) {\r
+        XMLReaderTool.checkAttributes(anAttributes,\r
+                                      PRODUCER_VERB_REQUIRED_ATTRIBUTES,\r
+                                      PRODUCER_VERB_OPTIONAL_ATTRIBUTES);\r
+        currentVerb = (String) anAttributes.get(PRODUCER_VERB_NAME_ATTRIBUTE);\r
+\r
+        XMLReaderTool.checkValidIdentifier(currentVerb);\r
+\r
+        if (verbNodes.containsKey(currentVerb))\r
+          throw new XMLReader.XMLReaderExc("Duplicate definition of verb '" +\r
+                                           currentVerb + "'");\r
+\r
+        if (anAttributes.containsKey(PRODUCER_VERB_DEFAULT_ATTRIBUTE)) {\r
+          if (defaultVerb != null)\r
+            throw new XMLReader.XMLReaderExc("Default verb already declared");\r
+\r
+          defaultVerb = currentVerb;\r
+        }\r
+\r
+        if (anAttributes.containsKey(PRODUCER_VERB_DESCRIPTION_ATTRIBUTE))\r
+          currentVerbDescription = (String) anAttributes.get(\r
+              PRODUCER_VERB_DESCRIPTION_ATTRIBUTE);\r
+        else\r
+          currentVerbDescription = "";\r
+\r
+        return new ProducerNodeSectionHandler();\r
+      }\r
+      else\r
+        throw new XMLReader.XMLReaderExc("Only 'verb' tags allowed here, '" +\r
+                                         aTag + "' encountered.");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) {\r
+      verbNodes.put(currentVerb, ((ProducerNodeSectionHandler) aHandler).getProducerNode());\r
+      verbs.add(new SimpleProducerVerb(currentVerb, currentVerbDescription));\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+\r
+    public String getDefaultVerb() {\r
+      return defaultVerb;\r
+    }\r
+\r
+    public List getVerbs() {\r
+      return verbs;\r
+    }\r
+\r
+    public Map getVerbNodes() {\r
+      return verbNodes;\r
+    }\r
+  }\r
+\r
+  public class EmptySectionHandler implements XMLReader.SectionHandler {\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      throw new XMLReader.XMLReaderExc("No tags are allowed here");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) {\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+  }\r
+\r
+  public class MultiProducerNodeSectionHandler implements XMLReader.SectionHandler {\r
+    private Map nodeParameters;\r
+    private Set validNodeParameters;\r
+    private String currentNodeParameter;\r
+    private String scriptedNodeName;\r
+    private Set allowedNodeParameterReferences;\r
+\r
+    public MultiProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences, Set aValidNodeParameters) {\r
+      allowedNodeParameterReferences = anAllowedNodeParameterReferences;\r
+      scriptedNodeName = aScriptedNodeName;\r
+      validNodeParameters = aValidNodeParameters;\r
+      nodeParameters = new HashMap();\r
+    }\r
+    public MultiProducerNodeSectionHandler(Set aValidNodeParameters) {\r
+      this("", new HashSet(), aValidNodeParameters);\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (!validNodeParameters.contains(aTag))\r
+        throw new XMLReader.XMLReaderExc("Invalid node parameter: '" + aTag + "'");\r
+      else if (nodeParameters.containsKey(aTag))\r
+        throw new XMLReader.XMLReaderExc("Node parameter: '" + aTag + "' already specified");\r
+      else if (anAttributes.size()>0)\r
+        throw new XMLReader.XMLReaderExc("No parameters are allowed here");\r
+\r
+      currentNodeParameter = aTag;\r
+\r
+      return new ProducerNodeSectionHandler(scriptedNodeName, validNodeParameters);\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc  {\r
+      if (aHandler instanceof ProducerNodeSectionHandler) {\r
+        nodeParameters.put(currentNodeParameter, ((ProducerNodeSectionHandler) aHandler).getProducerNode());\r
+      }\r
+      else {\r
+        throw new XMLReader.XMLReaderExc("Internal error: unknown section handler '" + aHandler.getClass().getName() + "'" );\r
+      }\r
+    }\r
+\r
+    public Map getNodeParameters() {\r
+      return nodeParameters;\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+  }\r
+\r
+  public class ProducerNodeSectionHandler implements XMLReader.SectionHandler {\r
+    private CompositeProducerNode producerNode;\r
+    private ProducerNodeBuilder currentBuilder;\r
+    private String scriptedNodeName;\r
+    private Set allowedNodeParameterReferences;\r
+\r
+    public ProducerNodeSectionHandler(String aScriptedNodeName, Set anAllowedNodeParameterReferences) {\r
+      producerNode = new CompositeProducerNode();\r
+      scriptedNodeName = aScriptedNodeName;\r
+      allowedNodeParameterReferences = anAllowedNodeParameterReferences;\r
+    }\r
+\r
+    public ProducerNodeSectionHandler() {\r
+      this("", new HashSet());\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      try {\r
+        if (allowedNodeParameterReferences.contains( (aTag))) {\r
+          if (!anAttributes.isEmpty()) {\r
+            throw new XMLReader.XMLReaderExc("No attributes allowed");\r
+          }\r
+\r
+          currentBuilder = new DefaultProducerNodeBuilders.\r
+              ScriptedProducerParameterNodeBuilder(scriptedNodeName, aTag);\r
+          return new EmptySectionHandler();\r
+        }\r
+        else if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag) ||\r
+                 builderLibrary.hasBuilderForName( (aTag))) {\r
+\r
+          if (scriptedNodeBuilderLibrary.hasBuilderForName(aTag))\r
+            currentBuilder = scriptedNodeBuilderLibrary.constructBuilder(aTag);\r
+          else\r
+            currentBuilder = builderLibrary.constructBuilder(aTag);\r
+\r
+          currentBuilder.setAttributes(anAttributes);\r
+          if (currentBuilder.getAvailableSubNodes().isEmpty()) {\r
+            return new EmptySectionHandler();\r
+          }\r
+          if (currentBuilder.getAvailableSubNodes().size() > 1)\r
+            return new MultiProducerNodeSectionHandler(scriptedNodeName,\r
+                allowedNodeParameterReferences,\r
+                currentBuilder.getAvailableSubNodes());\r
+          else if (currentBuilder.getAvailableSubNodes().size() < 1)\r
+            return new EmptySectionHandler();\r
+          else {\r
+            return new ProducerNodeSectionHandler(scriptedNodeName,\r
+                allowedNodeParameterReferences);\r
+          }\r
+        }\r
+        else\r
+          throw new XMLReader.XMLReaderExc("Unknown producer node tag: '" +\r
+                                           aTag + "'");\r
+      }\r
+      catch (Throwable t) {\r
+        throw new XMLReader.XMLReaderFailure(t);\r
+      }\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc  {\r
+      try {\r
+        if (aHandler instanceof ProducerNodeSectionHandler) {\r
+          currentBuilder.setSubNode(\r
+                (String) (currentBuilder.getAvailableSubNodes().iterator().next()),\r
+                ((ProducerNodeSectionHandler) aHandler).getProducerNode());\r
+        }\r
+        else if (aHandler instanceof MultiProducerNodeSectionHandler) {\r
+          Iterator i;\r
+          Map nodeParameters;\r
+          Map.Entry entry;\r
+\r
+          nodeParameters = ( (MultiProducerNodeSectionHandler) aHandler).\r
+              getNodeParameters();\r
+          i = nodeParameters.entrySet().iterator();\r
+          while (i.hasNext()) {\r
+            entry = (Map.Entry) i.next();\r
+            currentBuilder.setSubNode( (String) entry.getKey(),\r
+                                      (ProducerNode) entry.getValue());\r
+          }\r
+        }\r
+        else if (aHandler instanceof EmptySectionHandler) {\r
+          // deliberately empty: nothing expected, so nothing to process\r
+        }\r
+        else {\r
+          throw new XMLReader.XMLReaderExc(\r
+              "Internal error: unknown section handler '" +\r
+              aHandler.getClass().getName() + "'");\r
+        }\r
+\r
+        producerNode.addSubNode(currentBuilder.constructNode());\r
+        currentBuilder = null;\r
+      }\r
+      catch (Throwable t) {\r
+        throw new XMLReader.XMLReaderFailure(t);\r
+      }\r
+    }\r
+\r
+    public ProducerNode getProducerNode() {\r
+      if (producerNode.getNrSubNodes()==1) {\r
+        return producerNode.getSubNode(0);\r
+      }\r
+      else {\r
+        return producerNode;\r
+      }\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+  }\r
+\r
+  public class NodeDefinitionSectionHandler implements XMLReader.SectionHandler {\r
+    private ScriptedProducerNodeDefinition nodeDefinition;\r
+    private ProducerNode body;\r
+    private Map stringParameters;\r
+    private Map integerParameters;\r
+    private Map nodeParameters;\r
+    private String name;\r
+\r
+    public NodeDefinitionSectionHandler(String aName) {\r
+      body = null;\r
+      nodeParameters = null;\r
+      stringParameters = null;\r
+      integerParameters = null;\r
+      name = aName;\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      if (aTag.equals("parameters")) {\r
+        if (!anAttributes.isEmpty()) {\r
+          throw new XMLReader.XMLReaderExc( "No attributes allowed for tag 'parameters'" );\r
+        }\r
+        if (nodeParameters!=null) {\r
+          throw new XMLReader.XMLReaderExc( "Parameters have already been declared" );\r
+        }\r
+        if (body!=null) {\r
+          throw new XMLReader.XMLReaderExc( "Parameters should come before definition in nodedefinition '" + name +"'" );\r
+        }\r
+\r
+        return new NodeDefinitionParametersSectionHandler();\r
+      }\r
+      else if (aTag.equals("definition")) {\r
+        if (nodeParameters==null)\r
+          throw new XMLReader.XMLReaderExc( "Parameters should come before definition in nodedefinition '" + name +"'"  );\r
+\r
+        return new ProducerNodeSectionHandler(name, nodeParameters.keySet());\r
+      }\r
+      else throw new XMLReader.XMLReaderExc("Only 'definition' or 'parameters' tags allowed here, '" + aTag + "' encountered.");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) {\r
+      if (aHandler instanceof NodeDefinitionParametersSectionHandler) {\r
+        stringParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getStringParameters();\r
+        integerParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getIntegerParameters();\r
+        nodeParameters = ((NodeDefinitionParametersSectionHandler) aHandler).getNodeParameters();\r
+      }\r
+      else if (aHandler instanceof ProducerNodeSectionHandler) {\r
+        body = ((ProducerNodeSectionHandler) aHandler).getProducerNode();\r
+      }\r
+    }\r
+\r
+    public void finishSection() throws XMLReader.XMLReaderExc {\r
+      Iterator i;\r
+      if (body == null)\r
+        throw new XMLReader.XMLReaderExc( "Definition missing" );\r
+\r
+      nodeDefinition = new ScriptedProducerNodeDefinition(name);\r
+\r
+      nodeDefinition.setBody(body);\r
+\r
+      i = nodeParameters.keySet().iterator();\r
+      while (i.hasNext()) {\r
+        nodeDefinition.addNodeParameter((String) i.next());\r
+      }\r
+\r
+      i = stringParameters.entrySet().iterator();\r
+      while (i.hasNext()) {\r
+        Map.Entry entry = (Map.Entry) i.next();\r
+        nodeDefinition.addStringParameter((String) entry.getKey(), (String) entry.getValue());\r
+      }\r
+\r
+      i = integerParameters.entrySet().iterator();\r
+      while (i.hasNext()) {\r
+        Map.Entry entry = (Map.Entry) i.next();\r
+        nodeDefinition.addIntegerParameter((String) entry.getKey(), (String) entry.getValue());\r
+      }\r
+    }\r
+\r
+    public ScriptedProducerNodeDefinition getDefinition() {\r
+      return nodeDefinition;\r
+    }\r
+  }\r
+\r
+  private final static String   NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE = "name";\r
+  private final static String   NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE = "defaultvalue";\r
+  private final static String[] NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE };\r
+  private final static String[] NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES = { NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE };\r
+  private final static String[] NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES = { };\r
+\r
+  public class NodeDefinitionParametersSectionHandler implements XMLReader.SectionHandler {\r
+    private Map nodeParameters;\r
+    private Map stringParameters;\r
+    private Map integerParameters;\r
+\r
+    public NodeDefinitionParametersSectionHandler() {\r
+      nodeParameters = new HashMap();\r
+      stringParameters = new HashMap();\r
+      integerParameters = new HashMap();\r
+    }\r
+\r
+    public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {\r
+      String parameterName;\r
+      String defaultValue;\r
+\r
+      if (aTag.equals("node")) {\r
+        XMLReaderTool.checkAttributes(anAttributes,\r
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,\r
+            NODE_DEFINITION_NODE_PARAMETER_OPTIONAL_ATTRIBUTES);\r
+        parameterName = (String) anAttributes.get(\r
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);\r
+\r
+        if (nodeParameters.containsKey(parameterName))\r
+          throw new XMLReader.XMLReaderExc("Duplicate parameter name: '" +\r
+                                           parameterName + "'");\r
+\r
+        XMLReaderTool.checkValidIdentifier(parameterName);\r
+\r
+        nodeParameters.put(parameterName, parameterName);\r
+\r
+        return new EmptySectionHandler();\r
+      }\r
+      else if (aTag.equals("string") || aTag.equals("integer")) {\r
+        XMLReaderTool.checkAttributes(anAttributes,\r
+            NODE_DEFINITION_PARAMETER_REQUIRED_ATTRIBUTES,\r
+            NODE_DEFINITION_PARAMETER_OPTIONAL_ATTRIBUTES);\r
+        parameterName = (String) anAttributes.get(\r
+            NODE_DEFINITION_PARAMETER_NAME_ATTRIBUTE);\r
+\r
+        if (stringParameters.containsKey(parameterName) ||\r
+            integerParameters.containsKey(parameterName))\r
+          throw new XMLReader.XMLReaderExc("Duplicate parameter name: '" +\r
+                                           parameterName + "'");\r
+\r
+        XMLReaderTool.checkValidIdentifier(parameterName);\r
+\r
+        defaultValue = (String) anAttributes.get(\r
+            NODE_DEFINITION_PARAMETER_DEFAULTVALUE_ATTRIBUTE);\r
+\r
+        if (aTag.equals("string"))\r
+          stringParameters.put(parameterName, defaultValue);\r
+        else\r
+          integerParameters.put(parameterName, defaultValue);\r
+\r
+        return new EmptySectionHandler();\r
+      }\r
+      else\r
+        throw new XMLReader.XMLReaderExc(\r
+            "Only 'string', 'integer' and 'node' tags allowed here, '" + aTag + "' encountered.");\r
+    }\r
+\r
+    public void endElement(XMLReader.SectionHandler aHandler) {\r
+    }\r
+\r
+    public void finishSection() {\r
+    }\r
+\r
+    public Map getNodeParameters() {\r
+      return nodeParameters;\r
+    }\r
+\r
+    public Map getStringParameters() {\r
+      return stringParameters;\r
+    }\r
+\r
+    public Map getIntegerParameters() {\r
+      return integerParameters;\r
+    }\r
+  }\r
+}\r
index 03532c1..5cb16fc 100755 (executable)
@@ -35,9 +35,10 @@ import java.util.Map;
 import java.util.Set;
 
 import mir.producer.ProducerNode;
+import mir.util.*;
 
 public interface ProducerNodeBuilder  {
-  public void setAttributes(Map anAttributes) throws ProducerConfigExc;
+  public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc;
   public void setSubNode(String aName, ProducerNode aNode) throws ProducerConfigExc;
   public Set getAvailableSubNodes() throws ProducerConfigExc;
   public ProducerNode constructNode() throws ProducerConfigExc;
@@ -49,14 +50,14 @@ public interface ProducerNodeBuilder  {
   public class DefaultProducerNodeBuilderFactory implements ProducerNodeBuilderFactory {
     private Class producerNodeBuilderClass;
 
-    public DefaultProducerNodeBuilderFactory(Class aProducerNodeBuilderClass) throws ProducerConfigExc {
+    public DefaultProducerNodeBuilderFactory(Class aProducerNodeBuilderClass) throws ProducerConfigExc, XMLReader.XMLReaderExc  {
       if (!ProducerNodeBuilder.class.isAssignableFrom(aProducerNodeBuilderClass))
         throw new ProducerConfigExc("supplied class is not a ProducerNodeBuilder class but a " + aProducerNodeBuilderClass.getClass().getName());
 
       producerNodeBuilderClass = aProducerNodeBuilderClass;
     }
 
-    public ProducerNodeBuilder makeBuilder() throws ProducerConfigExc{
+    public ProducerNodeBuilder makeBuilder() throws ProducerConfigExc {
       try {
         return (ProducerNodeBuilder) producerNodeBuilderClass.newInstance();
       }
diff --git a/source/mir/producer/reader/ReaderTool.java b/source/mir/producer/reader/ReaderTool.java
deleted file mode 100755 (executable)
index eb02254..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2001, 2002  The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with the com.oreilly.servlet library, any library
- * licensed under the Apache Software License, The Sun (tm) Java Advanced
- * Imaging library (JAI), The Sun JIMI library (or with modified versions of
- * the above that use the same license as the above), and distribute linked
- * combinations including the two.  You must obey the GNU General Public
- * License in all respects for all of the code used other than the above
- * mentioned libraries.  If you modify this file, you may extend this exception
- * to your version of the file, but you are not obligated to do so.  If you do
- * not wish to do so, delete this exception statement from your version.
- */
-
-package mir.producer.reader;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-public class ReaderTool {
-
-  public static void checkValidIdentifier(String anIdentifier) throws ProducerConfigExc {
-  }
-
-  public static String getStringAttributeWithDefault(Map anAttributes, String aKey, String aDefault) {
-    if (anAttributes.containsKey(aKey))
-      return (String) anAttributes.get(aKey);
-    else
-      return aDefault;
-  }
-
-  public static void checkIntegerAttribute(Map anAttributes, String aKey) throws ProducerConfigExc {
-    try {
-      Integer.parseInt((String) anAttributes.get(aKey));
-    }
-    catch (Throwable t) {
-      throw new ProducerConfigExc("attribute '"+aKey+"' is not an integer" );
-    }
-  }
-
-  public static int getIntegerAttributeWithDefault(Map anAttributes, String aKey, int aDefault) throws ProducerConfigExc  {
-    String value;
-
-    if (anAttributes.containsKey(aKey)) {
-      checkIntegerAttribute(anAttributes, aKey);
-      return Integer.parseInt((String) anAttributes.get(aKey));
-    }
-    else
-      return aDefault;
-  }
-
-  public static void checkAttributes(Map anAttributes, String[] aRequiredAttributes, String[] anOptionalAttributes)  throws ProducerConfigExc {
-    checkAttributeSet(anAttributes.keySet(),
-       new HashSet(Arrays.asList(aRequiredAttributes)),
-       new HashSet(Arrays.asList(anOptionalAttributes)));
-  }
-
-  public static void checkAttributeSet(Set aSet, Set aRequiredElements, Set anOptionalElements) throws ProducerConfigExc{
-    Iterator i;
-
-    i = aSet.iterator();
-    while (i.hasNext()) {
-      Object item = i.next();
-
-      if (!(aRequiredElements.contains(item) || anOptionalElements.contains(item)))
-        throw new ProducerConfigExc("unknown attribute '" + item + "'" );
-    }
-
-    i = aRequiredElements.iterator();
-    while (i.hasNext()) {
-      Object item = i.next();
-
-      if (!(aSet.contains(item)))
-        throw new ProducerConfigExc("missing required attribute '" + item + "'" );
-    }
-
-  }
-}
\ No newline at end of file
diff --git a/source/mir/util/XMLReader.java b/source/mir/util/XMLReader.java
new file mode 100755 (executable)
index 0000000..6b53f8e
--- /dev/null
@@ -0,0 +1,319 @@
+/*\r
+ * Copyright (C) 2001, 2002  The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with the com.oreilly.servlet library, any library\r
+ * licensed under the Apache Software License, The Sun (tm) Java Advanced\r
+ * Imaging library (JAI), The Sun JIMI library (or with modified versions of\r
+ * the above that use the same license as the above), and distribute linked\r
+ * combinations including the two.  You must obey the GNU General Public\r
+ * License in all respects for all of the code used other than the above\r
+ * mentioned libraries.  If you modify this file, you may extend this exception\r
+ * to your version of the file, but you are not obligated to do so.  If you do\r
+ * not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package mir.util;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
+\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.Locator;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+import multex.Failure;\r
+import multex.Exc;\r
+\r
+public class XMLReader {\r
+  private Locator locator;\r
+  private String filename;\r
+\r
+  public void parseFile(String aFileName, SectionHandler aRootHandler, List aUsedFiles) throws XMLReaderFailure, XMLReaderExc {\r
+    try {\r
+      SAXParserFactory parserFactory = SAXParserFactory.newInstance();\r
+\r
+      parserFactory.setNamespaceAware(false);\r
+      parserFactory.setValidating(true);\r
+\r
+      XMLReaderHandler handler = new XMLReaderHandler(parserFactory, aRootHandler, aUsedFiles);\r
+\r
+      handler.includeFile(aFileName);\r
+    }\r
+    catch (Throwable e) {\r
+      Throwable t = getRootCause(e);\r
+\r
+      if (t instanceof XMLReaderExc) {\r
+        ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());\r
+        throw (XMLReaderExc) t;\r
+      }\r
+\r
+      if (t instanceof XMLReaderFailure) {\r
+        throw (XMLReaderFailure) t;\r
+      }\r
+\r
+      throw new XMLReaderFailure(t);\r
+    }\r
+  }\r
+\r
+  private Throwable getRootCause(Throwable t) {\r
+    if (t instanceof SAXParseException && ((SAXParseException) t).getException()!=null) {\r
+      return getRootCause(((SAXParseException) t).getException());\r
+    }\r
+    else if (t instanceof Failure && ((Failure) t).getCause()!=null) {\r
+      return getRootCause(((Failure) t).getCause());\r
+    }\r
+    else return t;\r
+  }\r
+\r
+  private class XMLReaderHandler extends DefaultHandler {\r
+    private Stack includeFileStack;\r
+    private SAXParserFactory parserFactory;\r
+    private SectionsManager manager;\r
+    private List usedFiles;\r
+    private InputSource inputSource;\r
+\r
+    public XMLReaderHandler(SAXParserFactory aParserFactory, SectionHandler aRootHandler, List aUsedFiles) {\r
+      super();\r
+\r
+      includeFileStack=new Stack();\r
+      parserFactory=aParserFactory;\r
+      includeFileStack = new Stack();\r
+      manager = new SectionsManager();\r
+      usedFiles = aUsedFiles;\r
+      manager.pushHandler(aRootHandler);\r
+   }\r
+\r
+    public String getLocatorDescription(Locator aLocator) {\r
+      return aLocator.getPublicId()+" ("+aLocator.getLineNumber()+")";\r
+    }\r
+\r
+    public void setDocumentLocator(Locator aLocator) {\r
+      locator=aLocator;\r
+    }\r
+\r
+    private void includeFile(String aFileName) throws XMLReaderExc, XMLReaderFailure, SAXParseException, SAXException {\r
+      File file;\r
+      SAXParser parser;\r
+\r
+      try {\r
+        if (!includeFileStack.empty())\r
+          file = new File(new File((String) includeFileStack.peek()).getParent(), aFileName);\r
+        else\r
+          file = new File(aFileName);\r
+\r
+        System.err.println("about to include "+file.getCanonicalPath());\r
+\r
+        if (includeFileStack.contains(file.getCanonicalPath())) {\r
+          throw new XMLReaderExc("recursive inclusion of file "+file.getCanonicalPath());\r
+        }\r
+\r
+        usedFiles.add(file);\r
+\r
+        parser=parserFactory.newSAXParser();\r
+\r
+        inputSource = new InputSource(new FileInputStream(file));\r
+        inputSource.setPublicId(file.getCanonicalPath());\r
+\r
+        includeFileStack.push(file.getCanonicalPath());\r
+        filename = file.getCanonicalPath();\r
+        try {\r
+          parser.parse(inputSource, this);\r
+        }\r
+        finally {\r
+          includeFileStack.pop();\r
+        }\r
+        if (!includeFileStack.empty())\r
+          filename = (String) includeFileStack.peek();\r
+      }\r
+      catch (ParserConfigurationException e) {\r
+        throw new XMLReaderExc("Internal exception while including \""+aFileName+"\": "+e.getMessage());\r
+      }\r
+      catch (SAXParseException e) {\r
+        throw e;\r
+      }\r
+      catch (XMLReaderFailure e) {\r
+        throw e;\r
+      }\r
+      catch (FileNotFoundException e) {\r
+        throw new XMLReaderExc("Include file \""+aFileName+"\" not found: "+e.getMessage());\r
+      }\r
+      catch (IOException e) {\r
+        throw new XMLReaderExc("unable to open include file \""+aFileName+"\": "+e.getMessage());\r
+      }\r
+    }\r
+\r
+    public void startElement(String aUri, String aTag, String aQualifiedName, Attributes anAttributes) throws SAXException {\r
+      Map attributesMap;\r
+      int i;\r
+\r
+      try {\r
+        if (aQualifiedName.equals("include")) {\r
+          String fileName=anAttributes.getValue("file");\r
+\r
+          if (fileName==null) {\r
+            throw new XMLReaderExc("include has no file attribute");\r
+          }\r
+\r
+          includeFile(fileName);\r
+        }\r
+        else {\r
+          attributesMap = new HashMap();\r
+          for (i=0; i<anAttributes.getLength(); i++)\r
+            attributesMap.put(anAttributes.getQName(i), anAttributes.getValue(i));\r
+\r
+          SectionHandler handler = manager.currentHandler().startElement(aQualifiedName, attributesMap);\r
+\r
+          manager.pushHandler( handler );\r
+        }\r
+      }\r
+      catch (XMLReaderExc e) {\r
+        throw new SAXParseException(e.getMessage(), null, e);\r
+      }\r
+      catch (Exception e) {\r
+        throw new SAXException(e);\r
+      }\r
+    }\r
+\r
+    public void endElement(String aUri, String aTag, String aQualifiedName) throws SAXException {\r
+      try\r
+      {\r
+        if (!aQualifiedName.equals("include")) {\r
+          SectionHandler handler = manager.popHandler();\r
+\r
+          handler.finishSection();\r
+\r
+          if (!manager.isEmpty()) {\r
+            manager.currentHandler().endElement(handler);\r
+          }\r
+        }\r
+      }\r
+      catch (XMLReaderExc e) {\r
+        throw new SAXParseException(e.getMessage(), null, e);\r
+      }\r
+      catch (Exception e) {\r
+        throw new SAXException(e);\r
+      }\r
+    }\r
+\r
+    public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXParseException {\r
+      String text = new String(aBuffer, aStart, anEnd).trim();\r
+      if ( text.length() > 0) {\r
+        throw new SAXParseException("Text not allowed", null, new XMLReaderExc("Text not allowed"));\r
+      }\r
+    }\r
+  }\r
+\r
+  private class SectionsManager {\r
+    Stack handlerStack;\r
+\r
+    public SectionsManager() {\r
+      handlerStack = new Stack();\r
+    }\r
+\r
+    public void pushHandler(SectionHandler aSectionHandler) {\r
+      handlerStack.push(aSectionHandler);\r
+    }\r
+\r
+    public SectionHandler popHandler() {\r
+      return (SectionHandler) handlerStack.pop();\r
+    }\r
+\r
+    public SectionHandler currentHandler() {\r
+      return (SectionHandler) handlerStack.peek();\r
+    }\r
+\r
+    public boolean isEmpty() {\r
+      return handlerStack.isEmpty();\r
+    }\r
+  }\r
+\r
+  public static interface SectionHandler {\r
+    public abstract SectionHandler startElement(String aTag, Map anAttributes) throws XMLReaderExc;\r
+\r
+    public abstract void endElement(SectionHandler aHandler) throws XMLReaderExc;\r
+\r
+    public void finishSection() throws XMLReaderExc;\r
+  }\r
+\r
+  public static abstract class AbstractSectionHandler implements SectionHandler {\r
+    public SectionHandler startElement(String aTag, Map anAttributes) throws XMLReaderExc {\r
+      return null;\r
+    };\r
+\r
+    public void endElement(SectionHandler aHandler) throws XMLReaderExc {\r
+    };\r
+\r
+    public void finishSection() throws XMLReaderExc {\r
+    }\r
+  }\r
+\r
+  public static class XMLReaderExc extends Exc {\r
+    private boolean hasLocation;\r
+    private String filename;\r
+    private int lineNr;\r
+    private int columnNr;\r
+\r
+    public XMLReaderExc(String aMessage) {\r
+      super(aMessage);\r
+      hasLocation = false;\r
+    }\r
+\r
+    protected void setLocation(String aFilename, int aLineNr, int aColumnNr) {\r
+      filename = aFilename;\r
+      lineNr = aLineNr;\r
+      columnNr = aColumnNr;\r
+      hasLocation = true;\r
+    }\r
+\r
+    public boolean getHasLocation() {\r
+      return hasLocation;\r
+    }\r
+\r
+    public int getLineNr() {\r
+      return lineNr;\r
+    }\r
+\r
+    public int getColumnNr() {\r
+      return columnNr;\r
+    }\r
+\r
+    public String getFilename() {\r
+      return filename;\r
+    }\r
+  }\r
+\r
+  public static class XMLReaderFailure extends Failure {\r
+    public XMLReaderFailure(String aMessage, Throwable aCause) {\r
+      super(aMessage, aCause);\r
+    }\r
+\r
+    public XMLReaderFailure(Throwable aCause) {\r
+      super(aCause.getMessage(), aCause);\r
+    }\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/source/mir/util/XMLReaderTool.java b/source/mir/util/XMLReaderTool.java
new file mode 100755 (executable)
index 0000000..95e4322
--- /dev/null
@@ -0,0 +1,98 @@
+package mir.util;
+
+/*
+ * Copyright (C) 2001, 2002  The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with the com.oreilly.servlet library, any library
+ * licensed under the Apache Software License, The Sun (tm) Java Advanced
+ * Imaging library (JAI), The Sun JIMI library (or with modified versions of
+ * the above that use the same license as the above), and distribute linked
+ * combinations including the two.  You must obey the GNU General Public
+ * License in all respects for all of the code used other than the above
+ * mentioned libraries.  If you modify this file, you may extend this exception
+ * to your version of the file, but you are not obligated to do so.  If you do
+ * not wish to do so, delete this exception statement from your version.
+ */
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+public class XMLReaderTool {
+
+  public static void checkValidIdentifier(String anIdentifier) throws XMLReader.XMLReaderExc {
+  }
+
+  public static String getStringAttributeWithDefault(Map anAttributes, String aKey, String aDefault) {
+    if (anAttributes.containsKey(aKey))
+      return (String) anAttributes.get(aKey);
+    else
+      return aDefault;
+  }
+
+  public static void checkIntegerAttribute(Map anAttributes, String aKey) throws XMLReader.XMLReaderExc {
+    try {
+      Integer.parseInt((String) anAttributes.get(aKey));
+    }
+    catch (Throwable t) {
+      throw new XMLReader.XMLReaderExc("attribute '"+aKey+"' is not an integer" );
+    }
+  }
+
+  public static int getIntegerAttributeWithDefault(Map anAttributes, String aKey, int aDefault) throws XMLReader.XMLReaderExc  {
+    String value;
+
+    if (anAttributes.containsKey(aKey)) {
+      checkIntegerAttribute(anAttributes, aKey);
+      return Integer.parseInt((String) anAttributes.get(aKey));
+    }
+    else
+      return aDefault;
+  }
+
+  public static void checkAttributes(Map anAttributes, String[] aRequiredAttributes, String[] anOptionalAttributes)  throws XMLReader.XMLReaderExc {
+    checkAttributeSet(anAttributes.keySet(),
+       new HashSet(Arrays.asList(aRequiredAttributes)),
+       new HashSet(Arrays.asList(anOptionalAttributes)));
+  }
+
+  public static void checkAttributeSet(Set aSet, Set aRequiredElements, Set anOptionalElements) throws XMLReader.XMLReaderExc{
+    Iterator i;
+
+    i = aSet.iterator();
+    while (i.hasNext()) {
+      Object item = i.next();
+
+      if (!(aRequiredElements.contains(item) || anOptionalElements.contains(item)))
+        throw new XMLReader.XMLReaderExc("unknown attribute '" + item + "'" );
+    }
+
+    i = aRequiredElements.iterator();
+    while (i.hasNext()) {
+      Object item = i.next();
+
+      if (!(aSet.contains(item)))
+        throw new XMLReader.XMLReaderExc("missing required attribute '" + item + "'" );
+    }
+
+  }
+}
index f8dc268..3004000 100755 (executable)
@@ -38,7 +38,8 @@ import mir.producer.ProducerNode;
 import mir.producer.reader.DefaultProducerNodeBuilders;
 import mir.producer.reader.ProducerConfigExc;
 import mir.producer.reader.ProducerNodeBuilderLibrary;
-import mir.producer.reader.ReaderTool;
+import mir.util.*;
+
 import mircoders.producer.ContentMarkingProducerNode;
 import mircoders.producer.ContentModifyingProducerNode;
 import mircoders.producer.IndexingProducerNode;
@@ -47,6 +48,7 @@ import mircoders.producer.PDFGeneratingProducerNode;
 import mircoders.producer.PDFPreFormattingProducerNode;
 import mircoders.producer.UnIndexingProducerNode;
 
+
 public class SupplementalProducerNodeBuilders {
 
   public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary, EntityAdapterModel aModel) throws ProducerConfigExc {
@@ -73,8 +75,8 @@ public class SupplementalProducerNodeBuilders {
       super(MARKER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(MARKER_KEY_ATTRIBUTE);
     };
@@ -98,8 +100,8 @@ public class SupplementalProducerNodeBuilders {
       super(INDEXER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, INDEXER_REQUIRED_ATTRIBUTES, INDEXER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, INDEXER_REQUIRED_ATTRIBUTES, INDEXER_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(INDEXER_KEY_ATTRIBUTE);
       pathToIndex = (String) anAttributes.get(INDEXER_INDEX_ATTRIBUTE);
@@ -125,8 +127,8 @@ public class SupplementalProducerNodeBuilders {
       super(UNINDEXER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, UNINDEXER_REQUIRED_ATTRIBUTES, UNINDEXER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, UNINDEXER_REQUIRED_ATTRIBUTES, UNINDEXER_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(UNINDEXER_KEY_ATTRIBUTE);
       pathToIndex = (String) anAttributes.get(UNINDEXER_INDEX_ATTRIBUTE);
@@ -154,8 +156,8 @@ public class SupplementalProducerNodeBuilders {
       super(CONTENT_MODIFIER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, CONTENT_MODIFIER_REQUIRED_ATTRIBUTES, CONTENT_MODIFIER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, CONTENT_MODIFIER_REQUIRED_ATTRIBUTES, CONTENT_MODIFIER_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(CONTENT_MODIFIER_KEY_ATTRIBUTE);
       field = (String) anAttributes.get(CONTENT_MODIFIER_FIELD_ATTRIBUTE);
@@ -180,8 +182,8 @@ public class SupplementalProducerNodeBuilders {
       super(MEDIA_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, MEDIA_REQUIRED_ATTRIBUTES, MEDIA_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, MEDIA_REQUIRED_ATTRIBUTES, MEDIA_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(MEDIA_KEY_ATTRIBUTE);
     };
@@ -213,8 +215,8 @@ public class SupplementalProducerNodeBuilders {
       super(MARKER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
 
       key = (String) anAttributes.get(MARKER_KEY_ATTRIBUTE);
       numLinesBetweenImages = (String) anAttributes.get(PDF_NUM_LINES_ATTRIBUTE);
@@ -249,8 +251,8 @@ public class SupplementalProducerNodeBuilders {
       super(MARKER_SUBNODES);
     }
 
-    public void setAttributes(Map anAttributes) throws ProducerConfigExc {
-      ReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
+    public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
+      XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES);
 
       generator = (String) anAttributes.get(PDF_GENERATOR_ATTRIBUTE);
       destination = (String) anAttributes.get(PDF_DESTINATION_ATTRIBUTE);