001: /*
002: Copyright (c) 2007, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.ws.wsdl;
030:
031: /**
032: * Pull parser for generic method or field signature.
033: */
034: public class SignatureParser {
035: //
036: // Signature events
037: public static final int END_EVENT = 0;
038: public static final int TYPE_EVENT = 1;
039: public static final int METHOD_PARAMETERS_START_EVENT = 2;
040: public static final int METHOD_PARAMETERS_END_EVENT = 3;
041: public static final int TYPE_PARAMETERS_START_EVENT = 4;
042: public static final int TYPE_PARAMETERS_END_EVENT = 5;
043:
044: //
045: // Common types
046: private static final String STRING_SIGNATURE = "java/lang/String;";
047: private static final String STRING_TYPE = "java.lang.String";
048: private static final String OBJECT_SIGNATURE = "java/lang/Object;";
049: private static final String OBJECT_TYPE = "java.lang.Object";
050:
051: //
052: // Instance data
053: private final String m_signature;
054: private int m_offset;
055: private int m_event;
056: private boolean m_isPrimitive;
057: private boolean m_isParameterized;
058: private String m_type;
059:
060: /**
061: * Constructor.
062: *
063: * @param sig signature attribute value
064: */
065: public SignatureParser(String sig) {
066: if (sig.startsWith("Signature(") && sig.endsWith(")")) {
067: m_signature = sig.substring(10, sig.length() - 1);
068: m_event = -1;
069: } else {
070: throw new IllegalArgumentException(
071: "Internal error: not a valid Signature");
072: }
073: }
074:
075: /**
076: * Check if type is parameterized. It is an error to call this if the
077: * current event is not {@link #TYPE_EVENT}.
078: *
079: * @return <code>true</code> if parameterized type
080: */
081: public boolean isParameterized() {
082: if (m_event == TYPE_EVENT) {
083: return m_isParameterized;
084: } else {
085: throw new IllegalStateException(
086: "Internal error: not at TYPE_EVENT");
087: }
088: }
089:
090: /**
091: * Check if type is a primitive. It is an error to call this if the
092: * current event is not {@link #TYPE_EVENT}.
093: *
094: * @return <code>true</code> if primitive type
095: */
096: public boolean isPrimitive() {
097: if (m_event == TYPE_EVENT) {
098: return m_isPrimitive;
099: } else {
100: throw new IllegalStateException(
101: "Internal error: not at TYPE_EVENT");
102: }
103: }
104:
105: /**
106: * Get current event.
107: *
108: * @return event
109: */
110: public int getEvent() {
111: return m_event;
112: }
113:
114: /**
115: * Get type. It is an error to call this if the current event is not
116: * {@link #TYPE_EVENT}.
117: *
118: * @return type
119: */
120: public String getType() {
121: if (m_event == TYPE_EVENT) {
122: return m_type;
123: } else {
124: throw new IllegalStateException(
125: "Internal error: not at TYPE_EVENT");
126: }
127: }
128:
129: /**
130: * Get next parse event.
131: *
132: * @return event
133: */
134: public int next() {
135: if (m_event == END_EVENT) {
136: throw new IllegalStateException(
137: "Internal error: cannot advance parser");
138: } else if (m_offset >= m_signature.length()) {
139: m_event = END_EVENT;
140: } else {
141:
142: // assume next event is a primitive type, then correct if necessary
143: m_event = TYPE_EVENT;
144: m_isPrimitive = true;
145: m_isParameterized = false;
146: char chr = m_signature.charAt(m_offset++);
147: switch (chr) {
148:
149: // blocking start/end characters
150:
151: case '(':
152: m_event = METHOD_PARAMETERS_START_EVENT;
153: break;
154:
155: case ')':
156: m_event = METHOD_PARAMETERS_END_EVENT;
157: break;
158:
159: case '<':
160: m_event = TYPE_PARAMETERS_START_EVENT;
161: break;
162:
163: case '>':
164: m_event = TYPE_PARAMETERS_END_EVENT;
165: if (m_offset < m_signature.length()
166: && m_signature.charAt(m_offset) == ';') {
167: m_offset++;
168: }
169: break;
170:
171: // primitive type indication characters
172:
173: case 'B':
174: m_type = "byte";
175: break;
176:
177: case 'C':
178: m_type = "char";
179: break;
180:
181: case 'D':
182: m_type = "double";
183: break;
184:
185: case 'F':
186: m_type = "float";
187: break;
188:
189: case 'I':
190: m_type = "int";
191: break;
192:
193: case 'J':
194: m_type = "long";
195: break;
196:
197: case 'S':
198: m_type = "short";
199: break;
200:
201: case 'V':
202: m_type = "void";
203: break;
204:
205: case 'Z':
206: m_type = "boolean";
207: break;
208:
209: // object type
210:
211: case 'L': {
212: m_isPrimitive = false;
213: if (m_signature.startsWith(STRING_SIGNATURE, m_offset)) {
214: m_offset += STRING_SIGNATURE.length();
215: m_type = STRING_TYPE;
216: } else if (m_signature.startsWith(OBJECT_SIGNATURE,
217: m_offset)) {
218: m_offset += OBJECT_SIGNATURE.length();
219: m_type = OBJECT_TYPE;
220: } else {
221: StringBuffer buff = new StringBuffer();
222: boolean done = false;
223: while (m_offset < m_signature.length()) {
224: chr = m_signature.charAt(m_offset++);
225: if (chr == '/') {
226: buff.append('.');
227: } else if (chr == ';') {
228: done = true;
229: break;
230: } else if (chr == '<') {
231: done = true;
232: m_offset--;
233: m_isParameterized = true;
234: break;
235: } else {
236: buff.append(chr);
237: }
238: }
239: if (!done) {
240: throw new IllegalStateException(
241: "Internal error: cannot interpret type");
242: } else {
243: m_type = buff.toString();
244: }
245: }
246: break;
247: }
248:
249: // error if anything else
250:
251: default:
252: throw new IllegalStateException(
253: "Internal error: signature parse state");
254:
255: }
256: }
257: return m_event;
258: }
259: }
|