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;
024:
025: import java.io.Serializable;
026: import java.lang.reflect.InvocationHandler;
027: import java.lang.reflect.Method;
028: import java.lang.reflect.Proxy;
029: import java.sql.ResultSet;
030: import java.sql.SQLException;
031: import java.util.ArrayList;
032: import java.util.Collections;
033: import java.util.HashMap;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Map;
037: import java.util.Map.Entry;
038:
039: import org.w3c.dom.Element;
040:
041: import biz.hammurapi.convert.CompositeConverter;
042:
043: /**
044: * @author Pavel Vlasov
045: * @version $Revision: 1.5 $
046: */
047: public class InterfaceProjector extends BaseReflectionProjector
048: implements Projector {
049: private Class theInterface;
050: private Object delegate;
051:
052: /**
053: * @param typeMap
054: * @param theInterface Iterface projected object should implement.
055: */
056: public InterfaceProjector(Class theInterface, Map typeMap) {
057: super (typeMap);
058: this .theInterface = theInterface;
059: }
060:
061: /**
062: * @param typeMap
063: * @param delegate Object to delegate unmatched calls to.
064: * @param theInterface Iterface projected object should implement.
065: */
066: public InterfaceProjector(Class theInterface, Object delegate,
067: Map typeMap) {
068: super (typeMap);
069: this .theInterface = theInterface;
070: this .delegate = delegate;
071: }
072:
073: private static Map primitivesMap = new HashMap();
074:
075: static {
076: primitivesMap.put(int.class, java.lang.Integer.class);
077: primitivesMap.put(boolean.class, java.lang.Boolean.class);
078: primitivesMap.put(byte.class, java.lang.Byte.class);
079: primitivesMap.put(char.class, java.lang.Character.class);
080: primitivesMap.put(double.class, java.lang.Double.class);
081: primitivesMap.put(float.class, java.lang.Float.class);
082: primitivesMap.put(long.class, java.lang.Long.class);
083: primitivesMap.put(short.class, java.lang.Short.class);
084: }
085:
086: class ResultSetInvocationHandler implements InvocationHandler,
087: Serializable {
088: /**
089: * Comment for <code>serialVersionUID</code>
090: */
091: private static final long serialVersionUID = -971624963614852201L;
092: Map fieldMap;
093:
094: public ResultSetInvocationHandler(Map fieldMap) {
095: this .fieldMap = fieldMap;
096: }
097:
098: public Object invoke(Object proxy, Method method, Object[] args)
099: throws Throwable {
100: if (method.getName().length() > 3) {
101: String key = method.getName().substring(3);
102: if (method.getName().startsWith("get")
103: && method.getParameterTypes().length == 0
104: && fieldMap.containsKey(key)) {
105: Class prt = (Class) primitivesMap.get(method
106: .getReturnType());
107: Object value = fieldMap.get(key);
108: if (value == null) {
109: if (prt == null) {
110: return null;
111: }
112:
113: throw new IllegalArgumentException(
114: "Cannot convert 'null' to "
115: + method.getReturnType());
116: }
117:
118: Object ret = CompositeConverter
119: .getDefaultConverter().convert(value,
120: method.getReturnType(), false);
121: if (ret == null && prt != null) {
122: ret = CompositeConverter.getDefaultConverter()
123: .convert(value, prt, false);
124: }
125:
126: if (ret == null) {
127: throw new IllegalArgumentException(
128: "Cannot convert "
129: + (value == null ? "null"
130: : value.getClass()
131: + " '" + value
132: + "'")
133: + " to "
134: + method.getReturnType()
135: .getName());
136: }
137:
138: return ret;
139: } else if (method.getName().startsWith("set")
140: && method.getParameterTypes().length == 1
141: && fieldMap.containsKey(key)) {
142: fieldMap.put(key, args[0]);
143: return null;
144: }
145: }
146:
147: if ("toString".equals(method.getName())
148: && method.getParameterTypes().length == 0) {
149: StringBuffer ret = new StringBuffer(theInterface
150: .getName());
151: ret.append(" [");
152: List fields = new ArrayList(fieldMap.keySet());
153: Collections.sort(fields);
154: Iterator it = fields.iterator();
155: while (it.hasNext()) {
156: ret.append(" ");
157: String key = (String) it.next();
158: ret.append(key);
159: ret.append(" = ");
160: ret.append(fieldMap.get(key));
161: if (it.hasNext()) {
162: ret.append(";");
163: }
164: }
165: return ret.append(" ]").toString();
166: }
167:
168: if ("toDom".equals(method.getName())
169: && method.getParameterTypes().length == 1
170: && Element.class.isAssignableFrom(method
171: .getParameterTypes()[0])) {
172: Element holder = (Element) args[0];
173: Iterator it = fieldMap.entrySet().iterator();
174: while (it.hasNext()) {
175: Map.Entry entry = (Entry) it.next();
176: Element fieldElement = holder.getOwnerDocument()
177: .createElement((String) entry.getKey());
178: holder.appendChild(fieldElement);
179: if (entry.getValue() != null) {
180: fieldElement.setAttribute("type", entry
181: .getValue().getClass().getName());
182: fieldElement.appendChild(fieldElement
183: .getOwnerDocument().createTextNode(
184: entry.getValue().toString()));
185: }
186: }
187: }
188:
189: return (delegate == null ? fieldMap : delegate).getClass()
190: .getMethod(method.getName(),
191: method.getParameterTypes()).invoke(
192: delegate, args);
193: }
194:
195: }
196:
197: public Object project(ResultSet rs) throws SQLException {
198: final Map fieldMap = new HashMap();
199: for (int i = 1, c = rs.getMetaData().getColumnCount(); i <= c; i++) {
200: fieldMap.put(
201: accessorName(rs.getMetaData().getColumnName(i))
202: .substring(3), rs.getObject(i));
203: }
204:
205: return Proxy.newProxyInstance(theInterface.getClassLoader(),
206: new Class[] { theInterface },
207: new ResultSetInvocationHandler(fieldMap));
208: }
209: }
|