You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ek...@apache.org on 2005/05/09 22:18:03 UTC

svn commit: r169351 [6/12] - in /incubator/beehive/trunk/system-controls: ./ ant/ external/ external/commons/ external/ejb/ external/jms/ src/ src/ejb/ src/ejb/org/ src/ejb/org/apache/ src/ejb/org/apache/beehive/ src/ejb/org/apache/beehive/controls/ src/ejb/org/apache/beehive/controls/system/ src/ejb/org/apache/beehive/controls/system/ejb/ src/ejb/schema/ src/jdbc/ src/jdbc/org/ src/jdbc/org/apache/ src/jdbc/org/apache/beehive/ src/jdbc/org/apache/beehive/controls/ src/jdbc/org/apache/beehive/controls/system/ src/jdbc/org/apache/beehive/controls/system/jdbc/ src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ src/jms/ src/jms/org/ src/jms/org/apache/ src/jms/org/apache/beehive/ src/jms/org/apache/beehive/controls/ src/jms/org/apache/beehive/controls/system/ src/jms/org/apache/beehive/controls/system/jms/ src/jms/org/apache/beehive/controls/system/jms/impl/ src/jms/org/apache/beehive/controls/system/jndi/ src/jms/org/apache/beehive/controls/system/jndi/impl/ src/webservice/ src/webservice/org/ src/webservice/org/apache/ src/webservice/org/apache/beehive/ src/webservice/org/apache/beehive/controls/ src/webservice/org/apache/beehive/controls/system/ src/webservice/org/apache/beehive/controls/system/webservice/ src/webservice/org/apache/beehive/controls/system/webservice/generator/ src/webservice/org/apache/beehive/controls/system/webservice/jaxrpc/ src/webservice/org/apache/beehive/controls/system/webservice/utils/ test/ test/ant/ test/conf/ test/src/ test/src/jdbc/ test/src/jdbc/controls/ test/src/jdbc/controls/org/ test/src/jdbc/controls/org/apache/ test/src/jdbc/controls/org/apache/beehive/ test/src/jdbc/controls/org/apache/beehive/controls/ test/src/jdbc/controls/org/apache/beehive/controls/system/ test/src/jdbc/controls/org/apache/beehive/controls/system/jdbc/ test/src/jdbc/controls/org/apache/beehive/controls/system/jdbc/test/ test/src/jdbc/controls/org/apache/beehive/controls/system/jdbc/test/dbconnection/ test/src/jdbc/controls/org/apache/beehive/controls/system/jdbc/test/errors/ test/src/jdbc/controls/org/apache/beehive/controls/system/jdbc/test/results/ test/src/jdbc/controls/schemas/ test/src/jdbc/controls/schemas/badusers/ test/src/jdbc/controls/schemas/users/ test/src/jdbc/jdbc-container/ test/src/jdbc/jdbc-container/application/ test/src/jdbc/jdbc-container/src/ test/src/jdbc/jdbc-container/src/org/ test/src/jdbc/jdbc-container/src/org/apache/ test/src/jdbc/jdbc-container/src/org/apache/beehive/ test/src/jdbc/jdbc-container/src/org/apache/beehive/controls/ test/src/jdbc/jdbc-container/src/org/apache/beehive/controls/system/ test/src/jdbc/jdbc-container/src/org/apache/beehive/controls/system/jdbc/ test/src/jdbc/jdbc-container/src/org/apache/beehive/controls/system/jdbc/containertest/ test/src/jdbc/jdbc-container/webapp/ test/src/jdbc/jdbc-container/webapp/WEB-INF/ test/src/jdbc/jdbc-container/webapp/conf/ test/src/jdbc/jdbc-container/webapp/conf/Catalina/ test/src/jdbc/jdbc-container/webapp/conf/Catalina/localhost/ test/src/jdbc/junitTests/ test/src/jdbc/junitTests/org/ test/src/jdbc/junitTests/org/apache/ test/src/jdbc/junitTests/org/apache/beehive/ test/src/jdbc/junitTests/org/apache/beehive/controls/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/dbconnection/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/errors/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/results/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/sqlparser/ test/src/jdbc/junitTests/org/apache/beehive/controls/system/jdbc/units/utils/

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/RowToXmlObjectMapper.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/RowToXmlObjectMapper.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/RowToXmlObjectMapper.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/RowToXmlObjectMapper.java Mon May  9 13:17:58 2005
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.xmlbeans.SchemaProperty;
+import org.apache.xmlbeans.SchemaType;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.HashMap;
+
+/**
+ * Maps a ResultSet row to an XmlObject.
+ */
+public class RowToXmlObjectMapper extends RowMapper {
+
+    private final int _columnCount;
+    private final SchemaType _schemaType;
+
+    private SetterMethod[] _setterMethods;
+    private final Object[] _args = new Object[1];
+
+    /**
+     * Create a new RowToXmlObjectMapper.
+     *
+     * @param resultSet       ResultSet to map
+     * @param returnTypeClass Class to map to.
+     * @param cal             Calendar instance for date/time mappings.
+     * @throws SQLException on error.
+     */
+    RowToXmlObjectMapper(ResultSet resultSet, Class returnTypeClass, Calendar cal)
+            throws SQLException {
+        super(resultSet, returnTypeClass, cal);
+
+        _columnCount = resultSet.getMetaData().getColumnCount();
+        _schemaType = getSchemaType(_returnTypeClass);
+        _setterMethods = null;
+    }
+
+    /**
+     * map a row from the ResultSet to an XmlObject instance
+     *
+     * @return An XmlObject instance.
+     */
+    public Object mapRowToReturnType() {
+
+        Object resultObject = null;
+        if (_columnCount == 1) {
+
+            final int typeId = _tmf.getTypeId(_returnTypeClass);
+
+            try {
+                if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) {
+                    return extractColumnValue(1, typeId);
+                } else {
+                    // we still might want a single value (i.e. java.util.Date)
+                    Object val = extractColumnValue(1, typeId);
+                    if (_returnTypeClass.isAssignableFrom(val.getClass())) {
+                        return val;
+                    }
+                }
+            } catch (SQLException e) {
+                throw new ControlException(e.getMessage(), e);
+            }
+        }
+
+        if (_setterMethods == null) {
+            try {
+                getResultSetMappings();
+            } catch (SQLException e) {
+                throw new ControlException(e.getMessage(), e);
+            }
+        }
+
+        resultObject = XmlObject.Factory.newInstance(new XmlOptions().setDocumentType(_schemaType));
+
+        for (int i = 1; i < _setterMethods.length; i++) {
+            Method setterMethod = _setterMethods[i].getSetter();
+            Object resultValue = null;
+
+            try {
+                resultValue = extractColumnValue(i, _setterMethods[i].getParameterType());
+
+                // if the setter is for an xmlbean enum type, convert the extracted resultset column
+                // value to the proper xmlbean enum type. All xmlbean enums are derived from the class
+                // StringEnumAbstractBase
+                if (_setterMethods[i].getParameterType() == TypeMappingsFactory.TYPE_XMLBEAN_ENUM) {
+                    Class parameterClass = _setterMethods[i].getParameterClass();
+                    Method m = parameterClass.getMethod("forString", new Class[]{String.class});
+                    resultValue = m.invoke(null, new Object[]{resultValue});
+                }
+
+                _args[0] = resultValue;
+                setterMethod.invoke(resultObject, _args);
+
+                if (_setterMethods[i].getNilable() != null) {
+                    if (_resultSet.wasNull()) {
+                        _setterMethods[i].getNilable().invoke(resultObject, (Object[]) null);
+                    }
+                }
+            } catch (SQLException se) {
+                throw new ControlException(se.getMessage(), se);
+            } catch (IllegalArgumentException iae) {
+                try {
+                    ResultSetMetaData md = _resultSet.getMetaData();
+                    throw new ControlException("The declared Java type for method " + setterMethod.getName()
+                                               + setterMethod.getParameterTypes()[0].toString()
+                                               + " is incompatible with the SQL format of column " + md.getColumnName(i).toString()
+                                               + md.getColumnTypeName(i).toString()
+                                               + " which returns objects of type " + resultValue.getClass().getName());
+                } catch (SQLException e) {
+                    throw new ControlException(e.getMessage(), e);
+                }
+            } catch (IllegalAccessException e) {
+                throw new ControlException("IllegalAccessException when trying to access method " + setterMethod.getName(), e);
+            } catch (NoSuchMethodException e) {
+                throw new ControlException("NoSuchMethodException when trying to map schema enum value using Enum.forString().", e);
+            } catch (InvocationTargetException e) {
+                throw new ControlException("IllegalInvocationException when trying to access method " + setterMethod.getName(), e);
+            }
+        }
+        return resultObject;
+    }
+
+
+// ///////////////////////////////////////////////// private methods /////////////////////////////////////////////////
+
+    /**
+     * Build the necessary structures to do the mapping
+     *
+     * @throws SQLException
+     */
+    private void getResultSetMappings() throws SQLException {
+
+        //
+        // special case for XmlObject, find factory class
+        //
+        if (_schemaType.isDocumentType()) {
+            return;
+        }
+
+        final String[] keys = getKeysFromResultSet();
+
+        //
+        // find setters for return class
+        //
+        HashMap<String, Method> mapFields = new HashMap<String, Method>(_columnCount * 2);
+        for (int i = 1; i <= _columnCount; i++) {
+            mapFields.put(keys[i], null);
+        }
+
+        // public methods
+        Method[] classMethods = _returnTypeClass.getMethods();
+        for (Method method : classMethods) {
+
+            if (isSetterMethod(method)) {
+                final String fieldName = method.getName().substring(3).toUpperCase();
+                if (mapFields.containsKey(fieldName)) {
+                    mapFields.put(fieldName, method);
+                }
+            }
+        }
+
+        // finally actually init the fields array
+        _setterMethods = new SetterMethod[_columnCount + 1];
+
+        for (int i = 1; i < _setterMethods.length; i++) {
+            Method setterMethod = mapFields.get(keys[i]);
+            if (setterMethod == null) {
+                throw new ControlException("Unable to map the SQL column " + keys[i]
+                                           + " to a field on the " + _returnTypeClass.getName() +
+                                           " class. Mapping is done using a case insensitive comparision of SQL ResultSet "
+                                           + "columns to public setter methods on the return class.");
+            }
+
+            _setterMethods[i] = new SetterMethod(setterMethod);
+        }
+    }
+
+    /**
+     * Build a String array of column names from the ResultSet.
+     *
+     * @return A String array containing the column names contained within the ResultSet.
+     * @throws SQLException on error
+     */
+    protected String[] getKeysFromResultSet()
+            throws SQLException {
+
+        String[] keys = super.getKeysFromResultSet();
+
+        // check schemaProperty mapping names for more accurate column->field mapping
+        SchemaProperty[] props = _schemaType.getElementProperties();
+        for (int i = 0; i < props.length; i++) {
+
+            int col = -1;
+            try {
+                col = _resultSet.findColumn(props[i].getName().getLocalPart());
+            } catch (SQLException x) {
+            }
+
+            if (col > 0) {
+                keys[col] = props[i].getJavaPropertyName().toUpperCase();
+            }
+        }
+        return keys;
+    }
+
+    /**
+     * Get the SchemaType for the specified class.
+     *
+     * @param returnType Class to get the SchemaType for.
+     * @return SchemaType
+     */
+    private SchemaType getSchemaType(Class returnType) {
+        SchemaType schemaType = null;
+        if (XmlObject.class.isAssignableFrom(returnType)) {
+            try {
+                Field f = returnType.getField("type");
+                if (SchemaType.class.isAssignableFrom(f.getType()) && Modifier.isStatic(f.getModifiers())) {
+                    schemaType = (SchemaType) f.get(null);
+                }
+            } catch (NoSuchFieldException x) {
+            } catch (IllegalAccessException x) {
+            }
+        }
+        return schemaType;
+    }
+
+    // /////////////////////////////////////////////INNER CLASSES/////////////////////////////////////////////////
+
+    /**
+     * Helper class which contains setter method information.
+     */
+    private final class SetterMethod {
+        private final Method _setter;
+        private final int _parameterType;
+        private final Class _parameterClass;
+        private final Method _nilable;
+
+        /**
+         * Create a new setter method.
+         *
+         * @param setter Method instance.
+         */
+        SetterMethod(Method setter) {
+            _setter = setter;
+            _parameterClass = _setter.getParameterTypes()[0];
+            _parameterType = _tmf.getTypeId(_parameterClass);
+            _nilable = isNilable();
+        }
+
+        /**
+         * Return the setter method.
+         *
+         * @return Method
+         */
+        Method getSetter() { return _setter; }
+
+        /**
+         * Return the class of the setter method's paramater.
+         *
+         * @return Class of the setter method's param.
+         */
+        Class getParameterClass() { return _parameterClass; }
+
+        /**
+         * Get the type of the methods paramter.
+         * Type is defined by the TypeMappingsFactory, prefixed by TYPE_.
+         *
+         * @return int type.
+         */
+        int getParameterType() { return _parameterType; }
+
+        /**
+         * Get the nilable method for this setter.
+         *
+         * @return Method.
+         */
+        Method getNilable() { return _nilable; }
+
+        /**
+         * This takes care of the special case for xml beans return types.
+         * since they return primitive types even if they are nillable, we
+         * must explicitly call setNil after getting the column out of the resultSet.
+         * for that, we need to keep track of each field's setNil method.
+         * if the field is not nillable, it will not have a setNil method, and
+         * that array index will be null.
+         *
+         * @return Method
+         */
+        private Method isNilable() {
+            try {
+                return _returnTypeClass.getMethod("setNil" + _setter.getName().substring(3), new Class[]{});
+            } catch (NoSuchMethodException e) {
+                // NOOP - just means there is no setNil
+            }
+            return null;
+        }
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/TypeMappingsFactory.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/TypeMappingsFactory.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/TypeMappingsFactory.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/TypeMappingsFactory.java Mon May  9 13:17:58 2005
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc;
+
+import org.apache.beehive.controls.api.ControlException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Types;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Currently contains all types of type mappings. Implemented using singleton pattern.
+ */
+//@todo: refactor!
+public final class TypeMappingsFactory {
+
+
+    private static TypeMappingsFactory _instance;
+
+    /**
+     * Get an instance of this class.
+     * @return TypeMappingsFactory instance.
+     */
+    public static TypeMappingsFactory getInstance() {
+        if (_instance == null) {
+            _instance = new TypeMappingsFactory();
+        }
+        return _instance;
+    }
+
+    public static final int TYPE_UNKNOWN = 0;
+    static final int TYPE_BYTE = 1;
+    static final int TYPE_SHORT = 2;
+    static final int TYPE_INT = 3;
+    static final int TYPE_LONG = 4;
+    static final int TYPE_FLOAT = 5;
+    static final int TYPE_DOUBLE = 6;
+    static final int TYPE_BOOLEAN = 7;
+    static final int TYPE_BYTE_OBJ = 8;
+    static final int TYPE_SHORT_OBJ = 9;
+    static final int TYPE_INT_OBJ = 10;
+    static final int TYPE_LONG_OBJ = 11;
+    static final int TYPE_FLOAT_OBJ = 12;
+    static final int TYPE_DOUBLE_OBJ = 13;
+    static final int TYPE_BOOLEAN_OBJ = 14;
+    static final int TYPE_BIG_DECIMAL = 15;
+    static final int TYPE_STRING = 16;
+    static final int TYPE_BYTES = 17;
+    static final int TYPE_SQLDATE = 18;
+    static final int TYPE_TIME = 19;
+    static final int TYPE_TIMESTAMP = 20;
+    static final int TYPE_STREAM = 21;
+    static final int TYPE_READER = 22;
+    static final int TYPE_CLOB = 23;
+    static final int TYPE_BLOB = 24;
+    static final int TYPE_ARRAY = 25;
+    static final int TYPE_REF = 26;
+    static final int TYPE_DATE = 27;
+    static final int TYPE_CALENDAR = 28;
+    static final int TYPE_STRUCT = 29;
+    static final int TYPE_XMLBEAN_ENUM = 30;
+    static final int TYPE_MAX = 31;
+
+    private Map<Class, Object> _primitiveDefaults;
+
+    //
+    // keys in this map are the class of the method's return type,
+    // values are the set of constants defined above all prefixed with
+    // TYPE_
+    //
+    private Map<Class, Integer> _typeMap;
+    private Map<Class, Integer> _typeSqlMap;
+
+    /**
+     * Map a string version of sql type to sql type (java.sql.Types).
+     * example: "INTEGER" maps to java.sql.Types.INTEGER
+     */
+    private Map<String, Integer> _typeSqlNameMap;
+
+    private static Method _methodMapGet;
+
+    /**
+     * Constructor
+     */
+    TypeMappingsFactory() {
+
+        _primitiveDefaults = new HashMap<Class, Object>();
+        _primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
+        _primitiveDefaults.put(Integer.TYPE, new Integer(0));
+        _primitiveDefaults.put(Long.TYPE, new Long(0));
+        _primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0));
+        _primitiveDefaults.put(Short.TYPE, new Short((short) 0));
+        _primitiveDefaults.put(Character.TYPE, new Character('\u0000'));
+        _primitiveDefaults.put(Float.TYPE, new Float(0.0f));
+        _primitiveDefaults.put(Double.TYPE, new Double(0.0d));
+
+        // Class to internal enum
+        _typeMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
+        _typeMap.put(Boolean.TYPE, new Integer(TYPE_BOOLEAN));
+        _typeMap.put(Integer.TYPE, new Integer(TYPE_INT));
+        _typeMap.put(Long.TYPE, new Integer(TYPE_LONG));
+        _typeMap.put(Byte.TYPE, new Integer(TYPE_BYTE));
+        _typeMap.put(Short.TYPE, new Integer(TYPE_SHORT));
+        _typeMap.put(Float.TYPE, new Integer(TYPE_FLOAT));
+        _typeMap.put(Double.TYPE, new Integer(TYPE_DOUBLE));
+        _typeMap.put(Boolean.class, new Integer(TYPE_BOOLEAN_OBJ));
+        _typeMap.put(Integer.class, new Integer(TYPE_INT_OBJ));
+        _typeMap.put(Long.class, new Integer(TYPE_LONG_OBJ));
+        _typeMap.put(Byte.class, new Integer(TYPE_BYTE_OBJ));
+        _typeMap.put(Short.class, new Integer(TYPE_SHORT_OBJ));
+        _typeMap.put(Float.class, new Integer(TYPE_FLOAT_OBJ));
+        _typeMap.put(Double.class, new Integer(TYPE_DOUBLE_OBJ));
+        _typeMap.put(String.class, new Integer(TYPE_STRING));
+        _typeMap.put(java.math.BigDecimal.class, new Integer(TYPE_BIG_DECIMAL));
+        _typeMap.put(byte[].class, new Integer(TYPE_BYTES));
+        _typeMap.put(java.sql.Timestamp.class, new Integer(TYPE_TIMESTAMP));
+        _typeMap.put(java.sql.Time.class, new Integer(TYPE_TIME));
+        _typeMap.put(java.sql.Date.class, new Integer(TYPE_SQLDATE));
+        _typeMap.put(java.sql.Ref.class, new Integer(TYPE_REF));
+        _typeMap.put(java.sql.Blob.class, new Integer(TYPE_BLOB));
+        _typeMap.put(java.sql.Clob.class, new Integer(TYPE_CLOB));
+        _typeMap.put(java.sql.Array.class, new Integer(TYPE_ARRAY));
+        _typeMap.put(java.sql.Struct.class, new Integer(TYPE_STRUCT));
+        _typeMap.put(java.io.Reader.class, new Integer(TYPE_READER));
+        _typeMap.put(java.io.InputStream.class, new Integer(TYPE_STREAM));
+        _typeMap.put(java.util.Date.class, new Integer(TYPE_DATE));
+        _typeMap.put(java.util.Calendar.class, new Integer(TYPE_CALENDAR));
+        _typeMap.put(java.util.GregorianCalendar.class, new Integer(TYPE_CALENDAR));
+        _typeMap.put(org.apache.xmlbeans.StringEnumAbstractBase.class, new Integer(TYPE_XMLBEAN_ENUM));
+
+        // Class to java.sql.Types
+        _typeSqlMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
+        _typeSqlMap.put(Boolean.TYPE, new Integer(Types.BOOLEAN));
+        _typeSqlMap.put(Integer.TYPE, new Integer(Types.INTEGER));
+        _typeSqlMap.put(Long.TYPE, new Integer(Types.BIGINT));
+        _typeSqlMap.put(Byte.TYPE, new Integer(Types.TINYINT));
+        _typeSqlMap.put(Short.TYPE, new Integer(Types.SMALLINT));
+        _typeSqlMap.put(Float.TYPE, new Integer(Types.REAL));
+        _typeSqlMap.put(Double.TYPE, new Integer(Types.DOUBLE));
+        _typeSqlMap.put(Boolean.class, new Integer(Types.BOOLEAN));
+        _typeSqlMap.put(Integer.class, new Integer(Types.INTEGER));
+        _typeSqlMap.put(Long.class, new Integer(Types.BIGINT));
+        _typeSqlMap.put(Byte.class, new Integer(Types.TINYINT));
+        _typeSqlMap.put(Short.class, new Integer(Types.SMALLINT));
+        _typeSqlMap.put(Float.class, new Integer(Types.REAL));
+        _typeSqlMap.put(Double.class, new Integer(Types.DOUBLE));
+        _typeSqlMap.put(String.class, new Integer(Types.VARCHAR));
+        _typeSqlMap.put(java.math.BigDecimal.class, new Integer(Types.DECIMAL));
+        _typeSqlMap.put(byte[].class, new Integer(Types.VARBINARY));
+        _typeSqlMap.put(java.sql.Timestamp.class, new Integer(Types.TIMESTAMP));
+        _typeSqlMap.put(java.sql.Time.class, new Integer(Types.TIME));
+        _typeSqlMap.put(java.sql.Date.class, new Integer(Types.DATE));
+        _typeSqlMap.put(java.sql.Ref.class, new Integer(Types.REF));
+        _typeSqlMap.put(java.sql.Blob.class, new Integer(Types.BLOB));
+        _typeSqlMap.put(java.sql.Clob.class, new Integer(Types.CLOB));
+        _typeSqlMap.put(java.sql.Array.class, new Integer(Types.ARRAY));
+        _typeSqlMap.put(java.sql.Struct.class, new Integer(Types.STRUCT));
+        _typeSqlMap.put(java.util.Date.class, new Integer(Types.TIMESTAMP));
+        _typeSqlMap.put(java.util.Calendar.class, new Integer(Types.TIMESTAMP));
+        _typeSqlMap.put(java.util.GregorianCalendar.class, new Integer(Types.TIMESTAMP));
+        _typeSqlMap.put(org.apache.xmlbeans.StringEnumAbstractBase.class, new Integer(Types.VARCHAR));
+
+        // String to java.sql.Types
+        _typeSqlNameMap = new HashMap<String, Integer>(TYPE_MAX * 2);
+        _typeSqlNameMap.put("BIT", new Integer(Types.BIT));
+        _typeSqlNameMap.put("TINYINT", new Integer(Types.TINYINT));
+        _typeSqlNameMap.put("SMALLINT", new Integer(Types.SMALLINT));
+        _typeSqlNameMap.put("INTEGER", new Integer(Types.INTEGER));
+        _typeSqlNameMap.put("BIGINT", new Integer(Types.BIGINT));
+        _typeSqlNameMap.put("FLOAT", new Integer(Types.REAL));
+        _typeSqlNameMap.put("REAL", new Integer(Types.REAL));
+        _typeSqlNameMap.put("DOUBLE", new Integer(Types.DOUBLE));
+        _typeSqlNameMap.put("NUMERIC", new Integer(Types.NUMERIC));
+        _typeSqlNameMap.put("DECIMAL", new Integer(Types.DECIMAL));
+        _typeSqlNameMap.put("CHAR", new Integer(Types.CHAR));
+        _typeSqlNameMap.put("VARCHAR", new Integer(Types.VARCHAR));
+        _typeSqlNameMap.put("LONGVARCHAR", new Integer(Types.LONGVARCHAR));
+        _typeSqlNameMap.put("DATE", new Integer(Types.DATE));
+        _typeSqlNameMap.put("TIME", new Integer(Types.TIME));
+        _typeSqlNameMap.put("TIMESTAMP", new Integer(Types.TIMESTAMP));
+        _typeSqlNameMap.put("BINARY", new Integer(Types.BINARY));
+        _typeSqlNameMap.put("VARBINARY", new Integer(Types.VARBINARY));
+        _typeSqlNameMap.put("LONGVARBINARY", new Integer(Types.LONGVARBINARY));
+        _typeSqlNameMap.put("NULL", new Integer(Types.NULL));
+        _typeSqlNameMap.put("OTHER", new Integer(Types.OTHER));
+        _typeSqlNameMap.put("JAVA_OBJECT", new Integer(Types.JAVA_OBJECT));
+        _typeSqlNameMap.put("DISTINCT", new Integer(Types.DISTINCT));
+        _typeSqlNameMap.put("STRUCT", new Integer(Types.STRUCT));
+        _typeSqlNameMap.put("ARRAY", new Integer(Types.ARRAY));
+        _typeSqlNameMap.put("BLOB", new Integer(Types.BLOB));
+        _typeSqlNameMap.put("CLOB", new Integer(Types.CLOB));
+        _typeSqlNameMap.put("REF", new Integer(Types.REF));
+        _typeSqlNameMap.put("DATALINK", new Integer(Types.DATALINK));
+        _typeSqlNameMap.put("BOOLEAN", new Integer(Types.BOOLEAN));
+
+        // some JAVA synonyms
+        _typeSqlNameMap.put("BYTE", new Integer(Types.TINYINT));
+        _typeSqlNameMap.put("SHORT", new Integer(Types.SMALLINT));
+        _typeSqlNameMap.put("INT", new Integer(Types.INTEGER));
+        _typeSqlNameMap.put("LONG", new Integer(Types.BIGINT));
+
+        // cache the Map.get method for efficiency
+        try {
+            _methodMapGet = java.util.Map.class.getMethod("get", new Class[]{Object.class});
+        } catch (NoSuchMethodException e) {
+            throw new ControlException("Can not find java.util.Map.get(Object) method");
+        }
+    }
+
+    /**
+     * Convert a type string to its SQL Type int value.
+     * @param type A String containing the SQL type name.
+     * @return The SQL type, TYPE_UNKNOWN if cannot convert.
+     */
+    public int convertStringToSQLType(String type) {
+        if (_typeSqlNameMap.containsKey(type.toUpperCase())) {
+            return _typeSqlNameMap.get(type.toUpperCase());
+        }
+        return TYPE_UNKNOWN;
+    }
+
+    /**
+     * Get the SQL type of a class, start at top level class an check all super classes until match is found.
+     * @param classType Class to get SQL type of.
+     * @return Types.OTHER if cannot find SQL type.
+     */
+    public int getSqlType(Class classType) {
+
+        final Class origType = classType;
+        while (classType != null) {
+            Integer type = _typeSqlMap.get(classType);
+            if (type != null) {
+                return type.intValue();
+            }
+            classType = classType.getSuperclass();
+        }
+
+        //
+        // special check for blobs/clobs they are interfaces not derived from
+        //
+        if (Blob.class.isAssignableFrom(origType)) {
+            return _typeSqlMap.get(Blob.class).intValue();
+        } else if (Clob.class.isAssignableFrom(origType)) {
+            return _typeSqlMap.get(Clob.class).intValue();
+        }
+
+        return Types.OTHER;
+    }
+
+    /**
+     * Get the SQL type for an object.
+     * @param o Object to get SQL type of.
+     * @return SQL type of the object, Types.OTHER if cannot classify.
+     */
+    public int getSqlType(Object o) {
+        if (null == o) {
+            return Types.NULL;
+        }
+        return getSqlType(o.getClass());
+    }
+
+    /**
+     *
+     * @param val
+     * @param args
+     * @return
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public Object lookupType(Object val, Object[] args)
+            throws IllegalAccessException, InvocationTargetException
+    {
+        return _methodMapGet.invoke(val, args);
+    }
+
+    /**
+     * Get the type id (defined by this class) for the given class.
+     * @param classType Class to get type of.
+     * @return Type id of class.
+     */
+    public int getTypeId(Class classType) {
+
+        final Class origType = classType;
+        while (null != classType) {
+            Integer typeObj = (Integer) _typeMap.get(classType);
+            if (null != typeObj) {
+                return typeObj.intValue();
+            }
+            classType = classType.getSuperclass();
+        }
+
+        //
+        // special check for blobs/clobs they are interfaces not derived from
+        //
+        if (Blob.class.isAssignableFrom(origType)) {
+            return _typeMap.get(Blob.class).intValue();
+        } else if (Clob.class.isAssignableFrom(origType)) {
+            return _typeMap.get(Clob.class).intValue();
+        }
+
+        return TYPE_UNKNOWN;
+    }
+
+   /**
+    * Returns a primitive legal value as opposed to null if type is primitive.
+    * @param type type to get null value for.
+    * @return null value for specifed type.
+    */
+   public Object fixNull(Class type) {
+       return type.isPrimitive() ? _primitiveDefaults.get(type) : null;
+   }
+
+   /**
+     * Create an Object array for the given array.
+     *
+     * @param o An array.
+     * @return A new object array.
+     */
+    public static Object[] toObjectArray(Object o) {
+
+        Class clas = o.getClass().getComponentType();
+
+        if (null == clas) return null;
+
+        Object[] arr;
+
+        if (clas == Boolean.TYPE) {
+            boolean[] src = (boolean[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Boolean(src[i]);
+        } else if (clas == Character.TYPE) {
+            char[] src = (char[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Character(src[i]);
+        } else if (clas == Byte.TYPE) {
+            byte[] src = (byte[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Byte(src[i]);
+        } else if (clas == Short.TYPE) {
+            short[] src = (short[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Short(src[i]);
+        } else if (clas == Integer.TYPE) {
+            int[] src = (int[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Integer(src[i]);
+        } else if (clas == Long.TYPE) {
+            long[] src = (long[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Long(src[i]);
+        } else if (clas == Float.TYPE) {
+            float[] src = (float[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Float(src[i]);
+        } else if (clas == Double.TYPE) {
+            double[] src = (double[]) o;
+            arr = new Object[src.length];
+            for (int i = 0; i < src.length; i++)
+                arr[i] = new Double(src[i]);
+        } else {
+            arr = (Object[]) o;
+        }
+        return arr;
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/JdbcFragment.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/JdbcFragment.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/JdbcFragment.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/JdbcFragment.java Mon May  9 13:17:58 2005
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * Represents an SQL escape sequence found in the SQL annotation's statement member. A JdbcFragment may
+ * contain child SqlFragments, typically these fragments consist of LiteralFragments and ReflectionFragments.
+ * Parameter substitutions may occur within the SQL escape delimiters {}.
+ *
+ * Syntactically an SQL escape sequence must match one of the following forms, where <i>_space_</i> is a whitespace character:
+ *
+ * <UL><LI>{call_space_.....}</LI>
+ * <LI>{?=_space_.....}</LI>
+ * <LI>{d_space_.....}</LI>
+ * <LI>{t_space_.....}</LI>
+ * <LI>{ts_space_.....}</LI>
+ * <LI>{fn_space_.....}</LI>
+ * <LI>{escape_space_.....}</LI>
+ * <LI>{oj_space_.....}</LI>
+ */
+public final class JdbcFragment extends SqlFragmentContainer {
+
+    /**
+     * Create a new JdbcFragment
+     */
+    JdbcFragment() {
+        super();
+    }
+
+    /**
+     * Get the prepared statement parameter value(s) contained within this fragment.
+     *
+     * @param context A ControlBeanContext instance.
+     * @param method The annotated method.
+     * @param args The method's arguments.
+     *
+     * @return null if this fragment doesn't contain a parameter value.
+     */
+    Object[] getParameterValues(ControlBeanContext context, Method method, Object[] args) {
+
+        ArrayList<Object> values = new ArrayList<Object>();
+        for (SqlFragment sf : _children) {
+            if (sf.hasParamValue()) {
+                Object[] moreValues = sf.getParameterValues(context, method, args);
+                for (Object o : moreValues) {
+                    values.add(o);
+                }
+            }
+        }
+        return values.toArray();
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/LiteralFragment.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/LiteralFragment.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/LiteralFragment.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/LiteralFragment.java Mon May  9 13:17:58 2005
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * Represents a portion of the SQL annotation's statement member which is not within substitution delimiters.
+ * The parser creates LiteralFragements for portions of the SQL statement which do not require any special processing.
+ */
+public final class LiteralFragment extends SqlFragment {
+
+    private final String _value;
+
+    /**
+     * Create an new LiteralFragment with the specified value.
+     * @param value Value of this fragment.
+     */
+    LiteralFragment(String value) {
+        _value = value;
+    }
+
+    /**
+     * Get the text for a PreparedStatement
+     * @param context A ControlBeanContext instance
+     * @param m The annotated method.
+     * @param args The method's parameters.
+     * @return A String containing the literal value for this fragment.
+     */
+    String getPreparedStatementText(ControlBeanContext context, Method m, Object[] args) {
+       return _value;
+    }
+
+    /**
+     * Required for JUnit testing.
+     * @return The String value of this fragment.
+     */
+    public String toString() {
+        return _value;
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParameterChecker.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParameterChecker.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParameterChecker.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParameterChecker.java Mon May  9 13:17:58 2005
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import com.sun.mirror.declaration.ClassDeclaration;
+import com.sun.mirror.declaration.FieldDeclaration;
+import com.sun.mirror.declaration.MethodDeclaration;
+import com.sun.mirror.declaration.ParameterDeclaration;
+import com.sun.mirror.declaration.TypeDeclaration;
+import com.sun.mirror.type.DeclaredType;
+import com.sun.mirror.type.TypeMirror;
+import com.sun.mirror.util.DeclarationFilter;
+import org.apache.beehive.controls.api.ControlException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * Does compile-time checking of reflection parameteres in the SQL annotations's statement
+ * element vs. method parameters. Invoked by the JdbcControlChecker.
+ */
+public class ParameterChecker {
+
+    /**
+     * Verify that all reflection parameters in the statement element can be mapped to method parameters.
+     *
+     * @param statement The parsed statement element.
+     * @param methodDecl The method declaration which was annotated.
+     */
+    public static void checkReflectionParameters(SqlFragmentContainer statement, MethodDeclaration methodDecl) {
+
+        ArrayList<ParameterDeclaration> params =
+                new ArrayList<ParameterDeclaration>(methodDecl.getParameters());
+        HashMap<String, ParameterDeclaration> paramMap = new HashMap<String, ParameterDeclaration>();
+
+        // don't run these checks if this is a compiled class file (method names replaced with arg0, arg1, etc)
+        if (params.size() > 0 && params.get(0).getSimpleName().equals("arg0")) {
+            return;
+        }
+
+        for (int i = 0; i < params.size(); i++) {
+            paramMap.put(params.get(i).getSimpleName(), params.get(i));
+        }
+
+        doCheck(statement, paramMap, methodDecl);
+    }
+
+    /**
+     * Walk the tree of children of the statement, process all children of type ReflectionFragment.
+     *
+     * @param statement The parsed statement element.
+     * @param paramMap The method parameters, keyed by name.
+     * @param method The method declaration which was annotated.
+     */
+    private static void doCheck(SqlFragmentContainer statement, HashMap<String, ParameterDeclaration> paramMap,
+                         final MethodDeclaration method)
+    {
+
+        SqlFragment[] fragments = statement.getChildren();
+        for (SqlFragment fragment : fragments) {
+
+            // if the fragment is a container check all of its children.
+            if (fragment instanceof SqlFragmentContainer) {
+                doCheck((SqlFragmentContainer) fragment, paramMap, method);
+
+                // reflection fragment - make sure it can be mapped using the method's param values.
+            } else if (fragment instanceof ReflectionFragment) {
+                checkReflectionFragment((ReflectionFragment) fragment, paramMap, method);
+            }
+        }
+    }
+
+    /**
+     * Check the fragment.  Must be able to resolve references like 'foo.bar' -> 'foo' where 'foo' is a method param
+     * of a type which contains a public getter or field named 'getBar()' or 'bar' respectively.
+     *
+     * @param fragment The reflection fragment to check.
+     * @param paramMap The method parameters, keyed by name.
+     * @param method The method declaration which was annotated.
+     */
+    private static void checkReflectionFragment(ReflectionFragment fragment,
+                                                HashMap<String, ParameterDeclaration> paramMap, MethodDeclaration method)
+    {
+
+        final String[] paramNameQualifiers = ((ReflectionFragment) fragment).getParameterNameQualifiers();
+        final String parameterName = ((ReflectionFragment) fragment).getParameterName();
+
+        if (paramMap.containsKey(paramNameQualifiers[0]) == false) {
+            throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
+        }
+
+        ParameterDeclaration tpd = paramMap.get(paramNameQualifiers[0]);
+        TypeMirror type = tpd.getType();
+
+        MethodDeclaration getterMethod = null;
+        FieldDeclaration field = null;
+
+        for (int i = 1; i < paramNameQualifiers.length; i++) {
+
+            getterMethod = null;
+            field = null;
+
+            // loop through superclasses until we find a match or run out of superclasses
+            while (type != null) {
+
+                if (type instanceof DeclaredType == false) {
+                    throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
+                }
+
+                TypeDeclaration td = ((DeclaredType) type).getDeclaration();
+                //
+                // abort if Map!!! No further checking can be done.
+                //
+                if (td.getQualifiedName().equals("java.util.Map")) {
+                    return;
+                }
+
+                Collection<? extends MethodDeclaration> methods =
+                        DeclarationFilter.FILTER_PUBLIC.filter(td.getMethods());
+                for (MethodDeclaration m : methods) {
+                    String upperFirst = paramNameQualifiers[i].substring(0,1).toUpperCase();
+                    if (paramNameQualifiers[i].length() > 1) {
+                        upperFirst = upperFirst + paramNameQualifiers[i].substring(1);
+                    }
+                    if (m.getSimpleName().equals("get" + upperFirst)
+                        || m.getSimpleName().equals("is" + upperFirst)) {
+                        getterMethod = m;
+                    }
+                }
+
+                if (getterMethod == null) {
+                    Collection<FieldDeclaration> fields =
+                            DeclarationFilter.FILTER_PUBLIC.filter(td.getFields());
+                    for (FieldDeclaration fd : fields) {
+                        if (fd.getSimpleName().equals(paramNameQualifiers[i])) {
+                            field = fd;
+                        }
+                    }
+                }
+
+                // try the super-class
+                if (getterMethod == null && field == null) {
+                    if (td instanceof ClassDeclaration) {
+                        type = ((ClassDeclaration) td).getSuperclass();
+                        continue;
+                    }
+                }
+
+                break;
+            } // while
+
+            // found a match, get its type and continue within the for loop
+            if (getterMethod != null) {
+                type = getterMethod.getReturnType();
+            } else if (field != null) {
+                type = field.getType();
+            } else {
+                throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
+            }
+        }
+    }
+
+    /**
+     * build the error message for this module.
+     * 
+     * @param parameterName
+     * @param methodName
+     * @return
+     */
+    private static String buildMessage(String parameterName, String methodName) {
+        StringBuilder message = new StringBuilder();
+        message.append("Unable to map the parameter in SQL statement ");
+        message.append(parameterName);
+        message.append(" to a parameter of the method ");
+        message.append(methodName);
+        message.append(". Mapping is accomplished by matching a method parameter name to ");
+        message.append("a value delimited by '{' and '}' in the statement element.");
+        return message.toString();
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParseException.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParseException.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParseException.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ParseException.java Mon May  9 13:17:58 2005
@@ -0,0 +1,192 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
+package org.apache.beehive.controls.system.jdbc.parser;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.  The boolean
+   * flag "specialConstructor" is also set to true to indicate that
+   * this constructor was used to create this object.
+   * This constructor calls its super class with the empty string
+   * to force the "toString" method of parent class "Throwable" to
+   * print the error message in the form:
+   *     ParseException: <result of getMessage>
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super("");
+    specialConstructor = true;
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+    specialConstructor = false;
+  }
+
+  public ParseException(String message) {
+    super(message);
+    specialConstructor = false;
+  }
+
+  /**
+   * This variable determines which constructor was used to create
+   * this object and thereby affects the semantics of the
+   * "getMessage" method (see below).
+   */
+  protected boolean specialConstructor;
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * This method has the standard behavior when this object has been
+   * created using the standard constructors.  Otherwise, it uses
+   * "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser), then this method is called during the printing
+   * of the final stack trace, and hence the correct error message
+   * gets displayed.
+   */
+  public String getMessage() {
+    if (!specialConstructor) {
+      return super.getMessage();
+    }
+    String expected = "";
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected += tokenImage[expectedTokenSequences[i][j]] + " ";
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected += "...";
+      }
+      expected += eol + "    ";
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += add_escapes(tok.image);
+      tok = tok.next; 
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected;
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+ 
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  protected String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ReflectionFragment.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ReflectionFragment.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ReflectionFragment.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/ReflectionFragment.java Mon May  9 13:17:58 2005
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import org.apache.beehive.controls.api.ControlException;
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+import org.apache.beehive.controls.system.jdbc.TypeMappingsFactory;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Represents a method parameter substitution into the SQL annotation's statement member.  Delimited by '{' and '}'.
+ * Method parameter names must exactly match the name used in the SQL statement in order for the substitution to occur.
+ * <p/>
+ * <pre>
+ * SQL(statement="SELECT * FROM {tableName}")
+ * public void getAll(String tableName) throws SQLException;
+ * </pre>
+ */
+public final class ReflectionFragment extends SqlFragment {
+
+    private static final String PREPARED_STATEMENT_SUB_MARK = "?";
+    private static final Pattern s_parameterNamePattern = Pattern.compile("\\.");
+
+    private final String _parameterName;
+    private final String[] _nameQualifiers;
+    private int _sqlDataType;
+
+    /**
+     * Create a new ReflectionFragment with the specifed method parameter name.
+     *
+     * @param parameterName The name of the parameter whose value should be substituted at this location.
+     */
+    ReflectionFragment(String parameterName) {
+        _parameterName = parameterName;
+        _sqlDataType = TypeMappingsFactory.TYPE_UNKNOWN;
+        _nameQualifiers = s_parameterNamePattern.split(_parameterName);
+    }
+
+    /**
+     * Create a new ReflectionFragment with the specified method parameter name and SQL type.
+     *
+     * @param parameterName The name of the parameter whose value should be substituted at this location.
+     * @param sqlDataType   A String specifing the SQL data type for this parameter.
+     */
+    ReflectionFragment(String parameterName, String sqlDataType) {
+        this(parameterName);
+        if (sqlDataType != null) {
+            _sqlDataType = TypeMappingsFactory.getInstance().convertStringToSQLType(sqlDataType);
+        }
+    }
+
+    /**
+     * Return text generated by this fragment for a PreparedStatement
+     *
+     * @param context A ControlBeanContext instance.
+     * @param m       The annotated method.
+     * @param args    The method's parameters
+     * @return Always returns a PREPARED_STATEMENT_SUB_MARK
+     */
+    String getPreparedStatementText(ControlBeanContext context, Method m, Object[] args) {
+        return PREPARED_STATEMENT_SUB_MARK;
+    }
+
+    /**
+     * Always true for ReflectionFragment.
+     *
+     * @return true
+     */
+    boolean hasParamValue() { return true; }
+
+    /**
+     * Get the parameter name (as specified in the SQL statement).
+     *
+     * @return The parameter name.
+     */
+    String getParameterName() { return _parameterName; }
+
+    /**
+     * Get a copy of the array of parameter name qualifiers.
+     *
+     * @return An array of parameter name qualifiers.
+     */
+    String[] getParameterNameQualifiers() {
+        String[] nameQualifiersCopy = new String[_nameQualifiers.length];
+        System.arraycopy(_nameQualifiers, 0, nameQualifiersCopy, 0, _nameQualifiers.length);
+        return nameQualifiersCopy;
+    }
+
+    /**
+     * Get the SQL data type of this param.
+     *
+     * @return The SQL data type for this param.
+     */
+    int getParamSqlDataType() { return _sqlDataType; }
+
+    /**
+     * For JUnit testing.
+     *
+     * @return The String value of this fragment.
+     */
+    public String toString() { return PREPARED_STATEMENT_SUB_MARK; }
+
+    /**
+     * Get the value of this parameter.
+     *
+     * @param context ControlBeanContext instance to evaluate the parameter's value against.
+     * @param method  Method instance to evaluate against.
+     * @param args    Method argument values
+     * @return All parameter object values contained within this fragment
+     */
+    Object[] getParameterValues(ControlBeanContext context, Method method, Object[] args) {
+
+        Object value = null;
+        try {
+            value = context.getParameterValue(method, _nameQualifiers[0], args);
+        } catch (IllegalArgumentException iae) {
+            throw new ControlException("Invalid argument name in SQL statement: " + _nameQualifiers[0], iae);
+        }
+
+        for (int i = 1; i < _nameQualifiers.length; i++) {
+            // handle maps, properties, and fields...
+            value = extractValue(value, _nameQualifiers[i - 1], _nameQualifiers[i]);
+        }
+        return new Object[]{value};
+    }
+
+    //
+    // /////////////////////////////////////////////// PRIVATE METHODS /////////////////////////////////////////////
+    //
+
+    /**
+     * Get the value from the referenced method parameter using java reflection
+     *
+     * @param aValue
+     * @param aName
+     * @param bName
+     * @return
+     */
+    private Object extractValue(Object aValue, String aName, String bName) {
+
+        Class aClass = aValue.getClass();
+        Object value = null;
+
+        //
+        //  a.isB() or a.getB()
+        //
+        String bNameCapped = Character.toUpperCase(bName.charAt(0)) + bName.substring(1);
+        Method getMethod = null;
+        Class retType = null;
+
+        //
+        // try a.isB() first, if found verify that a.isB() returns a boolean value,
+        // and that there is not also a a.getB() method - if there is except
+        //
+        try {
+
+            getMethod = aClass.getMethod("is" + bNameCapped, (Class[]) null);
+            retType = getMethod.getReturnType();
+            if (!(retType.equals(Boolean.class) ||
+                    retType.equals(Boolean.TYPE))) {
+                // only boolean returns can be isB()
+                getMethod = null;
+            } else {
+                /**
+                 *  make sure ("get" + bNameCapped) does not exist as well
+                 *  see CR216159
+                 */
+                boolean getMethodFound = true;
+                try {
+                    aClass.getMethod("get" + bNameCapped, (Class[])null);
+                } catch (NoSuchMethodException e) {
+                    getMethodFound = false;
+                }
+
+                if (getMethodFound) {
+                    throw new ControlException("Colliding field accsessors in user defined class '"
+                                               + aClass.getName() + "' for field '" + bName
+                                               + "'. Please use is<FieldName> for boolean fields and get<FieldName> name for other datatypes.");
+                }
+            }
+        } catch (NoSuchMethodException e) {
+        }
+
+        //
+        // try a.getB() if a.isB() was not found.
+        //
+        if (getMethod == null) {
+            try {
+                getMethod = aClass.getMethod("get" + bNameCapped, (Class[])null);
+                retType = getMethod.getReturnType();
+            } catch (NoSuchMethodException e) {
+            }
+        }
+
+        if (getMethod != null) {
+            // OK- a.getB()
+            try {
+                value = getMethod.invoke(aValue, (Object[]) null);
+            } catch (IllegalAccessException e) {
+                throw new ControlException("Unable to access public method: " + e.toString());
+            } catch (java.lang.reflect.InvocationTargetException e) {
+                throw new ControlException("Exception thrown when executing : " + getMethod.getName() + "() to use as parameter");
+            }
+            return value;
+        }
+
+        //
+        // try a.b
+        //
+
+        try {
+            value = aClass.getField(bName).get(aValue);
+            return value;
+        } catch (NoSuchFieldException e) {
+        } catch (IllegalAccessException e) {
+        }
+
+        //
+        // try a.get(b)
+        //
+
+        if (aValue instanceof Map) {
+            try {
+                value = TypeMappingsFactory.getInstance().lookupType(aValue, new Object[]{bName});
+                return value;
+            } catch (Exception mapex) {
+                throw new ControlException("Exception thrown when executing Map.get() to resolve parameter" + mapex.toString());
+            }
+        }
+
+        // no other options...
+        if (true) {
+            throw new ControlException("Illegal argument in SQL statement: " + _parameterName.toString()
+                                       + "; unable to find suitable method of retrieving property " + bName.toString()
+                                       + " out of object " + aName.toString() + ".");
+        }
+        return null;
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SimpleCharStream.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SimpleCharStream.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SimpleCharStream.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SimpleCharStream.java Mon May  9 13:17:58 2005
@@ -0,0 +1,401 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 3.0 */
+package org.apache.beehive.controls.system.jdbc.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+  public int bufpos = -1;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+     char[] newbuffer = new char[bufsize + 2048];
+     int newbufline[] = new int[bufsize + 2048];
+     int newbufcolumn[] = new int[bufsize + 2048];
+
+     try
+     {
+        if (wrapAround)
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           System.arraycopy(buffer, 0, newbuffer,
+                                             bufsize - tokenBegin, bufpos);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+           bufcolumn = newbufcolumn;
+
+           maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+        }
+        else
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           bufcolumn = newbufcolumn;
+
+           maxNextCharInd = (bufpos -= tokenBegin);
+        }
+     }
+     catch (Throwable t)
+     {
+        throw new Error(t.getMessage());
+     }
+
+
+     bufsize += 2048;
+     available = bufsize;
+     tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+     if (maxNextCharInd == available)
+     {
+        if (available == bufsize)
+        {
+           if (tokenBegin > 2048)
+           {
+              bufpos = maxNextCharInd = 0;
+              available = tokenBegin;
+           }
+           else if (tokenBegin < 0)
+              bufpos = maxNextCharInd = 0;
+           else
+              ExpandBuff(false);
+        }
+        else if (available > tokenBegin)
+           available = bufsize;
+        else if ((tokenBegin - available) < 2048)
+           ExpandBuff(true);
+        else
+           available = tokenBegin;
+     }
+
+     int i;
+     try {
+        if ((i = inputStream.read(buffer, maxNextCharInd,
+                                    available - maxNextCharInd)) == -1)
+        {
+           inputStream.close();
+           throw new java.io.IOException();
+        }
+        else
+           maxNextCharInd += i;
+        return;
+     }
+     catch(java.io.IOException e) {
+        --bufpos;
+        backup(0);
+        if (tokenBegin == -1)
+           tokenBegin = bufpos;
+        throw e;
+     }
+  }
+
+  public char BeginToken() throws java.io.IOException
+  {
+     tokenBegin = -1;
+     char c = readChar();
+     tokenBegin = bufpos;
+
+     return c;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+     column++;
+
+     if (prevCharIsLF)
+     {
+        prevCharIsLF = false;
+        line += (column = 1);
+     }
+     else if (prevCharIsCR)
+     {
+        prevCharIsCR = false;
+        if (c == '\n')
+        {
+           prevCharIsLF = true;
+        }
+        else
+           line += (column = 1);
+     }
+
+     switch (c)
+     {
+        case '\r' :
+           prevCharIsCR = true;
+           break;
+        case '\n' :
+           prevCharIsLF = true;
+           break;
+        case '\t' :
+           column--;
+           column += (8 - (column & 07));
+           break;
+        default :
+           break;
+     }
+
+     bufline[bufpos] = line;
+     bufcolumn[bufpos] = column;
+  }
+
+  public char readChar() throws java.io.IOException
+  {
+     if (inBuf > 0)
+     {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        return buffer[bufpos];
+     }
+
+     if (++bufpos >= maxNextCharInd)
+        FillBuff();
+
+     char c = buffer[bufpos];
+
+     UpdateLineColumn(c);
+     return (c);
+  }
+
+  /**
+   * @deprecated 
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  /**
+   * @deprecated 
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+     return bufline[bufpos];
+  }
+
+  public int getEndColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  public int getBeginColumn() {
+     return bufcolumn[tokenBegin];
+  }
+
+  public int getBeginLine() {
+     return bufline[tokenBegin];
+  }
+
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+       bufpos += bufsize;
+  }
+
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                                                           int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public SimpleCharStream(java.io.Reader dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+  public void ReInit(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  public void ReInit(java.io.Reader dstream, int startline,
+                                                           int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  public void ReInit(java.io.Reader dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+     this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+
+  public void ReInit(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize)
+  {
+     ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+  public void ReInit(java.io.InputStream dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public void ReInit(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+  public String GetImage()
+  {
+     if (bufpos >= tokenBegin)
+        return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+     else
+        return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                              new String(buffer, 0, bufpos + 1);
+  }
+
+  public char[] GetSuffix(int len)
+  {
+     char[] ret = new char[len];
+
+     if ((bufpos + 1) >= len)
+        System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+     else
+     {
+        System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                          len - bufpos - 1);
+        System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+     }
+
+     return ret;
+  }
+
+  public void Done()
+  {
+     buffer = null;
+     bufline = null;
+     bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+     int start = tokenBegin;
+     int len;
+
+     if (bufpos >= tokenBegin)
+     {
+        len = bufpos - tokenBegin + inBuf + 1;
+     }
+     else
+     {
+        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+     }
+
+     int i = 0, j = 0, k = 0;
+     int nextColDiff = 0, columnDiff = 0;
+
+     while (i < len &&
+            bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+     {
+        bufline[j] = newLine;
+        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+        bufcolumn[j] = newCol + columnDiff;
+        columnDiff = nextColDiff;
+        i++;
+     } 
+
+     if (i < len)
+     {
+        bufline[j] = newLine++;
+        bufcolumn[j] = newCol + columnDiff;
+
+        while (i++ < len)
+        {
+           if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+              bufline[j] = newLine++;
+           else
+              bufline[j] = newLine;
+        }
+     }
+
+     line = bufline[j];
+     column = bufcolumn[j];
+  }
+
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragment.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragment.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragment.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragment.java Mon May  9 13:17:58 2005
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+import org.apache.beehive.controls.system.jdbc.TypeMappingsFactory;
+
+import java.lang.reflect.Method;
+
+/**
+ * The abstract base class for fragments generated during parsing.
+ */
+public abstract class SqlFragment {
+
+    /**
+     * True if this fragment shouldn't be cached since the prepared statement may change on each invocation.
+     * @return true if this fragment shouldn't be cached by the parser
+     */ 
+    boolean isDynamicFragment() {
+        return false;
+    }
+
+    /**
+     * Does this fragment contain a parameter value for a prepared statement
+     * @return true if this fragement doesn't contain a prepared statement value.
+     */
+    boolean hasParamValue() {
+        return false;
+    }
+
+    /**
+     * Get the SQL data type for the parameter value contained within this fragment.
+     * @return The SQL data type for this fragment.
+     */
+    int getParamSqlDataType() {
+        return TypeMappingsFactory.TYPE_UNKNOWN;
+    }
+
+    /**
+     * Get the prepared statement parameter value contained within this fragment.
+     *
+     * @param context A ControlBeanContext instance
+     * @param method The annotated method
+     * @param args The method's parameters
+     * @return null if this fragment doesn't contain a parameter value.
+     */
+    Object[] getParameterValues(ControlBeanContext context, Method method, Object[] args)  {
+        return null;
+    }
+
+    /**
+     * Get the text for a prepared statement generated by this fragment.
+     * @param context A ControlBeanContext instance
+     * @param method The annotated method
+     * @param args The method's parameters
+     * @return A String containing the prepared statement text generated by this fragment
+     */
+    abstract String getPreparedStatementText(ControlBeanContext context, Method method, Object[] args);
+
+    /**
+     * Must be implemented for JUnit testing.
+     * @return The String value of this fragment.
+     */
+    public String toString() {
+        assert false : "Classes which extend SqlFragment must implement toString()";
+        return null;
+    }
+}

Added: incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragmentContainer.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragmentContainer.java?rev=169351&view=auto
==============================================================================
--- incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragmentContainer.java (added)
+++ incubator/beehive/trunk/system-controls/src/jdbc/org/apache/beehive/controls/system/jdbc/parser/SqlFragmentContainer.java Mon May  9 13:17:58 2005
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+
+package org.apache.beehive.controls.system.jdbc.parser;
+
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * The abstract base class for fragment's which may contain child fragments.
+ */
+public abstract class SqlFragmentContainer extends SqlFragment {
+
+    /** Child fragments of this container. */
+    protected ArrayList<SqlFragment> _children;
+
+    /**
+     * Construct a new SqlFragmentContainer instance.
+     */
+    SqlFragmentContainer() {
+        _children = new ArrayList<SqlFragment>();
+    }
+
+    /**
+     * Does this fragment contain a parameter value for a prepared statement?
+     * @return true If this fragment contains a parameter value for a PreparedStatement.
+     */
+    boolean hasParamValue() {
+        for (SqlFragment f : _children) {
+            if (f.hasParamValue()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Add a child.
+     * @param child Child to add.
+     */
+    void addChild(SqlFragment child) {
+        _children.add(child);
+    }
+
+    /**
+     * Return the array of children.
+     * @return An array of SqlFragments.
+     */
+    SqlFragment[] getChildren() {
+        SqlFragment[] fragments = new SqlFragment[_children.size()];
+        return _children.toArray(fragments);
+    }
+
+    /**
+     * Must be implemented for JUnit testing.
+     * @return The String value of this fragment and all of its child fragments.
+     */
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        for (SqlFragment f : _children) {
+            s.append(f.toString());
+        }
+        return s.toString();
+    }
+
+    /**
+     * builds the text of the prepared statement
+     *
+     * @param context A ControlBeanContext instance.
+     * @param m The annotated method.
+     * @param args The method's parameters.
+     * @return The PreparedStatement text generated by this fragment and its children.
+     */
+    String getPreparedStatementText(ControlBeanContext context, Method m, Object[] args) {
+        StringBuilder sb = new StringBuilder();
+        for (SqlFragment sf : _children) {
+            sb.append(sf.getPreparedStatementText(context, m, args));
+        }
+        return sb.toString();
+    }
+}