001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.sql.xml;
024:
025: import java.io.ByteArrayInputStream;
026: import java.sql.ResultSet;
027: import java.sql.ResultSetMetaData;
028: import java.sql.SQLException;
029:
030: import javax.xml.transform.TransformerException;
031:
032: import org.apache.xpath.XPathAPI;
033: import org.w3c.dom.DOMException;
034: import org.w3c.dom.Document;
035: import org.w3c.dom.Element;
036: import org.w3c.dom.Node;
037:
038: import biz.hammurapi.CarryOverException;
039: import biz.hammurapi.config.ConfigurationException;
040: import biz.hammurapi.config.Context;
041: import biz.hammurapi.config.DomConfigFactory;
042: import biz.hammurapi.config.PropertyParser;
043: import biz.hammurapi.sql.MetadataAwareRowProcessor;
044: import biz.hammurapi.sql.SQLProcessor;
045:
046: /**
047: * @author Pavel Vlasov
048: * @version $Revision: 1.2 $
049: */
050: public class Select extends SQLCommand implements Command {
051:
052: // private String pageSize;
053: // private String pageNumParameter;
054: private CompositeCommand onRow;
055: private CompositeCommand onEmptySet;
056:
057: public void configure(Node configNode, Context context)
058: throws ConfigurationException {
059: super .configure(configNode, context);
060: Element configElement = (Element) configNode;
061: try {
062: Node n = XPathAPI.selectSingleNode(configNode, "on-row");
063: if (n != null) {
064: onRow = new CompositeCommand();
065: onRow.configure(n, context);
066: }
067:
068: n = XPathAPI.selectSingleNode(configNode,
069: "on-empty-result-set");
070: if (n != null) {
071: onEmptySet = new CompositeCommand();
072: onEmptySet.configure(n, context);
073: }
074: } catch (TransformerException e) {
075: throw new ConfigurationException(e);
076: }
077: }
078:
079: public void execute(final Element holder, SQLProcessor pProcessor,
080: final Context context) throws SQL2XMLException {
081: final SQLProcessor processor = getProcessor() == null ? pProcessor
082: : getProcessor();
083: // TODO Paged processing
084: try {
085: if (parameterizer == null
086: || parameterizer.setContext(context)) {
087: final Document ownerDocument = holder
088: .getOwnerDocument();
089: final Element resultSetElement = ownerDocument
090: .createElement("result-set");
091: holder.appendChild(resultSetElement);
092: if (name != null) {
093: resultSetElement.setAttribute("name", name);
094: }
095:
096: processor.processSelect(sql, parameterizer,
097: new MetadataAwareRowProcessor() {
098: public boolean process(final ResultSet rs)
099: throws SQLException {
100: Element rowElement = ownerDocument
101: .createElement("row");
102: resultSetElement
103: .appendChild(rowElement);
104: for (int i = 1, j = rs.getMetaData()
105: .getColumnCount(); i <= j; i++) {
106: Element columnElement = ownerDocument
107: .createElement("column");
108: rowElement
109: .appendChild(columnElement);
110: columnElement.setAttribute("name",
111: rs.getMetaData()
112: .getColumnName(i));
113: columnElement.setAttribute("type",
114: rs.getMetaData()
115: .getColumnTypeName(
116: i));
117: switch (rs.getMetaData()
118: .isNullable(i)) {
119: case ResultSetMetaData.columnNoNulls:
120: columnElement.setAttribute(
121: "nullable", "no");
122: break;
123: case ResultSetMetaData.columnNullable:
124: columnElement.setAttribute(
125: "nullable", "yes");
126: break;
127: case ResultSetMetaData.columnNullableUnknown:
128: columnElement.setAttribute(
129: "nullable", "unknown");
130: break;
131: }
132: String value = rs.getString(i);
133: if (value != null) {
134: columnElement
135: .appendChild(ownerDocument
136: .createTextNode(value));
137: }
138:
139: }
140:
141: try {
142: if (onRow != null) {
143: onRow.execute(rowElement,
144: processor,
145: new Context() {
146: public Object get(
147: String name) {
148: //System.out.println("Context.get("+name+")");
149: if (Select.this .name != null
150: && name
151: .startsWith(Select.this .name
152: + ".")) {
153: name = name
154: .substring(Select.this .name
155: .length() + 1);
156: return findColumn(name);
157: } else if (name
158: .indexOf('.') != -1) {
159: return context == null ? null
160: : context
161: .get(name);
162: } else {
163: Object ret = findColumn(name);
164: return ret == null ? context == null ? null
165: : context
166: .get(name)
167: : ret;
168: }
169: }
170:
171: /**
172: * @param rs
173: * @param name
174: * @return
175: */
176: private Object findColumn(
177: String name) {
178: try {
179: for (int i = 1; i <= rs
180: .getMetaData()
181: .getColumnCount(); i++) {
182: if (name
183: .equals(rs
184: .getMetaData()
185: .getColumnName(
186: i))) {
187: return rs
188: .getObject(i);
189: }
190: }
191: return null;
192: } catch (SQLException e) {
193: throw new CarryOverException(
194: e);
195: }
196: }
197:
198: });
199: }
200: } catch (SQL2XMLException e) {
201: throw new CarryOverException(e);
202: }
203:
204: return true;
205: }
206:
207: public void processMetadata(
208: ResultSetMetaData metadata)
209: throws DOMException, SQLException {
210: Element metadataElement = ownerDocument
211: .createElement("metadata");
212: resultSetElement
213: .appendChild(metadataElement);
214: for (int i = 1; i <= metadata
215: .getColumnCount(); i++) {
216: Element columnElement = ownerDocument
217: .createElement("column");
218: metadataElement
219: .appendChild(columnElement);
220: columnElement.setAttribute("name",
221: metadata.getColumnName(i));
222: columnElement
223: .setAttribute(
224: "type",
225: metadata
226: .getColumnTypeName(i));
227: }
228: }
229:
230: public void onEmptyResultSet()
231: throws SQLException {
232: try {
233: if (onEmptySet != null) {
234: onEmptySet.execute(holder,
235: processor, context);
236: }
237: } catch (SQL2XMLException e) {
238: throw new CarryOverException(e);
239: }
240: }
241: });
242: }
243: } catch (final SQLException e) {
244: throw new SQL2XMLException(new PropertyParser(
245: new Context() {
246: public Object get(String name) {
247: if ("error.message".equals(name)) {
248: return e.getMessage();
249: } else if ("error.class".equals(name)) {
250: return e.getClass().getName();
251: } else {
252: return context.get(name);
253: }
254: }
255: }, false).parse(errorMessage), e);
256: } catch (final CarryOverException e) {
257: if (e.getCause() instanceof SQL2XMLException) {
258: throw (SQL2XMLException) e.getCause();
259: } else {
260: throw new SQL2XMLException(new PropertyParser(
261: new Context() {
262: public Object get(String name) {
263: if ("error.message".equals(name)) {
264: return e.getCause().getMessage();
265: } else if ("error.class".equals(name)) {
266: return e.getCause().getClass()
267: .getName();
268: } else {
269: return context.get(name);
270: }
271: }
272: }, false).parse(errorMessage), e.getCause());
273: }
274: }
275: }
276:
277: public static void main(String[] args) throws Exception {
278: DomConfigFactory factory = new DomConfigFactory();
279: String xml = "<query type=\"biz.hammurapi.sql.xml.Select\">"
280: + "<sql>select * from people where last_name=?[lastName]?</sql>"
281: + "</query>";
282: Command select = (Command) factory.create(
283: new ByteArrayInputStream(xml.getBytes()), "/query");
284:
285: }
286: }
|