001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019:
020: package org.apache.beehive.controls.system.jdbc;
021:
022: import org.apache.beehive.controls.api.ControlException;
023:
024: import java.lang.reflect.Constructor;
025: import java.lang.reflect.InvocationTargetException;
026: import java.sql.ResultSet;
027: import java.util.Calendar;
028: import java.util.HashMap;
029: import java.util.Map;
030:
031: /**
032: * Factory for creating row mappers.
033: * <p/>
034: * Row mapper types supported by this factory include: HashMap, Map, Object, XmlObject. The factory determines the
035: * proper row mapper to use by checking its List of RowMappers against the type of mapping requested. When performing
036: * the lookup, the factory attempts to find the most specific type match. If a match can't be found the most general
037: * type of RowMapper is returned, RowToObjectMapper.
038: */
039: public final class RowMapperFactory {
040:
041: private static final HashMap<Class, Class<? extends RowMapper>> _rowMappings = new HashMap<Class, Class<? extends RowMapper>>();
042:
043: private static Class<? extends RowMapper> DEFAULT_OBJ_ROWMAPPING = RowToObjectMapper.class;
044:
045: private static Class XMLOBJ_CLASS = null;
046: private static Class<? extends RowMapper> DEFAULT_XMLOBJ_ROWMAPPING = null;
047: private final static Class[] _params = { ResultSet.class,
048: Class.class, Calendar.class };
049:
050: static {
051:
052: _rowMappings.put(HashMap.class, RowToHashMapMapper.class);
053: _rowMappings.put(Map.class, RowToMapMapper.class);
054:
055: try {
056: XMLOBJ_CLASS = Class
057: .forName("org.apache.xmlbeans.XmlObject");
058: DEFAULT_XMLOBJ_ROWMAPPING = RowToXmlObjectMapper.class;
059: } catch (ClassNotFoundException e) {
060: // NOOP if apache xml beans not present
061: }
062: }
063:
064: /**
065: * Get a RowMapper instance which knows how to map a ResultSet row to the given return type.
066: *
067: * @param rs The ResultSet to map.
068: * @param returnTypeClass The class to map a ResultSet row to.
069: * @param cal Calendar instance for mapping date/time values.
070: * @return A RowMapper instance.
071: */
072: public static RowMapper getRowMapper(ResultSet rs,
073: Class returnTypeClass, Calendar cal) {
074:
075: Class<? extends RowMapper> rm = _rowMappings
076: .get(returnTypeClass);
077: if (rm != null) {
078: return getMapper(rm, rs, returnTypeClass, cal);
079: }
080:
081: //
082: // if we made it to here, check if the default XMLObject Mapper can be used,
083: // otherwise use the default object mapper
084: //
085: if (XMLOBJ_CLASS != null
086: && XMLOBJ_CLASS.isAssignableFrom(returnTypeClass)) {
087: return getMapper(DEFAULT_XMLOBJ_ROWMAPPING, rs,
088: returnTypeClass, cal);
089: } else {
090: return getMapper(DEFAULT_OBJ_ROWMAPPING, rs,
091: returnTypeClass, cal);
092: }
093: }
094:
095: /**
096: * Add a new row mapper to the list of available row mappers. The getRowMapper method traverses the
097: * list of mappers from beginning to end, checking to see if a mapper can handle the specified
098: * returnTypeClass. There is a default mapper which is used if a match cannot be found in the list.
099: *
100: * @param returnTypeClass Class which this mapper maps a row to.
101: * @param rowMapperClass The row mapper class.
102: */
103: public static void addRowMapping(Class returnTypeClass,
104: Class<? extends RowMapper> rowMapperClass) {
105: _rowMappings.put(returnTypeClass, rowMapperClass);
106: }
107:
108: /**
109: * Replace a row mapping.
110: *
111: * @param returnTypeClass Class which this mapper maps a row to.
112: * @param rowMapperClass The row mapper class.
113: * @return if the mapper was replaced, false mapper for returnTypeClass was not found, no action taken.
114: */
115: public static Class<? extends RowMapper> replaceRowMapping(
116: Class returnTypeClass,
117: Class<? extends RowMapper> rowMapperClass) {
118: return _rowMappings.put(returnTypeClass, rowMapperClass);
119: }
120:
121: /**
122: * remove the row mapping for the specified class type.
123: *
124: * @param returnTypeClass
125: * @return the RowMapper class which was removed, null if returnTypeClass did not match any of the registered
126: * row mappers.
127: */
128: public static Class<? extends RowMapper> removeRowMapping(
129: Class returnTypeClass) {
130: return _rowMappings.remove(returnTypeClass);
131: }
132:
133: /**
134: * Sets the rowmapper for Object.class
135: *
136: * @param rowMapperClass
137: */
138: public static Class<? extends RowMapper> setDefaultRowMapping(
139: Class<? extends RowMapper> rowMapperClass) {
140: Class<? extends RowMapper> ret = DEFAULT_OBJ_ROWMAPPING;
141: DEFAULT_OBJ_ROWMAPPING = rowMapperClass;
142: return ret;
143: }
144:
145: /**
146: * Sets the rowmapper for XmlObject.class
147: *
148: * @param rowMapperClass
149: */
150: public static Class<? extends RowMapper> setDefaultXmlRowMapping(
151: Class mapToClass, Class<? extends RowMapper> rowMapperClass) {
152: Class<? extends RowMapper> ret = DEFAULT_XMLOBJ_ROWMAPPING;
153: DEFAULT_XMLOBJ_ROWMAPPING = rowMapperClass;
154: XMLOBJ_CLASS = mapToClass;
155: return ret;
156: }
157:
158: /**
159: * Create an instance of the RowMapper class.
160: *
161: * @param rowMapper
162: * @param rs ResultSet we are mapping from.
163: * @param returnType Class to map rows to.
164: * @param cal Calendar instance for date/time values.
165: * @return A RowMapper instance.
166: */
167: private static RowMapper getMapper(
168: Class<? extends RowMapper> rowMapper, ResultSet rs,
169: Class returnType, Calendar cal) {
170: Constructor c = null;
171: try {
172: c = rowMapper.getDeclaredConstructor(_params);
173: return (RowMapper) c.newInstance(new Object[] { rs,
174: returnType, cal });
175: } catch (NoSuchMethodException e) {
176: throw new ControlException(
177: "Failure creating new instance of RowMapper, "
178: + e.toString(), e);
179: } catch (InstantiationException e) {
180: throw new ControlException(
181: "Failure creating new instance of RowMapper, "
182: + e.toString(), e);
183: } catch (IllegalAccessException e) {
184: throw new ControlException(
185: "Failure creating new instance of RowMapper, "
186: + e.toString(), e);
187: } catch (InvocationTargetException e) {
188: throw new ControlException(
189: "Failure creating new instance of RowMapper, "
190: + e.getCause().toString(), e);
191: }
192: }
193: }
|