You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hivemind.apache.org by hl...@apache.org on 2004/04/30 21:22:39 UTC

cvs commit: jakarta-hivemind/framework/src/java/org/apache/hivemind/parse AbstractParser.java DescriptorParser.java

hlship      2004/04/30 12:22:39

  Modified:    framework/src/java/org/apache/hivemind/parse
                        DescriptorParser.java
  Added:       framework/src/java/org/apache/hivemind/parse
                        AbstractParser.java
  Log:
  Split out much of DescriptorParser into an abstract super-class for easy reuse.
  
  Revision  Changes    Path
  1.9       +23 -200   jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.java
  
  Index: DescriptorParser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DescriptorParser.java	28 Apr 2004 23:31:17 -0000	1.8
  +++ DescriptorParser.java	30 Apr 2004 19:22:39 -0000	1.9
  @@ -73,26 +73,18 @@
    * 
    * <p>
    * TODO: The parser ignores element content except inside
  - * &lt;extension&gt; and &lt;parameters&gt; ... it probably should forbid
  + * &lt;contribution&gt; and &lt;invoke-factory&gt; ... it probably should forbid
    * non-whitespace content.
    *
    * @author Howard Lewis Ship
    * @version $Id$
    */
  -public final class DescriptorParser extends DefaultHandler
  +public final class DescriptorParser extends AbstractParser
   {
       private static final Log LOG = LogFactory.getLog(DescriptorParser.class);
   
  -    private Resource _resource;
       private ClassResolver _resolver;
  -
       private SAXParser _parser;
  -
  -    private Locator _locator;
  -    private Location _location;
  -    private int _line;
  -    private int _column;
  -
       private ModuleDescriptor _moduleDescriptor;
   
       private class SchemaRelinker implements Runnable
  @@ -238,42 +230,6 @@
       private final Map _ruleMap = new HashMap();
   
       /**
  -     * The parser is built around a stack of these Items.  This used to figure
  -     * out the current state, the element being processed, and the matching descriptor
  -     * object.
  -     */
  -    private static class Item
  -    {
  -        String _elementName;
  -        Object _object;
  -        int _state;
  -        StringBuffer _buffer;
  -
  -        String getContent()
  -        {
  -            if (_buffer != null)
  -                return _buffer.toString().trim();
  -
  -            return null;
  -        }
  -
  -        void addContent(char[] buffer, int start, int length)
  -        {
  -            if (_state == STATE_LWDOM)
  -            {
  -                if (_buffer == null)
  -                    _buffer = new StringBuffer(length);
  -
  -                _buffer.append(buffer, start, length);
  -            }
  -        }
  -    }
  -
  -    private List _stack = new ArrayList();
  -
  -    private Item _top;
  -
  -    /**
        * Temporary storage of the current {@link Attributes}.
        */
       private Map _attributes = new HashMap();
  @@ -291,56 +247,6 @@
        * is set to the current location.
        */
   
  -    private void push(String elementName, Object object, int state)
  -    {
  -        HiveMind.setLocation(object, getLocation());
  -
  -        Item item = new Item();
  -        item._elementName = elementName;
  -        item._object = object;
  -        item._state = state;
  -
  -        _stack.add(item);
  -
  -        _top = item;
  -
  -    }
  -
  -    private void pop()
  -    {
  -        int count = _stack.size();
  -
  -        _stack.remove(count - 1);
  -
  -        if (count == 1)
  -            _top = null;
  -        else
  -            _top = (Item) _stack.get(count - 2);
  -    }
  -
  -    private Item peek()
  -    {
  -        return peek(0);
  -    }
  -
  -    private Item peek(int depth)
  -    {
  -        int count = _stack.size();
  -        return (Item) _stack.get(count - 1 - depth);
  -    }
  -
  -    private Object peekObject()
  -    {
  -        return peekObject(0);
  -    }
  -
  -    private Object peekObject(int depth)
  -    {
  -        Item item = peek(depth);
  -
  -        return item._object;
  -    }
  -
       public ModuleDescriptor parse(Resource resource, ClassResolver resolver)
       {
           try
  @@ -348,7 +254,8 @@
               if (LOG.isDebugEnabled())
                   LOG.debug("Parsing " + resource);
   
  -            _resource = resource;
  +            initializeParser(resource, STATE_START);
  +
               _resolver = resolver;
   
               String path = resource.getPath();
  @@ -376,11 +283,8 @@
           }
           finally
           {
  -            _resource = null;
  -            _locator = null;
  -            _location = null;
  -            _stack.clear();
  -            _top = null;
  +            resetParser();
  +
               _moduleDescriptor = null;
               _attributes.clear();
               _resolver = null;
  @@ -435,45 +339,6 @@
           return _parser;
       }
   
  -    private Location getLocation()
  -    {
  -        int line = _locator.getLineNumber();
  -        int column = _locator.getColumnNumber();
  -
  -        if (line != _line || column != _column)
  -            _location = null;
  -
  -        if (_location == null)
  -            _location = new LocationImpl(_resource, line, column);
  -
  -        return _location;
  -    }
  -
  -    public void characters(char[] ch, int start, int length) throws SAXException
  -    {
  -        _top.addContent(ch, start, length);
  -    }
  -
  -    public void error(SAXParseException ex) throws SAXException
  -    {
  -        fatalError(ex);
  -    }
  -
  -    public void fatalError(SAXParseException ex) throws SAXException
  -    {
  -        throw ex;
  -    }
  -
  -    public void warning(SAXParseException ex) throws SAXException
  -    {
  -        fatalError(ex);
  -    }
  -
  -    public void setDocumentLocator(Locator locator)
  -    {
  -        _locator = locator;
  -    }
  -
       private void buildAttributes(Attributes attributes)
       {
           _attributes.clear();
  @@ -498,7 +363,7 @@
       {
           Iterator i = _attributes.keySet().iterator();
   
  -        String elementName = _top._elementName;
  +        String elementName = peekElementName();
   
           ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
   
  @@ -606,49 +471,17 @@
           }
       }
   
  -    private String getElementPath()
  -    {
  -        StringBuffer buffer = new StringBuffer();
  -
  -        int count = _stack.size();
  -        for (int i = 0; i < count; i++)
  -        {
  -            if (i > 0)
  -                buffer.append('/');
  -
  -            Item item = (Item) _stack.get(i);
  -
  -            buffer.append(item._elementName);
  -        }
  -
  -        return buffer.toString();
  -    }
  -
  -    private void unexpectedElement(String elementName)
  -    {
  -        throw new ApplicationRuntimeException(
  -            HiveMind.format(
  -                "DescriptorParser.unexpected-element",
  -                elementName,
  -                getElementPath(),
  -                getLocation()),
  -            getLocation(),
  -            null);
  -    }
  -
       public void startElement(String uri, String localName, String qName, Attributes attributes)
           throws SAXException
       {
  -        int state = (_top == null) ? STATE_START : _top._state;
  +        // The SDL parser reports localName but not qName.  The standard SAX parsers
  +        // report qName but not localName.
   
  -		// The SDL parser reports localName but not qName.  The standard SAX parsers
  -		// report qName but not localName.
  -		
           String elementName = qName != null ? qName : localName;
  -      
  +
           buildAttributes(attributes);
   
  -        switch (state)
  +        switch (getState())
           {
               case STATE_START :
   
  @@ -725,9 +558,7 @@
   
       public void endElement(String uri, String localName, String qName) throws SAXException
       {
  -        int state = _top._state;
  -
  -        switch (state)
  +        switch (getState())
           {
               case STATE_LWDOM :
   
  @@ -863,7 +694,7 @@
   
               String path = getAttribute("descriptor");
   
  -            Resource subModuleDescriptor = _resource.getRelativeResource(path);
  +            Resource subModuleDescriptor = getResource().getRelativeResource(path);
   
               _registryAssembly.enqueueModuleParse(subModuleDescriptor, _resolver);
   
  @@ -941,12 +772,11 @@
                   result = reffed;
               }
   
  -            Item top = peek();
  -
               // Change our mind about the state ... if using a ref-id, then
               // no content is allowed.
  -            top._object = reffed;
  -            top._state = STATE_NO_CONTENT;
  +
  +            updateObject(reffed);
  +            setState(STATE_NO_CONTENT);
   
               return result;
           }
  @@ -976,7 +806,7 @@
           ContributionDescriptor ed = (ContributionDescriptor) peekObject();
           ed.addElement(element);
   
  -        push(elementName, element, STATE_LWDOM);
  +        push(elementName, element, STATE_LWDOM, false);
       }
   
       /**
  @@ -995,7 +825,7 @@
   
           sid.addParameter(element);
   
  -        push(elementName, element, STATE_LWDOM);
  +        push(elementName, element, STATE_LWDOM, false);
       }
   
       private void beginLWDom(String elementName)
  @@ -1005,7 +835,7 @@
           ElementImpl parent = (ElementImpl) peekObject();
           parent.addElement(element);
   
  -        push(elementName, element, STATE_LWDOM);
  +        push(elementName, element, STATE_LWDOM, false);
       }
   
       private void beginServicePoint(String elementName)
  @@ -1334,11 +1164,6 @@
   
               elementModel.addRule(rule);
   
  -            // For what its worth, remember that Rule is the top
  -            // object on the stack (not really needed, because
  -            // <custom> allows no content.
  -
  -            peek()._object = rule;
               return;
           }
   
  @@ -1363,10 +1188,8 @@
   
       private void endLWDom()
       {
  -        Item item = peek();
  -
  -        ElementImpl element = (ElementImpl) item._object;
  -        element.setContent(item.getContent());
  +        ElementImpl element = (ElementImpl) peekObject();
  +        element.setContent(peekContent());
       }
   
       private ElementImpl buildLWDomElement(String elementName)
  @@ -1543,7 +1366,7 @@
               String message =
                   HiveMind.format(
                       "DescriptorParser.invalid-id-format",
  -                    new Object[] { attributeName, result, peek()._elementName, getLocation()});
  +                    new Object[] { attributeName, result, peekElementName(), getLocation()});
   
               LOG.error(message);
           }
  
  
  
  1.1                  jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/AbstractParser.java
  
  Index: AbstractParser.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  //Licensed under the Apache License, Version 2.0 (the "License");
  //you may not use this file except in compliance with the License.
  //You may obtain a copy of the License at
  //
  //	http://www.apache.org/licenses/LICENSE-2.0
  //
  //Unless required by applicable law or agreed to in writing, software
  //distributed under the License is distributed on an "AS IS" BASIS,
  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  //See the License for the specific language governing permissions and
  //limitations under the License.
  
  package org.apache.hivemind.parse;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.hivemind.HiveMind;
  import org.apache.hivemind.Location;
  import org.apache.hivemind.Resource;
  import org.apache.hivemind.impl.LocationImpl;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  import org.xml.sax.helpers.DefaultHandler;
  
  /**
   * Abstract super-class for parsers based around the SAX event model.
   * This class provides support for managing a stack of elements, making it
   * reasonable to establish relationships between elements. It also assists in
   * setting the {@link org.apache.hivemind.Location} of elements as they are created.
   * 
   * <p>
   * This support is structured around both XML and Simplified Data Language (SDL), both
   * of which can produce SAX events. It is also suited towards configuration files rather 
   * than documents, in that the <em>content</em> (parsable character data) within an element
   * is concatinated together and tracked as a single blob.
   *
   * @author Howard Lewis Ship
   * @version $Id: AbstractParser.java,v 1.1 2004/04/30 19:22:39 hlship Exp $
   */
  public abstract class AbstractParser extends DefaultHandler
  {
  
      /**
       * The parser is built around a stack of these Items.  This used to figure
       * out the current state, the element being processed, and the matching descriptor
       * object.
       */
      private static class Item
      {
          StringBuffer _buffer;
          String _elementName;
          boolean _ignoreCharacterData;
          Object _object;
  
          /**
           * Prior state of the parser before this item was pushed.
           */
          int _priorState;
  
          Item(String elementName, Object object, int priorState, boolean ignoreCharacterData)
          {
              _elementName = elementName;
              _object = object;
              _priorState = priorState;
              _ignoreCharacterData = ignoreCharacterData;
          }
  
          void addContent(char[] buffer, int start, int length)
          {
              if (_ignoreCharacterData)
                  return;
  
              if (_buffer == null)
                  _buffer = new StringBuffer(length);
  
              _buffer.append(buffer, start, length);
          }
  
          String getContent()
          {
              if (_buffer != null)
                  return _buffer.toString().trim();
  
              return null;
          }
      }
      
      private int _currentColumn;
      private int _currentLine;
      private Location _location;
      private Locator _locator;
      private Resource _resource;
      private List _stack;
      private int _state;
      private Item _top;
  
      /**
       * Accepts parseable character data from within an element and applies it to the
       * top stack element. This may be invoked multiple times by the parser, and the
       * overall data will accumulate. This content can be
       * retrieved via {@link #peekContent()}.
       */
      public void characters(char[] ch, int start, int length) throws SAXException
      {
          _top.addContent(ch, start, length);
      }
  
      /**
       * Invokes {@link #fatalError(SAXParseException)}.
       */
      public void error(SAXParseException ex) throws SAXException
      {
          fatalError(ex);
      }
  
      /**
       * @param ex exception to be thrown
       * @throws SAXParseException 
       */
      public void fatalError(SAXParseException ex) throws SAXException
      {
          throw ex;
      }
  
      /**
       * Returns a "path" to the current element, as a series of element names
       * seperated by slashes, i.e., "top/middle/leaf".
       */
      protected String getElementPath()
      {
          StringBuffer buffer = new StringBuffer();
  
          int count = _stack.size();
          for (int i = 0; i < count; i++)
          {
              if (i > 0)
                  buffer.append('/');
  
              Item item = (Item) _stack.get(i);
  
              buffer.append(item._elementName);
          }
  
          return buffer.toString();
      }
  
      /**
       * Returns the current lcoation, as reported by the parser.
       */
      protected Location getLocation()
      {
          int line = _locator.getLineNumber();
          int column = _locator.getColumnNumber();
  
          if (line != _currentLine || column != _currentColumn)
              _location = null;
  
          if (_location == null)
              _location = new LocationImpl(_resource, line, column);
  
          return _location;
      }
  
      /**
       * Returns the {@link Resource} being parsed (as set
       * by {@link #initializeParser(Resource, int)}.
       */
  
      protected Resource getResource()
      {
          return _resource;
      }
  
      /**
       * Returns the current state of the parser. State is initially
       * set by {@link #initializeParser(Resource, int) and is later updated
       * by {@link #push(String, Object, int)} and {@link #pop()}.
       */
      protected int getState()
      {
          return _state;
      }
  
      /**
       * Initializes the parser; this should be called before any SAX parse events
       * are received.
       * 
       * @param resource the resource being parsed (used for some error messages)
       * @param startState the initial state of the parser (the interpretation of state
       * is determined by subclasses)
       */
      protected void initializeParser(Resource resource, int startState)
      {
          _resource = resource;
          _stack = new ArrayList();
  
          _location = null;
          _state = startState;
      }
  
      private Item peek()
      {
          return peek(0);
      }
  
      private Item peek(int depth)
      {
          int count = _stack.size();
  
          return (Item) _stack.get(count - 1 - depth);
      }
  
      /**
       * Peeks at the top element on the stack, and returns
       * its content (the accumuulated parseable character data directly
       * enclosed by its start/end tags (for XML) or braces (for SDL).
       */
      protected String peekContent()
      {
          return _top.getContent();
      }
  
      /**
       * Peeks at the top element on the stack and returns its element name.
       */
      protected String peekElementName()
      {
          return _top._elementName;
      }
  
      /**
       * Peeks at the top element on the stack and returns the object for that element.
       */
  
      protected Object peekObject()
      {
          return _top._object;
      }
  
      /**
       * Invoked when the closing tag for an element is enountered
       * {i.e, from {@link #endElement(String)}). This removes the corresponding
       * item from the stack, and sets the parser state back to the (new) top element's
       * state.
       */
      protected void pop()
      {
          int count = _stack.size();
  
          _state = _top._priorState;
  
          _stack.remove(count - 1);
  
          if (count == 1)
              _top = null;
          else
              _top = (Item) _stack.get(count - 2);
      }
  
      /**
       * Enters a new state, pushing an object onto the stack.
       * Invokes {@link #push(String, Object, int, boolean), and ignores
       * character data within the element.
       * 
       * @param elementName the element whose start tag was just parsed
       * @param object the object created to represent the new object
       * @param state the new state for the parse
       */
      protected void push(String elementName, Object object, int state)
      {
          push(elementName, object, state, true);
      }
  
      /**
       * Enters a new state, pushing an object onto the stack. If the object
       * implements {@link ILocationHolder} then its location property
       * is set to the current location.
       * 
       * @param elementName the element whose start tag was just parsed
       * @param object the object created to represent the new object
       * @param state the new state for the parse
       * @param ignoreCharacterData if true, then any character data (typically whitespace)
       * directly enclosed by the element is ignored
       */
      protected void push(String elementName, Object object, int state, boolean ignoreCharacterData)
      {
          HiveMind.setLocation(object, getLocation());
  
          Item item = new Item(elementName, object, _state, ignoreCharacterData);
  
          _stack.add(item);
  
          _top = item;
          _state = state;
      }
  
      /**
       * Resets all state after a parse. 
       */
      protected void resetParser()
      {
          _resource = null;
          _locator = null;
          _stack = null;
          _location = null;
      }
  
      /**
       * Invoked by the parser, the locator is stored and later used
       * by {@link #getLocation()}.
       */
      public void setDocumentLocator(Locator locator)
      {
          _locator = locator;
      }
  
      /**
       * Forces a change to a specific state.
       */
      protected void setState(int state)
      {
          _state = state;
      }
  
      /**
       * Invoked when an unexpected element is parsed (useful for
       * parses that don't perform validation, or when there's no DTD).
       * 
       * @throws ApplicationRuntimeException describing the situation
       */
      protected void unexpectedElement(String elementName)
      {
          throw new ApplicationRuntimeException(
              HiveMind.format(
                  "DescriptorParser.unexpected-element",
                  elementName,
                  getElementPath(),
                  getLocation()),
              getLocation(),
              null);
      }
  
      /**
       * Ocassionaly it is necessary to "change our mind" about what's
       * on the top of the stack.
       * 
       * @param object the new object for the top stack element
       */
      protected void updateObject(Object object)
      {
          _top._object = object;
      }
  
      /**
       * Invokes {@link #fatalError(SAXParseException)},
       */
      public void warning(SAXParseException ex) throws SAXException
      {
          fatalError(ex);
      }
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-cvs-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-cvs-help@jakarta.apache.org