001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: VariableDataScanner.java 3622 2006-12-12 03:04:08Z lzheng $
023: */
024: package com.bostechcorp.cbesb.runtime.parser;
025:
026: import java.io.IOException;
027: import java.io.InputStreamReader;
028: import java.util.Vector;
029:
030: import org.apache.commons.collections.OrderedMap;
031: import org.apache.commons.lang.StringUtils;
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034:
035: import com.bostechcorp.cbesb.common.mdl.IElementDefinition;
036: import com.bostechcorp.cbesb.common.mdl.IVariableFormatDefinition;
037: import com.bostechcorp.cbesb.common.util.ErrorUtil;
038:
039: public class VariableDataScanner {
040:
041: private static final Log logger = LogFactory
042: .getLog(VariableDataScanner.class);
043:
044: private static final int STATE_DATA = 0;
045:
046: private static final int STATE_ESCAPED = 1;
047:
048: private static final int STATE_QUOTED = 2;
049:
050: private static final int STATE_MATCHING_DELIM = 3;
051:
052: private static final int STATE_MATCHING_REPEAT = 4;
053:
054: private static final int STATE_MATCHING_BOTH = 5;
055:
056: private static final int STATE_DONE = 6;
057:
058: private String delimiter;
059:
060: private String repeatDelimiter;
061:
062: private char escapeChar;
063:
064: private char quoteChar;
065:
066: private int tagLength;
067:
068: private String tagDelimiter = null;
069:
070: private int state;
071:
072: private Vector values;
073:
074: private StringBuffer dataBuffer;
075:
076: private StringBuffer matchBuffer;
077:
078: private int matchIndex;
079:
080: public String getDelimiter() {
081: return delimiter;
082: }
083:
084: public void setDelimiter(String delimiter) {
085: this .delimiter = delimiter;
086: }
087:
088: public char getEscapeChar() {
089: return escapeChar;
090: }
091:
092: public void setEscapeChar(char escapeChar) {
093: this .escapeChar = escapeChar;
094: }
095:
096: public char getQuoteChar() {
097: return quoteChar;
098: }
099:
100: public void setQuoteChar(char quoteChar) {
101: this .quoteChar = quoteChar;
102: }
103:
104: public String getRepeatDelimiter() {
105: return repeatDelimiter;
106: }
107:
108: public void setRepeatDelimiter(String repeatDelimiter) {
109: this .repeatDelimiter = repeatDelimiter;
110: }
111:
112: public int getTagLength() {
113: return tagLength;
114: }
115:
116: public void setTagLength(int tagLength) {
117: this .tagLength = tagLength;
118: }
119:
120: public String getTagDelimiter() {
121: return tagDelimiter;
122: }
123:
124: public void setTagDelimiter(String tagDelimiter) {
125: this .tagDelimiter = tagDelimiter;
126: }
127:
128: public void reset(IElementDefinition elemDef) {
129: IVariableFormatDefinition varDef = (IVariableFormatDefinition) elemDef
130: .getFormatDefinition();
131: this .setDelimiter(varDef.getResolvedDelimiter());
132: this .setRepeatDelimiter(varDef.getResolvedRepeatDelimiter());
133: this .setEscapeChar(varDef.getResolvedEscapeChar());
134: this .setQuoteChar(varDef.getResolvedQuoteChar());
135: this .setTagLength(varDef.getResolvedTagLength());
136: this .setTagDelimiter(varDef.getResolvedTagDelimiter());
137:
138: }
139:
140: public boolean preParser(InputStreamReader reader, OrderedMap map,
141: int count) throws ParserException {
142: logger.debug("VariableDataScanner - preParser.");
143: String[] stringArray = this .getNextElement(reader);
144: String tag;
145: String other;
146: for (int i = 0; i < stringArray.length; i++) {
147: if (stringArray[i] == null || stringArray[i].length() == 0) {
148: return false;
149: }
150: if (this .tagDelimiter == null
151: || this .tagDelimiter.equals("")) {
152: if (stringArray[i].length() < this .getTagLength()) {
153: return false;
154: }
155: tag = stringArray[i].substring(0, this .getTagLength());
156: other = stringArray[i].substring(this .getTagLength());
157: OrderedMapKey key = new OrderedMapKey(tag, count);
158: logger.debug("VariableDataScanner - key=" + key
159: + " value=" + other);
160: map.put(key, other);
161: } else {
162: String strs[] = StringUtils.splitPreserveAllTokens(
163: stringArray[i], this .tagDelimiter, 2);
164: if (strs.length < 2) {
165: return false;
166: }
167: OrderedMapKey key = new OrderedMapKey(strs[0], count);
168: if (logger.isDebugEnabled())
169: logger.debug("VariableDataScanner - key=" + key
170: + " value=" + strs[1]);
171: map.put(key, strs[1]);
172: }
173: }
174: return true;
175: }
176:
177: /**
178: * @param reader
179: * @return Value array the content between two deliminater
180: */
181: public String[] getNextElement(InputStreamReader reader)
182: throws ParserException {
183: values = new Vector();
184: dataBuffer = new StringBuffer();
185: matchBuffer = new StringBuffer();
186: state = STATE_DATA;
187: try {
188: int readvalue = reader.read();
189: char currentChar;
190: while (readvalue > -1 && state != STATE_DONE) {
191: currentChar = (char) readvalue;
192: switch (state) {
193: case STATE_DATA:
194: state_data(currentChar);
195: break;
196: case STATE_ESCAPED:
197: state_escaped(currentChar);
198: break;
199: case STATE_QUOTED:
200: state_quoted(currentChar);
201: break;
202: case STATE_MATCHING_DELIM:
203: state_matching_delim(currentChar);
204: break;
205: case STATE_MATCHING_REPEAT:
206: state_matching_repeat(currentChar);
207: break;
208: case STATE_MATCHING_BOTH:
209: state_matching_both(currentChar);
210: break;
211: default:
212: break;
213: }
214: if (state != STATE_DONE)
215: readvalue = reader.read();
216: }
217:
218: // Reached end of input before finding delimiter
219: // return all data that is left
220: if (state != STATE_DONE) {
221: dataBuffer.append(matchBuffer.toString());
222: values.add(dataBuffer.toString());
223: }
224: } catch (IOException ioe) {
225:
226: // ErrorUtil.printError("Exception in getNextElement(): ",ioe);
227: throw new ParserException(
228: "IOException caught in getNextElement() in VariableDataScanner",
229: ioe);
230: }
231:
232: // Convert vector to string array
233: String[] returnValues = new String[values.size()];
234: values.toArray(returnValues);
235:
236: return returnValues;
237: }
238:
239: private void state_data(char c) {
240: // System.out.println(delimiter.length()+" "+delimiter.charAt(0)+" "+c);
241: if (c == escapeChar) {
242: // Found escapeChar
243: state = STATE_ESCAPED;
244: } else if (c == quoteChar) {
245: // Found quoteChar
246: dataBuffer.append(quoteChar);
247: state = STATE_QUOTED;
248: } else if (delimiter.length() == 1 && c == delimiter.charAt(0)) {
249: // Found the entire delimiter
250: values.add(dataBuffer.toString());
251: dataBuffer = new StringBuffer();
252: state = STATE_DONE;
253: } else if (repeatDelimiter != null
254: && repeatDelimiter.length() == 1
255: && c == repeatDelimiter.charAt(0)) {
256: // Found the entire repeat Delimiter
257: // Leave state as STATE_DATA
258: values.add(dataBuffer.toString());
259: dataBuffer = new StringBuffer();
260: } else if (delimiter.length() > 0 && c == delimiter.charAt(0)
261: && repeatDelimiter != null
262: && repeatDelimiter.length() > 0
263: && c == repeatDelimiter.charAt(0)) {
264: // Matched the first char of delimiter and repeat delimiter
265: matchBuffer.append(c);
266: matchIndex = 1;
267: state = STATE_MATCHING_BOTH;
268: } else if (delimiter.length() > 0 && c == delimiter.charAt(0)) {
269: // Matched the first char of delimiter
270: matchBuffer.append(c);
271: matchIndex = 1;
272: state = STATE_MATCHING_DELIM;
273: } else if (repeatDelimiter != null
274: && repeatDelimiter.length() > 0
275: && c == repeatDelimiter.charAt(0)) {
276: // Matched the first char of repeat delimiter
277: matchBuffer.append(c);
278: matchIndex = 1;
279: state = STATE_MATCHING_REPEAT;
280: } else {
281: // Part of data
282: dataBuffer.append(c);
283: }
284: }
285:
286: /**
287: * Appent escaped char to the databuff,reset state to data
288: *
289: * @param c
290: */
291: private void state_escaped(char c) {
292: if ((delimiter != null && delimiter.length() == 1 && c == delimiter
293: .charAt(0))
294: || (repeatDelimiter != null
295: && repeatDelimiter.length() == 1 && c == repeatDelimiter
296: .charAt(0))
297: || (c == escapeChar)
298: || (c == quoteChar)) {
299: dataBuffer.append(c);
300: } else {
301: dataBuffer.append(escapeChar);
302: dataBuffer.append(c);
303:
304: }
305: state = STATE_DATA;
306: }
307:
308: /**
309: * Appent escaped char to the databuff,reset state to data
310: *
311: * @param c
312: */
313: private void state_quoted(char c) {
314: if (c == quoteChar) {
315: if (dataBuffer.length() > 0
316: && dataBuffer.charAt(0) == quoteChar) {
317: dataBuffer = dataBuffer.deleteCharAt(0);
318: }
319:
320: state = STATE_DATA;
321: }
322:
323: else
324: dataBuffer.append(c);
325:
326: }
327:
328: private void state_matching_delim(char c) {
329: char nextDelimChar = delimiter.charAt(matchIndex);
330: if (c == nextDelimChar) {
331: if (matchIndex == delimiter.length() - 1) {
332: // Matched the entire delimiter
333: values.add(dataBuffer.toString());
334: dataBuffer = new StringBuffer();
335: matchBuffer = new StringBuffer();
336: state = STATE_DONE;
337: } else {
338: // Still matching
339: matchBuffer.append(c);
340: matchIndex++;
341: }
342: } else {
343: // No match, append matchBuffer to dataBuffer
344: // and keep looking
345: dataBuffer.append(matchBuffer.toString() + c);
346: matchBuffer = new StringBuffer();
347: state = STATE_DATA;
348: }
349: }
350:
351: private void state_matching_repeat(char c) {
352: char nextDelimChar = repeatDelimiter.charAt(matchIndex);
353: if (c == nextDelimChar) {
354: if (matchIndex == repeatDelimiter.length() - 1) {
355: // Matched the entire delimiter
356: values.add(dataBuffer.toString());
357: dataBuffer = new StringBuffer();
358: matchBuffer = new StringBuffer();
359: state = STATE_DATA;
360: } else {
361: // Still matching
362: matchBuffer.append(c);
363: matchIndex++;
364: }
365: } else {
366: // No match, append matchBuffer to dataBuffer
367: // and keep looking
368: dataBuffer.append(matchBuffer.toString() + c);
369: matchBuffer = new StringBuffer();
370: state = STATE_DATA;
371: }
372: }
373:
374: private void state_matching_both(char c) {
375: char nextDelimChar = delimiter.charAt(matchIndex);
376: char nextRepeatDelimChar = repeatDelimiter.charAt(matchIndex);
377: if (c == nextDelimChar && c == nextRepeatDelimChar) {
378: // Still matches both
379: if (matchIndex == delimiter.length() - 1) {
380: // Matched the entire Delimiter
381: values.add(dataBuffer.toString());
382: dataBuffer = new StringBuffer();
383: matchBuffer = new StringBuffer();
384: state = STATE_DONE;
385: } else if (matchIndex == repeatDelimiter.length() - 1) {
386: // Matched the entire repeat delimiter
387: values.add(dataBuffer.toString());
388: dataBuffer = new StringBuffer();
389: matchBuffer = new StringBuffer();
390: state = STATE_DATA;
391: } else {
392: matchBuffer.append(c);
393: matchIndex++;
394: }
395: } else if (c == nextDelimChar) {
396: // Now only matches Delimiter
397: if (matchIndex == delimiter.length() - 1) {
398: // Matched the entire delimiter
399: values.add(dataBuffer.toString());
400: dataBuffer = new StringBuffer();
401: matchBuffer = new StringBuffer();
402: state = STATE_DONE;
403: } else {
404: // Still matching
405: matchBuffer.append(c);
406: matchIndex++;
407: state = STATE_MATCHING_DELIM;
408: }
409:
410: } else if (c == nextRepeatDelimChar) {
411: // Now only matches repeatDelimiter
412: if (matchIndex == repeatDelimiter.length() - 1) {
413: // Matched the entire delimiter
414: values.add(dataBuffer.toString());
415: dataBuffer = new StringBuffer();
416: matchBuffer = new StringBuffer();
417: state = STATE_DATA;
418: } else {
419: matchBuffer.append(c);
420: matchIndex++;
421: state = STATE_MATCHING_REPEAT;
422: }
423: } else {
424: // Doesn't match either delimiter
425: dataBuffer.append(matchBuffer.toString() + c);
426: matchBuffer = new StringBuffer();
427: state = STATE_DATA;
428: }
429: }
430: }
|