1 package org.opensync.engine.server.adapter;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5
6 import org.opensync.engine.server.OpenSyncException;
7 import org.xml.sax.Attributes;
8 import org.xml.sax.ErrorHandler;
9 import org.xml.sax.SAXException;
10 import org.xml.sax.SAXParseException;
11 import org.xml.sax.helpers.AttributesImpl;
12 import org.xml.sax.helpers.DefaultHandler;
13
14 /***
15 * Titre : OpenSync
16 * Description : This class implements a specific parser to read the descriptor
17 * files.
18 * A descriptor file describes a text file containing data to
19 * exchange between sources.
20 */
21
22 class DescriptorParser extends DefaultHandler implements ErrorHandler {
23
24 boolean settings_analyzed = false;
25
26 private static final String CR = "\015";
27 private static final String LF = "\012";
28 private static final String CRLF = "\015\012";
29 private static final String BASE_DOCUMENT_ELEMENT = "DATA";
30 private static final String BASE_ROW_ELEMENT = "ROW";
31 private static final String NULL_STRING = "";
32 private static final String PARSER_ERROR = "PARSER.ERROR";
33 private static final String FATAL = "fatal";
34 private static final String NONFATAL = "nonfatal";
35 private static final String SEVERITY = "severity";
36 private static final String DESCRIPTION = "description";
37 private static final String UNTERMINATED_ROW = "Unterminated row";
38 private static final String OFF_WIDTH_ROW ="Off-width row";
39 private static final String MISSING_LAST_FIELD = "Missing at least the last field";
40 private static final String LINE_NUMBER = "line.number";
41 private static final String CDATA = "CDATA";
42 private static final Attributes EMPTY_ATT_LIST = new AttributesImpl();
43 private boolean offWidthOK = false;
44 private boolean trimFields = true;
45 private String lineBreakMarker = CR;
46 private String documentElementTag = BASE_DOCUMENT_ELEMENT;
47 private String rowElementTag = BASE_ROW_ELEMENT;
48
49 private int startingOffset = -1;
50 private boolean prettyPrint = false;
51
52 private final static int _COLUMNS = 0;
53 private final static int _COLUMN = 1;
54 private final static int _NAME = 2;
55 private final static int _START = 3;
56 private final static int _END = 4;
57 private final static int _WIDTH = 5;
58 private final static int _SETTINGS = 6;
59 private final static int _DOCUMENT_ELEMENT = 7;
60 private final static int _ROW_ELEMENT = 8;
61 private final static int _OFFWIDTHOK = 9;
62 private final static int _TRIMCOLUMNS = 10;
63 private final static int _ON = 11;
64 private final static int _OFF = 12;
65 private final static int _LINEBREAK = 13;
66 private final static int _CR = 14;
67 private final static int _LF = 15;
68 private final static int _CRLF = 16;
69 private final static int _PRETTYPRINT = 17;
70 private final static int _STARTING_OFFSET = 18;
71 private final static int _TYPE = 19;
72 private final static int _DELIMITER = 20;
73 private final static int _SKIPFIRSTLINES = 21;
74 private final static int _SUPPRESSQUOTES = 22;
75
76 private static HashMap tokens = new HashMap();
77
78 static {
79 addToken("column",_COLUMN);
80 addToken("columns",_COLUMNS);
81 addToken("name",_NAME);
82 addToken("start",_START);
83 addToken("end",_END);
84 addToken("width",_WIDTH);
85 addToken("settings",_SETTINGS);
86 addToken("document.element",_DOCUMENT_ELEMENT);
87 addToken("row.element",_ROW_ELEMENT);
88 addToken("off.width.ok",_OFFWIDTHOK);
89 addToken("trim.columns",_TRIMCOLUMNS);
90 addToken("yes",_ON);
91 addToken("on",_ON);
92 addToken("true",_ON);
93 addToken("no",_OFF);
94 addToken("off",_OFF);
95 addToken("false",_OFF);
96 addToken("linebreak",_LINEBREAK);
97 addToken("cr",_CR);
98 addToken("lf",_LF);
99 addToken("crlf",_CRLF);
100 addToken("pretty.print",_PRETTYPRINT);
101 addToken("starting.offset",_STARTING_OFFSET);
102 addToken("type",_TYPE);
103 addToken("delimiter",_DELIMITER);
104 addToken("skipfirstlines",_SKIPFIRSTLINES);
105 addToken("suppressquotes",_SUPPRESSQUOTES);
106 }
107
108 private String type = "";
109 private String suppressquotes = "";
110 private String delimiter = "";
111 private String skipfirstlines = "";
112 private String skiplastlines = "";
113
114 private String off_width_ok="no";
115 private String row_element="ROW";
116 private String document_element="DATA";
117 private String trim_columns="no";
118 private String linebreak="crlf";
119 private String pretty_print="yes";
120 private String starting_offset="0";
121
122 Translator translator;
123
124 /***
125 * @param aTranslator
126 */
127 public DescriptorParser(Translator aTranslator) {
128 translator = aTranslator;
129 }
130
131
132 public void error(SAXParseException exception) throws SAXException {
133 OpenSyncException ex = new OpenSyncException("\r\nError at line "+exception.getLineNumber()+" in the file "+exception.getSystemId()+": "+exception.getLocalizedMessage());
134 throw new SAXException(ex);
135 }
136
137
138 public void fatalError(SAXParseException exception) throws SAXException {
139 throw new SAXException(new OpenSyncException("\r\nFatal error at line "+exception.getLineNumber()+" in the file "+exception.getSystemId()+": "+exception.getLocalizedMessage()));
140 }
141
142 public void warning(SAXParseException exception) throws SAXException {
143 throw new SAXException(new OpenSyncException("\r\nWarning at line "+exception.getLineNumber()+" in the file "+exception.getSystemId()+": "+exception.getLocalizedMessage()));
144 }
145
146
147
148 /****/
149 public void startDocument() {
150
151 translator.nfields = 0;
152 settings_analyzed = false;
153 }
154 /***
155 * @param uri
156 * @param sName
157 * @param qName
158 * @param atts
159 * @exception SAXException
160 */
161 public void startElement(String uri, String sName, String qName, Attributes atts) throws SAXException {
162
163 int currentElement;
164 String eName = sName;
165 if ("".equals(eName)) eName = qName;
166
167 if (eName.equals("settings")) {
168 currentElement = 0;
169 translator.colNames = new ArrayList();
170 translator.fields = new ArrayList();
171 translator.startColumns = new ArrayList();
172 translator.endColumns = new ArrayList();
173
174 if (atts != null) {
175 type = "";
176 suppressquotes = "";
177 delimiter = "";
178 skipfirstlines = "";
179 skiplastlines = "";
180
181 translator.type = atts.getValue("type");
182
183
184 if ( !translator.type.equals("fixed") &&
185 !translator.type.equals("delimited") )
186 throw new SAXException(
187 new OpenSyncException("error.config.adapter.descriptorparser.type", new Object[]{translator.type}));
188
189 translator.delimiter = atts.getValue("delimiter");
190
191
192 translator.append = yesNo(atts.getValue("append"), "append");
193
194 translator.remove_file = yesNo(atts.getValue("remove-file"), "remove-file");
195
196 try {
197 translator.skipfirstlines = Integer.parseInt(atts.getValue("skipfirstlines"));
198
199 } catch (NumberFormatException nfe) {
200 throw new SAXException(
201 new OpenSyncException("error.config.adapter.descriptorparser.skipfirstlines",
202 new Object[]{nfe.getMessage()}));
203 }
204 try {
205 String sSkipLastLines = atts.getValue("skiplastlines");
206
207 if (sSkipLastLines != null
208 && !sSkipLastLines.equals("")){
209 translator.skiplastlines = Integer.parseInt(atts.getValue("skiplastlines"));
210 }
211
212 } catch (NumberFormatException nfe) {
213 throw new SAXException(
214 new OpenSyncException("error.config.adapter.descriptorparser.skiplastlines",
215 new Object[]{nfe.getMessage()}));
216 }
217 translator.suppressquotes = yesNo(atts.getValue("suppressquotes"), "suppressquotes");
218
219
220 translator.offWidthOK = yesNo(atts.getValue("off.width.ok"), "off.width.ok");
221
222 translator.row_element = atts.getValue("row.element");
223
224 translator.document_element = atts.getValue("document.element");
225
226 translator.trim_columns = atts.getValue("trim.columns");
227 translator.trimFields = yesNo(trim_columns, "trim.columns");
228
229 linebreak = atts.getValue("linebreak");
230 switch (getToken(linebreak)) {
231 case _CR:
232 translator.lineBreakMarker = CR;
233 break;
234 case _LF:
235 translator.lineBreakMarker = LF;
236 break;
237 case _CRLF:
238 translator.lineBreakMarker =CRLF;
239 break;
240 }
241
242 translator.pretty_print = yesNo(atts.getValue("pretty.print"), "pretty.print");
243
244 translator.starting_offset = atts.getValue("starting.offset");
245 try {
246 translator.startingOffset = Integer.parseInt(translator.starting_offset);
247
248 } catch (NumberFormatException nfe) {
249 throw new SAXException(
250 new OpenSyncException("error.config.adapter.descriptorparser.starting_offset",
251 new Object[]{nfe.getMessage()}));
252 }
253
254 if (translator.type.equals("fixed")) {
255 if (translator.suppressquotes) System.out.println("attribute suppressquotes must be provided");
256 translator.toCSV = false;
257 } else if (translator.type.equals("delimited")) {
258
259
260 translator.toCSV = true;
261 }
262 }
263 settings_analyzed = true;
264 }
265 if (eName.equals("col")) {
266
267 if (atts != null && settings_analyzed) {
268 translator.colNames.add(new String(atts.getValue("name")));
269
270 if (!translator.toCSV) {
271 translator.startColumns.add(new Integer(atts.getValue("from")));
272 translator.endColumns.add(new Integer(atts.getValue("to")));
273 translator.fields.add(new Field( atts.getValue("name"),
274 Integer.parseInt(atts.getValue("from")),
275 Integer.parseInt(atts.getValue("to"))));
276 } else {
277 translator.startColumns.add(new Integer(0));
278 translator.endColumns.add(new Integer(1));
279 translator.fields.add(new Field( atts.getValue("name"),
280 Integer.parseInt("0"),
281 Integer.parseInt("1")));
282 }
283
284
285
286
287 translator.nfields++;
288 }
289 }
290 }
291
292 /***
293 * @param ch
294 * @param start
295 * @param length
296 * @exception SAXException
297 */
298 public void characters(char ch[], int start, int length) throws SAXException
299 {
300 String s = new String(ch, start, length);
301
302 }
303
304 /***
305 * @param uri
306 * @param name
307 * @param qName
308 */
309 public void endElement(String uri, String name, String qName) {
310
311
312
313
314
315
316 }
317
318 private final boolean yesNo(String value, String attributeName) throws SAXException {
319 int test = getToken(value);
320 if (test == _ON) return true;
321 if (test == _OFF) return false;
322 throw new SAXException(
323 new OpenSyncException("error.config.adapter.descriptorparser.yesNo", new Object[]{attributeName, value}));
324 }
325
326 private static final void addToken(String token, int value) {
327 tokens.put(new String(token), new Integer(value));
328 tokens.put(new String(token.toUpperCase()), new Integer(value));
329 }
330
331 private final int getToken(String s) {
332 Object o = tokens.get(s);
333 return (o != null) ?
334 ((Integer) o).intValue() : -1;
335 }
336 }