001: /*
002: * SQLeonardo :: java database frontend
003: * Copyright (C) 2004 nickyb@users.sourceforge.net
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: *
019: */
020:
021: package nickyb.sqleonardo.environment.io;
022:
023: import java.io.BufferedReader;
024: import java.io.BufferedWriter;
025: import java.io.FileReader;
026: import java.io.FileWriter;
027: import java.io.IOException;
028:
029: import nickyb.sqleonardo.common.util.Text;
030: import nickyb.sqleonardo.environment.Application;
031: import nickyb.sqleonardo.querybuilder.QueryModel;
032: import nickyb.sqleonardo.querybuilder.syntax.QueryExpression;
033: import nickyb.sqleonardo.querybuilder.syntax.QuerySpecification;
034: import nickyb.sqleonardo.querybuilder.syntax.QueryTokens;
035: import nickyb.sqleonardo.querybuilder.syntax.SubQuery;
036: import nickyb.sqleonardo.querybuilder.syntax._ReservedWords;
037:
038: public class FileStreamXLQ {
039: // ---------------------------------------------------------------
040: // entry points
041: // ---------------------------------------------------------------
042: public static QueryModel read(String filename) throws IOException,
043: ClassNotFoundException {
044: Reader r = new Reader(filename);
045: return r.getQueryModel();
046: }
047:
048: public static void write(String filename, QueryModel model)
049: throws IOException {
050: new Writer(filename, model);
051: }
052:
053: // ---------------------------------------------------------------
054: // reader class
055: // ---------------------------------------------------------------
056: private static class Reader {
057: private QueryModel model;
058: private BufferedReader in;
059:
060: Reader(String filename) throws IOException,
061: ClassNotFoundException {
062: model = new QueryModel();
063: in = new BufferedReader(new FileReader(filename));
064:
065: in.readLine(); // TAG:SQLEONARDO:OPEN
066: String tag = in.readLine(); // TAG:MODEL:OPEN
067: String schema = getAttribute(tag, "schema");
068: model.setSchema(schema);
069:
070: in.readLine(); // TAG:QUERY:OPEN
071: read(model.getQueryExpression());
072:
073: tag = in.readLine(); // TAG:ORDER_BY:OPEN
074: if (!tag.endsWith("/>")) {
075: /* leggi tokens */
076: while (true) {
077: tag = in.readLine();
078: if (tag.equals("</ORDER_BY>"))
079: break;
080:
081: short t = Short.valueOf(getAttribute(tag, "type"))
082: .shortValue();
083: model.addOrderByClause(new QueryTokens.Sort(
084: (QueryTokens._Expression) getToken(in
085: .readLine()), t));
086:
087: in.readLine(); // TAG:SORT:CLOSE
088: }
089: }
090:
091: in.readLine(); // TAG:MODEL:CLOSE
092: in.readLine();// TAG:SQLEONARDO:CLOSE
093: in.close();
094: }
095:
096: private QueryModel getQueryModel() {
097: return model;
098: }
099:
100: private void read(QueryExpression qe) throws IOException {
101: for (int i = 0; i < 5; i++) {
102: String tag = in.readLine();
103: if (!tag.endsWith("/>")) {
104: switch (i) {
105: case 0:
106: read(qe.getQuerySpecification(),
107: _ReservedWords.SELECT);
108: break;
109: case 1:
110: read(qe.getQuerySpecification(),
111: _ReservedWords.FROM);
112: break;
113: case 2:
114: read(qe.getQuerySpecification(),
115: _ReservedWords.WHERE);
116: break;
117: case 3:
118: read(qe.getQuerySpecification(),
119: _ReservedWords.GROUP_BY.replace(' ',
120: '_'));
121: break;
122: case 4:
123: read(qe.getQuerySpecification(),
124: _ReservedWords.HAVING);
125: break;
126: }
127: }
128: }
129:
130: String tag = in.readLine(); // TAG:QUERY:CLOSE || TAG:QUERY:OPEN -> union
131: if (tag.equals("<QUERY>")) {
132: QueryExpression union = new QueryExpression();
133: qe.setUnion(union);
134:
135: read(union);
136: in.readLine(); // TAG:QUERY:CLOSE
137: }
138: }
139:
140: private void read(QuerySpecification qs, String clause)
141: throws IOException {
142: while (true) {
143: String tag = in.readLine();
144: if (tag.equals("</" + clause + ">"))
145: break;
146:
147: QueryTokens._Base token = getToken(tag);
148: if (clause.equals(_ReservedWords.SELECT))
149: qs.addSelectList((QueryTokens._Expression) token);
150: else if (clause.equals(_ReservedWords.FROM))
151: qs
152: .addFromClause((QueryTokens._TableReference) token);
153: else if (clause.equals(_ReservedWords.WHERE))
154: qs.addWhereClause((QueryTokens.Condition) token);
155: else if (clause.equals(_ReservedWords.GROUP_BY.replace(
156: ' ', '_')))
157: qs.addGroupByClause(new QueryTokens.Group(
158: (QueryTokens._Expression) token));
159: else if (clause.equals(_ReservedWords.HAVING))
160: qs.addHavingClause((QueryTokens.Condition) token);
161: }
162: }
163:
164: private QueryTokens._Base getToken(String tag)
165: throws IOException {
166: if (tag.startsWith("<QUERY")) {
167: SubQuery sq = new SubQuery();
168: read(sq);
169: return sq;
170: }
171:
172: if (tag.startsWith("<EXPRESSION"))
173: return getExpression(tag);
174: if (tag.startsWith("<COLUMN"))
175: return getColumn(tag);
176: if (tag.startsWith("<TABLE"))
177: return getTable(tag);
178: if (tag.startsWith("<CONDITION"))
179: return getCondition(tag);
180: if (tag.startsWith("<JOIN"))
181: return getJoin(tag);
182:
183: return null;
184: }
185:
186: private QueryTokens.DefaultExpression getExpression(String tag) {
187: if (tag.equals("<EXPRESSION/>"))
188: return null;
189: return new QueryTokens.DefaultExpression(getAttribute(tag,
190: "value"));
191: }
192:
193: private QueryTokens.Column getColumn(String tag)
194: throws IOException {
195: QueryTokens.Column token = new QueryTokens.Column(
196: getTable(in.readLine()), getAttribute(tag, "name"));
197: token.setAlias(getAttribute(tag, "alias"));
198:
199: in.readLine(); // TAG:COLUMN:CLOSE
200:
201: return token;
202: }
203:
204: private QueryTokens.Table getTable(String tag) {
205: QueryTokens.Table token = new QueryTokens.Table(
206: getAttribute(tag, "schema"), getAttribute(tag,
207: "name"));
208: token.setAlias(getAttribute(tag, "alias"));
209:
210: return token;
211: }
212:
213: private QueryTokens.Condition getCondition(String tag)
214: throws IOException {
215: in.readLine(); // TAG:LEFT:OPEN
216: QueryTokens._Expression left = (QueryTokens._Expression) getToken(in
217: .readLine());
218: in.readLine(); // TAG:LEFT:CLOSE
219:
220: in.readLine(); // TAG:RIGHT:OPEN
221: QueryTokens._Expression right = (QueryTokens._Expression) getToken(in
222: .readLine());
223: in.readLine(); // TAG:RIGHT:CLOSE
224:
225: QueryTokens.Condition token = new QueryTokens.Condition(
226: getAttribute(tag, "append"), left, getAttribute(
227: tag, "operator"), right);
228: in.readLine(); // TAG:CONDITION:CLOSE
229:
230: return token;
231: }
232:
233: private QueryTokens.Join getJoin(String tag) throws IOException {
234: in.readLine(); // TAG:CONDITION:OPEN
235: QueryTokens.Condition condition = getCondition(tag);
236:
237: int t = Integer.valueOf(getAttribute(tag, "type"))
238: .intValue();
239: QueryTokens.Join token = new QueryTokens.Join(t,
240: (QueryTokens.Column) condition.getLeft(), condition
241: .getOperator(),
242: (QueryTokens.Column) condition.getRight());
243: in.readLine(); // TAG:JOIN:CLOSE
244:
245: return token;
246: }
247: }
248:
249: // ---------------------------------------------------------------
250: // writer class
251: // ---------------------------------------------------------------
252: private static class Writer {
253: private BufferedWriter out;
254:
255: private Writer(String filename, QueryModel model)
256: throws IOException {
257: out = new BufferedWriter(new FileWriter(filename));
258:
259: writeln("<" + Application.PROGRAM.toUpperCase()
260: + toAttribute("version", Application.getVersion())
261: + ">");
262: writeln("<MODEL" + toAttribute("schema", model.getSchema())
263: + ">");
264:
265: write(model.getQueryExpression());
266: write(model.getOrderByClause(), _ReservedWords.ORDER_BY
267: .replace(' ', '_'));
268:
269: writeln("</MODEL>");
270: writeln("</" + Application.PROGRAM.toUpperCase() + ">");
271:
272: out.flush();
273: out.close();
274: }
275:
276: private void write(QueryExpression qe) throws IOException {
277: if (qe == null)
278: return;
279:
280: writeln("<QUERY>");
281:
282: write(qe.getQuerySpecification().getSelectList(),
283: _ReservedWords.SELECT);
284: write(qe.getQuerySpecification().getFromClause(),
285: _ReservedWords.FROM);
286: write(qe.getQuerySpecification().getWhereClause(),
287: _ReservedWords.WHERE);
288: write(qe.getQuerySpecification().getGroupByClause(),
289: _ReservedWords.GROUP_BY.replace(' ', '_'));
290: write(qe.getQuerySpecification().getHavingClause(),
291: _ReservedWords.HAVING);
292: write(qe.getUnion());
293:
294: writeln("</QUERY>");
295: }
296:
297: private void write(Object[] tokens, String tag)
298: throws IOException {
299: if (tokens.length == 0) {
300: writeln("<" + tag + "/>");
301: return;
302: }
303:
304: writeln("<" + tag + ">");
305: for (int i = 0; i < tokens.length; i++) {
306: if (tokens[i] instanceof QueryTokens._Expression)
307: write((QueryTokens._Expression) tokens[i]);
308: else if (tokens[i] instanceof QueryTokens.Join)
309: write((QueryTokens.Join) tokens[i]);
310: else if (tokens[i] instanceof QueryTokens.Sort)
311: write((QueryTokens.Sort) tokens[i]);
312: else if (tokens[i] instanceof QueryTokens.Group)
313: write((QueryTokens.Group) tokens[i]);
314: else if (tokens[i] instanceof QueryTokens.Table)
315: write((QueryTokens.Table) tokens[i]);
316: else if (tokens[i] instanceof QueryTokens.Condition)
317: write((QueryTokens.Condition) tokens[i]);
318: }
319: writeln("</" + tag + ">");
320: }
321:
322: private void write(QueryTokens._Expression token)
323: throws IOException {
324: if (token instanceof SubQuery)
325: write((QueryExpression) token);
326: else if (token instanceof QueryTokens.Column)
327: write((QueryTokens.Column) token);
328: else if (token != null)
329: writeln("<EXPRESSION"
330: + toAttribute("value", token.toString()) + "/>");
331: else
332: writeln("<EXPRESSION/>");
333: }
334:
335: private void write(QueryTokens.Condition token)
336: throws IOException {
337: writeln("<CONDITION"
338: + toAttribute("append", token.getAppend())
339: + toAttribute("operator", token.getOperator())
340: + ">");
341: writeln("<LEFT>");
342: write(token.getLeft());
343: writeln("</LEFT>");
344: writeln("<RIGHT>");
345: write(token.getRight());
346: writeln("</RIGHT>");
347: writeln("</CONDITION>");
348: }
349:
350: private void write(QueryTokens.Join token) throws IOException {
351: writeln("<JOIN"
352: + toAttribute("type", new Integer(token.getType()))
353: + ">");
354: write(token.getCondition());
355: writeln("</JOIN>");
356: }
357:
358: private void write(QueryTokens.Column token) throws IOException {
359: writeln("<COLUMN" + toAttribute("name", token.getName())
360: + toAttribute("alias", token.getAlias()) + ">");
361: write(token.getTable());
362: writeln("</COLUMN>");
363: }
364:
365: private void write(QueryTokens.Table token) throws IOException {
366: writeln("<TABLE" + toAttribute("schema", token.getSchema())
367: + toAttribute("name", token.getName())
368: + toAttribute("alias", token.getAlias()) + "/>");
369: }
370:
371: private void write(QueryTokens.Group token) throws IOException {
372: write(token.getExpression());
373: }
374:
375: private void write(QueryTokens.Sort token) throws IOException {
376: writeln("<SORT"
377: + toAttribute(
378: "type",
379: new Short(
380: token.isAscending() ? QueryTokens.Sort.ASCENDING
381: : QueryTokens.Sort.DESCENDING))
382: + ">");
383: write(token.getExpression());
384: writeln("</SORT>");
385: }
386:
387: private void writeln(String s) throws IOException {
388: out.write(s + '\n');
389: }
390: }
391:
392: // ---------------------------------------------------------------
393: // utils
394: // ---------------------------------------------------------------
395: private static String getAttribute(String t, String a) {
396: a = " " + a + "=\"";
397:
398: int start = t.indexOf(a) + a.length();
399: int end = t.indexOf("\"", start);
400:
401: t = t.substring(start, end);
402: return t.equals("null") ? null : Text.replaceText(t, "'",
403: "'");
404: }
405:
406: private static String toAttribute(String a, Object o) {
407: return " "
408: + a
409: + "=\""
410: + (o == null ? null : Text.replaceText(o.toString(),
411: "'", "'")) + "\"";
412: }
413: }
|