18 package com.mysql.clusterj.core.metadata;
20 import com.mysql.clusterj.core.spi.DomainFieldHandler;
21 import com.mysql.clusterj.core.spi.ValueHandler;
22 import com.mysql.clusterj.ClusterJException;
23 import com.mysql.clusterj.ClusterJFatalInternalException;
24 import com.mysql.clusterj.ClusterJUserException;
25 import com.mysql.clusterj.DynamicObject;
26 import com.mysql.clusterj.ColumnMetadata;
27 import com.mysql.clusterj.DynamicObjectDelegate;
29 import com.mysql.clusterj.annotation.PersistenceCapable;
31 import com.mysql.clusterj.core.CacheManager;
33 import com.mysql.clusterj.core.store.Column;
34 import com.mysql.clusterj.core.store.Index;
35 import com.mysql.clusterj.core.store.Dictionary;
36 import com.mysql.clusterj.core.store.Operation;
40 import java.lang.reflect.Constructor;
41 import java.lang.reflect.InvocationHandler;
42 import java.lang.reflect.InvocationTargetException;
43 import java.lang.reflect.Method;
44 import java.lang.reflect.Proxy;
46 import java.util.ArrayList;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.List;
60 public class DomainTypeHandlerImpl<T>
extends AbstractDomainTypeHandlerImpl<T> {
66 boolean dynamic =
false;
69 private Map<String, Method> unmatchedGetMethods =
new HashMap<String, Method>();
70 private Map<String, Method> unmatchedSetMethods =
new HashMap<String, Method>();
82 protected static final Class<?>[] invocationHandlerClassArray =
83 new Class[]{InvocationHandler.class};
91 @SuppressWarnings(
"unchecked" )
92 public DomainTypeHandlerImpl(Class<T> cls,
Dictionary dictionary) {
94 this.
name = cls.getName();
98 this.tableName = getTableNameForDynamicObject((Class<DynamicObject>)cls);
101 proxyClass = (Class<T>)Proxy.getProxyClass(
102 cls.getClassLoader(),
new Class[]{cls});
103 ctor = getConstructorForInvocationHandler (proxyClass);
105 if (persistenceCapable == null) {
107 "ERR_No_Persistence_Capable_Annotation",
name));
109 this.tableName = persistenceCapable.table();
111 this.
table = getTable(dictionary);
115 if (logger.isDebugEnabled()) logger.debug(
"Found Table for " + tableName);
118 this.primaryKeyColumnNames =
table.getPrimaryKeyColumnNames();
119 this.numberOfIdFields = primaryKeyColumnNames.length;
121 this.idFieldNumbers =
new int[numberOfIdFields];
124 this.partitionKeyColumnNames =
table.getPartitionKeyColumnNames();
125 this.numberOfPartitionKeyColumns = partitionKeyColumnNames.length;
131 Index primaryIndex = dictionary.getIndex(
"PRIMARY$KEY", tableName,
"PRIMARY");
133 new IndexHandlerImpl(
this, dictionary, primaryIndex, primaryKeyColumnNames);
134 indexHandlerImpls.add(primaryIndexHandler);
137 for (
String indexName: indexNames) {
139 String indexAlias = removeUniqueSuffix(indexName);
140 Index index = dictionary.getIndex(indexName, tableName, indexAlias);
143 indexHandlerImpls.add(imd);
148 List<String> fieldNameList =
new ArrayList<String>();
154 String fieldName = domainFieldHandler.getName();
155 fieldNameList.add(fieldName);
156 fieldNameToNumber.put(domainFieldHandler.getName(), domainFieldHandler.getFieldNumber());
157 persistentFieldHandlers.add(domainFieldHandler);
158 if (!storeColumn.isPrimaryKey()) {
159 nonPKFieldHandlers.add(domainFieldHandler);
162 fieldNames = fieldNameList.toArray(
new String[fieldNameList.size()]);
165 List<String> fieldNameList =
new ArrayList<String>();
166 Method[] methods = cls.getMethods();
167 for (Method method: methods) {
169 String methodName = method.getName();
171 Class
type = getType(method);
173 if (methodName.startsWith(
"get")) {
174 Method unmatched = unmatchedSetMethods.get(name);
175 if (unmatched == null) {
177 unmatchedGetMethods.put(name, method);
180 if (getType(unmatched).equals(type)) {
182 unmatchedSetMethods.remove(name);
184 numberOfFields++, name, type, method, unmatched);
187 unmatchedGetMethods.put(name, method);
190 }
else if (methodName.startsWith(
"set")) {
191 Method unmatched = unmatchedGetMethods.get(name);
192 if (unmatched == null) {
194 unmatchedSetMethods.put(name, method);
197 if (getType(unmatched).equals(type)) {
199 unmatchedGetMethods.remove(name);
201 numberOfFields++, name, type, unmatched, method);
204 unmatchedSetMethods.put(name, method);
208 if (domainFieldHandler != null) {
211 String fieldName = domainFieldHandler.getName();
212 fieldNameList.add(fieldName);
213 fieldNameToNumber.put(domainFieldHandler.getName(), domainFieldHandler.getFieldNumber());
215 if (domainFieldHandler.isPersistent()) {
216 persistentFieldHandlers.add(domainFieldHandler);
218 nonPKFieldHandlers.add(domainFieldHandler);
221 if (domainFieldHandler.isPrimitive()) {
222 primitiveFieldHandlers.add(domainFieldHandler);
226 fieldNames = fieldNameList.toArray(
new String[fieldNameList.size()]);
228 if ((!unmatchedGetMethods.isEmpty()) || (!unmatchedSetMethods.isEmpty())) {
230 local.message(
"ERR_Unmatched_Methods",
231 unmatchedGetMethods, unmatchedSetMethods));
238 indexHandler.assertAllColumnsHaveFields();
241 if (logger.isDebugEnabled()) {
242 logger.debug(toString());
243 logger.debug(
"DomainTypeHandlerImpl " +
name +
"Indices " + indexHandlerImpls);
247 protected <O extends DynamicObject>
String getTableNameForDynamicObject(Class<O> cls) {
252 dynamicObject = cls.newInstance();
253 tableName = dynamicObject.table();
254 if (tableName == null && persistenceCapable != null) {
255 tableName = persistenceCapable.
table();
257 }
catch (InstantiationException e) {
258 throw new ClusterJUserException(local.message(
"ERR_Dynamic_Object_Instantiation", cls.getName()), e);
259 }
catch (IllegalAccessException e) {
260 throw new ClusterJUserException(local.message(
"ERR_Dynamic_Object_Illegal_Access", cls.getName()), e);
262 if (tableName == null) {
263 throw new ClusterJUserException(local.message(
"ERR_Dynamic_Object_Null_Table_Name",
276 throws IllegalArgumentException {
278 return (ValueHandler)instance;
280 return (ValueHandler)((DynamicObject)instance).delegate();
282 ValueHandler
handler = (ValueHandler)
283 Proxy.getInvocationHandler(instance);
288 public void objectMarkModified(ValueHandler
handler,
String fieldName) {
289 int fieldNumber = fieldNameToNumber.get(fieldName);
290 handler.markModified(fieldNumber);
293 public Class<T> getProxyClass() {
297 public Class<T> getDomainClass() {
301 public void operationSetValues(Object instance, Operation op) {
302 ValueHandler handler = getValueHandler(instance);
303 for (DomainFieldHandler fmd: persistentFieldHandlers) {
304 fmd.operationSetValue(handler, op);
308 public void objectSetKeys(Object keys, Object instance) {
309 ValueHandler handler = getValueHandler(instance);
310 int size = idFieldHandlers.length;
313 for (DomainFieldHandler fmd: idFieldHandlers) {
314 fmd.objectSetKeyValue(keys, handler);
316 }
else if (keys instanceof java.lang.Object[]) {
317 if (logger.isDetailEnabled()) logger.detail(keys.toString());
319 for (
int i = 0;
i < idFieldHandlers.length; ++
i) {
320 idFieldHandlers[
i].objectSetKeyValue(((Object[])keys)[
i], handler);
324 throw new ClusterJUserException(
325 local.message(
"ERR_Composite_Key_Parameter"));
329 public void objectResetModified(ValueHandler handler) {
330 handler.resetModified();
333 @SuppressWarnings(
"unchecked")
334 public
void objectSetCacheManager(CacheManager cm, Object instance) {
335 InvocationHandlerImpl<T> handler =
336 (InvocationHandlerImpl<T>)getValueHandler(instance);
337 handler.setCacheManager(cm);
340 public T newInstance() {
343 InvocationHandlerImpl<T> handler =
new InvocationHandlerImpl<T>(
this);
345 instance = cls.newInstance();
346 ((DynamicObject)instance).delegate((DynamicObjectDelegate)handler);
348 instance = ctor.newInstance(
new Object[] {handler});
349 handler.setProxy(instance);
352 }
catch (InstantiationException ex) {
353 throw new ClusterJException(
354 local.message(
"ERR_Create_Instance", cls.getName()), ex);
355 }
catch (IllegalAccessException ex) {
356 throw new ClusterJException(
357 local.message(
"ERR_Create_Instance", cls.getName()), ex);
358 }
catch (IllegalArgumentException ex) {
359 throw new ClusterJException(
360 local.message(
"ERR_Create_Instance", cls.getName()), ex);
361 }
catch (InvocationTargetException ex) {
362 throw new ClusterJException(
363 local.message(
"ERR_Create_Instance", cls.getName()), ex);
364 }
catch (SecurityException ex) {
365 throw new ClusterJException(
366 local.message(
"ERR_Create_Instance", cls.getName()), ex);
371 public void initializeNotPersistentFields(InvocationHandlerImpl<T> handler) {
372 for (DomainFieldHandler fmd:primitiveFieldHandlers) {
373 ((AbstractDomainFieldHandlerImpl) fmd).objectSetDefaultValue(handler);
384 String head = methodName.substring(3, 4).toLowerCase();
385 String tail = methodName.substring(4);
389 @SuppressWarnings(
"unchecked" )
390 public T getInstance(ValueHandler handler) {
391 return (T)((InvocationHandlerImpl)handler).getProxy();
394 private Class<?> getType(Method method) {
395 Class<?> result = null;
396 if (method.getName().startsWith(
"get")) {
397 result = method.getReturnType();
398 }
else if (method.getName().startsWith(
"set")) {
399 Class<?>[] types = method.getParameterTypes();
400 if (types.length != 1) {
401 throw new ClusterJUserException(
402 local.message(
"ERR_Set_Method_Parameters",
403 method.getName(), types.length));
407 throw new ClusterJFatalInternalException(
408 local.message(
"ERR_Method_Name", method.getName()));
410 if (result == null) {
411 throw new ClusterJUserException(
412 local.message(
"ERR_Unmatched_Method" + method.getName()));
418 protected Constructor<T> getConstructorForInvocationHandler(
421 return cls.getConstructor(invocationHandlerClassArray);
422 }
catch (NoSuchMethodException ex) {
424 local.message(
"ERR_Get_Constructor", cls), ex);
425 }
catch (SecurityException ex) {
427 local.message(
"ERR_Get_Constructor", cls), ex);
431 public ValueHandler createKeyValueHandler(Object keys) {
434 local.message(
"ERR_Key_Must_Not_Be_Null", getName(),
"unknown"));
436 Object[] keyValues =
new Object[numberOfFields];
438 if (numberOfIdFields == 1) {
439 Class<?> keyType = idFieldHandlers[0].getType();
440 DomainFieldHandler fmd = idFieldHandlers[0];
441 checkKeyType(fmd.getName(), keyType, keys);
442 int keyFieldNumber = fmd.getFieldNumber();
443 keyValues[keyFieldNumber] = keys;
445 if (!(keys.getClass().isArray())) {
447 local.message(
"ERR_Key_Must_Be_An_Object_Array",
450 Object[]keyObjects = (Object[])keys;
451 for (
int i = 0;
i < numberOfIdFields; ++
i) {
452 DomainFieldHandler fmd = idFieldHandlers[
i];
453 int index = fmd.getFieldNumber();
454 Object keyObject = keyObjects[
i];
455 Class<?> keyType = fmd.getType();
456 checkKeyType(fmd.getName(), keyType, keyObject);
457 keyValues[
index] = keyObjects[
i];
460 return new KeyValueHandlerImpl(keyValues);
471 public void checkKeyType(
String name, Class<?> keyType, Object keys)
476 Class<?> valueType = keys.getClass();
477 if (keyType.isAssignableFrom(valueType) ||
478 (keyType ==
int.class && valueType == Integer.class) ||
479 (keyType == Integer.class & valueType ==
int.class) ||
480 (keyType == Long.class & valueType ==
long.class) ||
481 (keyType ==
long.
class & valueType == Long.class)) {
485 local.message(
"ERR_Incorrect_Key_Type",
486 name, valueType.getName(), keyType.getName()));
490 public Class<?> getOidClass() {
496 return persistentFieldHandlers.toArray(result);