001: /**********************************************************************
002: Copyright (c) 2006 Andy Jefferson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: ...
017: **********************************************************************/package org.jpox.metadata.xml;
018:
019: /**
020: * Abstract handler for MetaData parsing.
021: * Should be extended to handle processing of specific types of metadata.
022: *
023: * @version $Revision: 1.1 $
024: */
025: import java.io.IOException;
026: import java.util.Stack;
027:
028: import org.jpox.metadata.MetaData;
029: import org.jpox.metadata.MetaDataManager;
030: import org.jpox.util.JPOXLogger;
031: import org.jpox.util.Localiser;
032: import org.xml.sax.Attributes;
033: import org.xml.sax.EntityResolver;
034: import org.xml.sax.InputSource;
035: import org.xml.sax.SAXException;
036: import org.xml.sax.SAXParseException;
037: import org.xml.sax.helpers.DefaultHandler;
038:
039: public class AbstractMetaDataHandler extends DefaultHandler {
040: /** Localiser for messages. */
041: protected static Localiser LOCALISER = Localiser
042: .getInstance("org.jpox.metadata.Localisation");
043:
044: /** Manager for the MetaData. */
045: protected final MetaDataManager mgr;
046:
047: /** Filename for the parsed file. */
048: protected final String filename;
049:
050: /** The MetaData for this file (the end result of the parse process. */
051: protected MetaData metadata;
052:
053: /** Entity Resolver to use (if required) */
054: protected final EntityResolver entityResolver;
055:
056: /** parser buffer */
057: protected StringBuffer charactersBuffer = new StringBuffer();
058:
059: /**
060: * Stack of meta-data elements. The top of the stack is always the element
061: * being process at the moment. The elements are not the XML Element type
062: * but are things like ClassMetaData, PackageMetaData etc.
063: */
064: protected Stack stack = new Stack();
065:
066: /**
067: * Constructor.
068: * @param mgr Manager for the MetaData
069: * @param filename The filename
070: * @param resolver Entity Resolver to use (null if not available)
071: */
072: public AbstractMetaDataHandler(MetaDataManager mgr,
073: String filename, EntityResolver resolver) {
074: super ();
075: this .mgr = mgr;
076: this .filename = filename;
077: this .entityResolver = resolver;
078: }
079:
080: /**
081: * Accessor for the MetaData for this file.
082: * @return The MetaData.
083: */
084: public MetaData getMetaData() {
085: return metadata;
086: }
087:
088: /**
089: * Parser error method. If any syntactical errors are encountered on
090: * validation they will appear here and be logged as warnings.
091: * Just points the user to the line/column of their Meta-Data file for now.
092: * @param e Parse Exception
093: * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
094: */
095: public void error(SAXParseException e) throws SAXException {
096: if (e.getColumnNumber() >= 0) {
097: // Give the column number if it has a value!
098: JPOXLogger.METADATA.warn(LOCALISER.msg("044039", filename,
099: "" + e.getLineNumber(), "" + e.getColumnNumber(), e
100: .getMessage()));
101: } else {
102: JPOXLogger.METADATA.warn(LOCALISER.msg("044038", filename,
103: "" + e.getLineNumber(), e.getMessage()));
104: }
105: }
106:
107: /**
108: * Accessor for an attribute out of the attributes for an element. Allows
109: * the specification of a default if no value is provided.
110: * @param attrs The attributes
111: * @param key Key for the attribute to return
112: * @param defaultValue A default to impose if no value.
113: * @return Value for the attribute with the specified key.
114: */
115: protected String getAttr(Attributes attrs, String key,
116: String defaultValue) {
117: String result = attrs.getValue(key);
118: if (result == null) {
119: return defaultValue;
120: } else if (result.length() == 0) {
121: return defaultValue;
122: }
123: return result;
124: }
125:
126: /**
127: * Accessor for an attribute out of the attributes for an element.
128: * @param attrs The attributes
129: * @param key Key for the attribute to return
130: * @return Value for the attribute with the specified key.
131: */
132: protected String getAttr(Attributes attrs, String key) {
133: return getAttr(attrs, key, null);
134: }
135:
136: /**
137: * Method to resolve XML entities.
138: * Uses the entity resolver (if provided) to check for local variants.
139: * @param publicId The public id.
140: * @param systemId The system id.
141: * @return Input Source for the URI.
142: * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,java.lang.String)
143: */
144: public InputSource resolveEntity(String publicId, String systemId)
145: throws SAXException {
146: InputSource source = null;
147: if (entityResolver != null) {
148: // Delegate to the entity resolver
149: try {
150: source = entityResolver.resolveEntity(publicId,
151: systemId);
152: } catch (IOException ioe) {
153: // Do nothing
154: }
155: }
156: if (source == null) {
157: // TODO Cater better here for this situation
158: // Would have been nice to just call super.resolveEntity() but sadly SUN have
159: // screwed the method by adding a new checked exception on it in JDK 1.5 meaning
160: // that we either compile in 1.4 or in 1.5.
161: }
162: return source;
163: }
164:
165: /**
166: * Notification handler for the "body" data inside an element.
167: * @param ch The characters
168: * @param start The start position in the character array.
169: * @param length The length of the string.
170: * @throws SAXException in parsing errors
171: */
172: public void characters(char[] ch, int start, int length)
173: throws SAXException {
174: // Add to the buffer
175: charactersBuffer.append(ch, start, length);
176: }
177:
178: /**
179: * Accessor for the "body" text metadata.
180: * Resets the body text after access.
181: * @return the string form of this metadata
182: */
183: public String getString() {
184: String result = charactersBuffer.toString();
185: charactersBuffer = new StringBuffer();
186: return result;
187: }
188:
189: /**
190: * Accessor for the current MetaData component.
191: * @return The current MetaData component.
192: */
193: protected MetaData getStack() {
194: Object o = stack.lastElement();
195: if (o != null) {
196: return (MetaData) o;
197: }
198: return null;
199: }
200:
201: /**
202: * Method to remove the current MetaData component from the Stack.
203: * @return Latest MetaData component.
204: */
205: protected MetaData popStack() {
206: return (MetaData) (stack.pop());
207: }
208:
209: /**
210: * Method to add a MetaData component to the Stack.
211: * @param md The component to add.
212: */
213: protected void pushStack(MetaData md) {
214: stack.push(md);
215: }
216: }
|