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
- * <extension> and <parameters> ... it probably should forbid
+ * <contribution> and <invoke-factory> ... 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