OSDN Git Service

"https://svn.sourceforge.jp/svnroot/ea2ddl" にプロジェクト "ea2ddl-dao" を共用
[ea2ddl/ea2ddl.git] / ea2ddl-dao / src / main / java / jp / sourceforge / ea2ddl / dao / allcommon / s2dao / internal / various / InternalProcedureMetaDataFactory.java
1 package jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various;\r
2 \r
3 import java.lang.reflect.Field;\r
4 import java.lang.reflect.Modifier;\r
5 import java.util.Collection;\r
6 import java.util.List;\r
7 import java.util.Map;\r
8 import java.util.Stack;\r
9 \r
10 import org.seasar.framework.beans.BeanDesc;\r
11 import org.seasar.framework.beans.factory.BeanDescFactory;\r
12 import org.seasar.extension.jdbc.ValueType;\r
13 import org.seasar.extension.jdbc.types.ValueTypes;\r
14 import org.seasar.dao.ValueTypeFactory;\r
15 import org.seasar.dao.util.TypeUtil;\r
16 \r
17 import jp.sourceforge.ea2ddl.dao.allcommon.cbean.ConditionBeanContext;\r
18 \r
19 /**\r
20  * @author DBFlute(AutoGenerator)\r
21  */\r
22 public class InternalProcedureMetaDataFactory {\r
23 \r
24         // ===================================================================================\r
25     //                                                                           Attribute\r
26     //                                                                           =========\r
27     protected ValueTypeFactory valueTypeFactory;\r
28     protected InternalFieldProcedureAnnotationReader annotationReader = new InternalFieldProcedureAnnotationReader();\r
29         \r
30         // ===================================================================================\r
31     //                                                                                Main\r
32     //                                                                                ====\r
33     public InternalProcedureMetaData createProcedureMetaData(final String procedureName, final Class<?> pmbType) {\r
34         final InternalProcedureMetaData metaData = new InternalProcedureMetaData(procedureName);\r
35         if (pmbType == null) {\r
36             return metaData;\r
37         } else {\r
38             if (!isDtoType(pmbType)) {\r
39                 throw new IllegalStateException("The pmb type was Not DTO type: " + pmbType.getName());\r
40             }\r
41         }\r
42         final BeanDesc pmbDesc = BeanDescFactory.getBeanDesc(pmbType);\r
43 \r
44         // *Point\r
45         final Stack<Class<?>> stack = new Stack<Class<?>>();\r
46         for (Class<?> clazz = pmbType; clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) {\r
47             stack.push(clazz);\r
48         }\r
49         for ( ; !stack.isEmpty() ;) {\r
50             final Class<?> clazz = stack.pop();\r
51             registerParameterType(metaData, pmbDesc, clazz.getDeclaredFields());\r
52         }\r
53 \r
54         return metaData;\r
55     }\r
56     protected void registerParameterType(InternalProcedureMetaData metaData, BeanDesc pmbDesc, Field[] fields) {\r
57         for (Field field : fields) {\r
58             if (!isInstanceField(field)) {\r
59                 continue;\r
60             }\r
61             final InternalProcedureParameterType ppt = getProcedureParameterType(pmbDesc, field);\r
62             if (ppt == null) {\r
63                 continue;\r
64             }\r
65             metaData.addParameterType(ppt);\r
66         }\r
67     }\r
68     protected InternalProcedureParameterType getProcedureParameterType(final BeanDesc dtoDesc, final Field field) {\r
69         final String procedureParameter = annotationReader.getProcedureParameter(dtoDesc, field);\r
70         if (procedureParameter == null) {\r
71             return null;\r
72         }\r
73         final String type = extractParameterType(procedureParameter);\r
74         field.setAccessible(true);\r
75         final InternalProcedureParameterType ppt = new InternalProcedureParameterType(field);\r
76         if (type.equalsIgnoreCase("in")) {\r
77             ppt.setInType(true);\r
78         } else if (type.equalsIgnoreCase("out")) {\r
79             ppt.setOutType(true);\r
80         } else if (type.equalsIgnoreCase("inout")) {\r
81             ppt.setInType(true);\r
82             ppt.setOutType(true);\r
83         } else if (type.equalsIgnoreCase("return")) {\r
84             ppt.setOutType(true);\r
85             ppt.setReturnType(true);\r
86         } else {\r
87             String msg = "The parameter type should be 'in' or 'out' or 'inout' or 'return':";\r
88             msg = msg + " class=" + field.getDeclaringClass().getSimpleName();\r
89             msg = msg + " field=" + field.getName();\r
90             msg = msg + " parameterType=" + type;\r
91             throw new IllegalStateException(msg);\r
92         }\r
93         final Integer index = extractParameterIndex(procedureParameter, field);\r
94         ppt.setParameterIndex(index);\r
95         final ValueType valueType = getValueType(dtoDesc, field);\r
96         ppt.setValueType(valueType);\r
97         return ppt;\r
98     }\r
99     protected String extractParameterType(String procedureParameter) {\r
100         if (procedureParameter.contains(",")) {\r
101             return procedureParameter.substring(0, procedureParameter.indexOf(",")).trim();\r
102         }\r
103         return procedureParameter.trim();\r
104     }\r
105     protected Integer extractParameterIndex(String procedureParameter, Field field) {\r
106         if (procedureParameter.contains(",")) {\r
107             String tmp = procedureParameter.substring(procedureParameter.indexOf(",") + ",".length()).trim();\r
108             try {\r
109                 return Integer.valueOf(tmp);\r
110             } catch (NumberFormatException e) {\r
111                 String msg = "The parameter index should be number:";\r
112                 msg = msg + " class=" + field.getDeclaringClass().getSimpleName();\r
113                 msg = msg + " field=" + field.getName();\r
114                 msg = msg + " parameterIndex=" + tmp + " procedureParameter=" + procedureParameter;\r
115                 throw new IllegalStateException(msg, e);\r
116             }\r
117         }\r
118         return null;\r
119     }\r
120     protected ValueType getValueType(final BeanDesc dtoDesc, final Field field) {\r
121         final String name = annotationReader.getValueType(dtoDesc, field);\r
122         if (name != null) {\r
123             return valueTypeFactory.getValueTypeByName(name);\r
124         }\r
125         final Class<?> type = field.getType();\r
126         if (List.class.isAssignableFrom(type)) {// is for out parameter cursor.\r
127             if (ConditionBeanContext.isOracle()) {\r
128                 return ValueTypes.ORACLE_RESULT_SET;\r
129             } else if (ConditionBeanContext.isPostgreSql()) {\r
130                 return ValueTypes.POSTGRE_RESULT_SET;\r
131             } else {\r
132                 return ValueTypes.SERIALIZABLE_BYTE_ARRAY;\r
133             }\r
134         }\r
135         return valueTypeFactory.getValueTypeByClass(type);\r
136     }\r
137     protected boolean isInstanceField(final Field field) {\r
138         final int mod = field.getModifiers();\r
139         return !Modifier.isStatic(mod) && !Modifier.isFinal(mod);\r
140     }\r
141     protected boolean isDtoType(final Class<?> clazz) {\r
142         return !TypeUtil.isSimpleType(clazz) && !isContainerType(clazz);\r
143     }\r
144     protected boolean isContainerType(final Class<?> clazz) {\r
145         if (clazz == null) { throw new NullPointerException("clazz"); }\r
146         return Collection.class.isAssignableFrom(clazz) || Map.class.isAssignableFrom(clazz) || clazz.isArray();\r
147     }\r
148     public void setValueTypeFactory(final ValueTypeFactory valueTypeFactory) {\r
149         this.valueTypeFactory = valueTypeFactory;\r
150     }\r
151     \r
152     protected static class InternalFieldProcedureAnnotationReader {\r
153         protected String PROCEDURE_PARAMETER_SUFFIX;\r
154         protected String VALUE_TYPE_SUFFIX;\r
155         public InternalFieldProcedureAnnotationReader() {\r
156             PROCEDURE_PARAMETER_SUFFIX = "_PROCEDURE_PARAMETER";\r
157             VALUE_TYPE_SUFFIX = "_VALUE_TYPE";\r
158         }\r
159         public String getProcedureParameter(BeanDesc dtoDesc, Field field) {\r
160             String fieldName = removeInstanceVariablePrefix(field.getName());// *Point\r
161             String annotationName = fieldName + PROCEDURE_PARAMETER_SUFFIX;\r
162             if (dtoDesc.hasField(annotationName)) {\r
163                 Field f = dtoDesc.getField(annotationName);\r
164                 return (String) getValue(f, null);\r
165             } else {\r
166                 return null;\r
167             }\r
168         }\r
169         public String getValueType(BeanDesc dtoDesc, Field field) {\r
170             String fieldName = removeInstanceVariablePrefix(field.getName());// *Point\r
171             String annotationName = fieldName + VALUE_TYPE_SUFFIX;\r
172             if (dtoDesc.hasField(annotationName)) {\r
173                 Field f = dtoDesc.getField(annotationName);\r
174                 return (String) getValue(f, null);\r
175             } else {\r
176                 return null;\r
177             }\r
178         }\r
179         protected String removeInstanceVariablePrefix(String fieldName) {\r
180             return fieldName.startsWith("_") ? fieldName.substring("_".length()) : fieldName;\r
181         }\r
182         protected Object getValue(Field field, Object target) {\r
183             try {\r
184                 return field.get(target);\r
185             } catch (IllegalAccessException e) {\r
186                 String msg = "The getting of the field threw the exception:";\r
187                 msg = msg + " class=" + field.getDeclaringClass().getSimpleName();\r
188                 msg = msg + " field=" + field.getName();\r
189                 throw new IllegalStateException(msg, e);\r
190             }\r
191         }\r
192     }\r
193 }\r