18 package com.mysql.clusterj.openjpa;
 
   20 import com.mysql.clusterj.ClusterJException;
 
   21 import com.mysql.clusterj.ClusterJFatalInternalException;
 
   22 import com.mysql.clusterj.ClusterJUserException;
 
   24 import com.mysql.clusterj.core.metadata.AbstractDomainFieldHandlerImpl;
 
   25 import com.mysql.clusterj.core.query.QueryDomainTypeImpl;
 
   26 import com.mysql.clusterj.core.spi.DomainTypeHandler;
 
   27 import com.mysql.clusterj.core.spi.QueryExecutionContext;
 
   28 import com.mysql.clusterj.core.spi.SessionSPI;
 
   29 import com.mysql.clusterj.core.spi.ValueHandler;
 
   30 import com.mysql.clusterj.core.store.IndexScanOperation;
 
   31 import com.mysql.clusterj.core.store.IndexScanOperation.BoundType;
 
   32 import com.mysql.clusterj.core.store.Dictionary;
 
   33 import com.mysql.clusterj.core.store.Operation;
 
   34 import com.mysql.clusterj.core.store.PartitionKey;
 
   35 import com.mysql.clusterj.core.store.ResultData;
 
   36 import com.mysql.clusterj.core.store.ScanFilter;
 
   37 import com.mysql.clusterj.core.store.Table;
 
   38 import com.mysql.clusterj.core.store.ScanFilter.BinaryCondition;
 
   39 import com.mysql.clusterj.core.util.I18NHelper;
 
   40 import com.mysql.clusterj.core.util.Logger;
 
   41 import com.mysql.clusterj.core.util.LoggerFactoryService;
 
   43 import com.mysql.clusterj.query.Predicate;
 
   44 import com.mysql.clusterj.query.PredicateOperand;
 
   45 import com.mysql.clusterj.query.QueryDomainType;
 
   47 import java.lang.reflect.Field;
 
   48 import java.sql.SQLException;
 
   49 import java.util.Arrays;
 
   50 import java.util.BitSet;
 
   51 import java.util.HashMap;
 
   55 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 
   56 import org.apache.openjpa.jdbc.meta.ClassMapping;
 
   57 import org.apache.openjpa.jdbc.meta.FieldMapping;
 
   58 import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
 
   60 import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
 
   61 import org.apache.openjpa.jdbc.meta.strats.RelationStrategies;
 
   62 import org.apache.openjpa.jdbc.schema.Column;
 
   63 import org.apache.openjpa.jdbc.schema.ForeignKey;
 
   64 import org.apache.openjpa.jdbc.schema.Index;
 
   65 import org.apache.openjpa.kernel.OpenJPAStateManager;
 
   66 import org.apache.openjpa.meta.JavaTypes;
 
   67 import org.apache.openjpa.util.IntId;
 
   68 import org.apache.openjpa.util.LongId;
 
   69 import org.apache.openjpa.util.ObjectId;
 
   70 import org.apache.openjpa.util.OpenJPAId;
 
   71 import org.apache.openjpa.util.StringId;
 
   84     private static com.mysql.clusterj.core.store.Column[] emptyStoreColumns = 
new com.mysql.clusterj.core.store.Column[] {};
 
   86     private FieldMapping fieldMapping;
 
   88     private Column column;
 
   92     private Field oidField;
 
   94     private String javaTypeName;
 
   97     private boolean isRelation = 
false;
 
   99     private boolean isMappedBy = 
false;
 
  101     private boolean isToOne = 
false;
 
  103     private boolean isEmbedded;
 
  105     private ClassMapping relatedTypeMapping = null;
 
  107     private NdbOpenJPADomainTypeHandlerImpl<?> relatedDomainTypeHandler = null;
 
  109     private FieldMapping relatedFieldMapping;
 
  111     private FieldMapping mappedByMapping;
 
  113     private Class<?> relatedType = null;
 
  115     private String relatedTypeName = null;
 
  119     private Column[] columns;
 
  122     private com.mysql.clusterj.core.store.Column[] storeColumns = emptyStoreColumns;
 
  125     private String relatedFieldName;
 
  128     private boolean supported = 
true;
 
  131     private String reason = 
"";
 
  133     private RelatedFieldLoadManager relatedFieldLoadManager;
 
  135     public FieldMapping getFieldMapping() {
 
  143         this.fieldMapping = fieldMapping;
 
  145         this.
name = fieldMapping.getName();
 
  147         this.
primaryKey = fieldMapping.isPrimaryKey();
 
  148         this.columns = fieldMapping.getColumns();
 
  150         this.mappedByMapping = fieldMapping.getMappedByMapping();
 
  151         this.isMappedBy = mappedByMapping != null;
 
  152         this.isToOne = fieldMapping.getStrategy() instanceof RelationFieldStrategy;
 
  154             relatedType = mappedByMapping.getDeclaringType();
 
  155             relatedFieldMapping = fieldMapping.getMappedByMapping();
 
  158         this.relatedTypeMapping = fieldMapping.getDeclaredTypeMapping();
 
  159         if (relatedTypeMapping != null) {
 
  160             relatedType = relatedTypeMapping.getDescribedType();
 
  162         if (relatedType != null) {
 
  163             relatedTypeName = relatedType.getName();
 
  166         this.isRelation = fieldMapping.getStrategy().getClass().getName().contains(
"Relation");
 
  167         this.isEmbedded = fieldMapping.getStrategy().getClass().getName().contains(
"Embed");
 
  168         if (logger.isDetailEnabled()) logger.detail(
 
  169                 "field: " + 
name + 
" strategy: " + fieldMapping.getStrategy().getClass().getName() + 
" with " + columns.length + 
" columns.");
 
  170         if ((!(isRelation | isEmbedded))) {
 
  171             if (columns.length == 1) {
 
  173                 this.column = columns[0];
 
  177                     message = local.
message(
"ERR_No_Mapped_Table", domainTypeHandler.getName());
 
  178                     setUnsupported(message);
 
  184                     setUnsupported(message);
 
  187                 this.storeColumns = 
new com.mysql.clusterj.core.store.Column[] {
storeColumn};
 
  191                 this.
javaType = column.getJavaType();
 
  195                     setUnsupported(message);
 
  200                         domainTypeHandler.registerPrimaryKeyColumn(
this, 
storeColumn.getName());
 
  203             } 
else if (columns.length > 1) {
 
  207                 for (Column errorColumn : columns) {
 
  208                     buffer.append(separator);
 
  209                     buffer.append(errorColumn.getName());
 
  212                 message = local.
message(
"ERR_More_Than_One_Column_Mapped_To_A_Field",
 
  213                         domainTypeHandler.getName(), 
name, buffer);
 
  214                 logger.info(message);
 
  215                 setUnsupported(message);
 
  217             } 
else if (columns.length == 0) {
 
  218                 message = local.
message(
"ERR_No_Column_Mapped_To_A_Field",
 
  219                         domainTypeHandler.getName(), 
name, fieldMapping.getTable(), fieldMapping.getStrategy().getClass().getName());
 
  220                 logger.info(message);
 
  221                 setUnsupported(message);
 
  227                 oidField = getFieldForOidClass(
this, domainTypeHandler.getOidClass(), 
name);
 
  233                     case JavaTypes.INT_OBJ: 
 
  239                     case JavaTypes.LONG_OBJ: 
 
  243                         objectOperationHandlerKeyString;
 
  246                         message = local.
message(
"ERR_Illegal_Primary_Key_Type",
 
  248                         logger.info(message);
 
  249                         setUnsupported(message);
 
  252         } 
else if (isRelation) {
 
  254             if (columns.length == 1) {
 
  255                 this.column = columns[0];
 
  262                     setUnsupported(message);
 
  265                 this.storeColumns = 
new com.mysql.clusterj.core.store.Column[] {
storeColumn};
 
  267                 this.
javaType = column.getJavaType();
 
  274             } 
else if (columns.length == 0) {
 
  279                     message = local.
message(
"ERR_No_Columns_And_Not_Mapped_By",
 
  280                             this.domainTypeHandler.getName(), this.
name);
 
  281                     logger.info(message);
 
  282                     setUnsupported(message);
 
  295                     this.relatedTypeMapping = fieldMapping.getDeclaredTypeMapping();
 
  296                     this.relatedType = relatedTypeMapping.getDescribedType();
 
  297                     Class<?> oid = relatedTypeMapping.getObjectIdType();
 
  298                     if (logger.isDetailEnabled()) logger.detail(
 
  299                             "For class: " + domainTypeHandler.getName() +
 
  300                             " field: " + 
name + 
" related type is: " + relatedType.getName() +
 
  301                             " objectid type: " + oid.getName());
 
  305                     this.storeColumns = 
new com.mysql.clusterj.core.store.Column[columns.length];
 
  306                     for (
int i = 0; 
i < columns.length; ++
i) {
 
  308                         Column localColumn = columns[
i];
 
  309                         String localColumnName = localColumn.getName();
 
  311                         com.mysql.clusterj.core.store.Column localStoreColumn = table.getColumn(localColumnName);
 
  312                         if (localStoreColumn == null) {
 
  313                             message = local.
message(
"ERR_No_Column", 
name, table.getName(), localColumnName);
 
  314                             logger.info(message);
 
  315                             setUnsupported(message);
 
  318                         this.storeColumns[
i] = localStoreColumn;
 
  320                         ForeignKey foreignKey = fieldMapping.getForeignKey();
 
  322                         Column pkColumn = foreignKey.getPrimaryKeyColumn(localColumn);
 
  323                         if (logger.isDetailEnabled()) {
 
  324                             detailMessage.append(
" column: " + localColumnName);
 
  325                             detailMessage.append(
" fk-> " + foreignKey);
 
  326                             detailMessage.append(
" pkColumn-> " + pkColumn);
 
  327                             logger.detail(detailMessage.toString());
 
  331                         if (relatedFieldHandler.isSupported()) {
 
  334                             message = relatedFieldHandler.getReason();
 
  335                             setUnsupported(message);
 
  341                             objectOperationHandlerRelationCompositeField;
 
  346             message = local.
message(
"ERR_Embedded_Fields_Not_Supported",
 
  347                     this.domainTypeHandler.getName(), this.
name);
 
  348             logger.info(message);
 
  349             setUnsupported(message);
 
  353         Index 
index = fieldMapping.getJoinIndex();
 
  356             String indexName = index.getName();
 
  357             Column[] indexColumns = index.getColumns();
 
  358             if (logger.isDetailEnabled()) {
 
  359                 StringBuilder buffer = 
new StringBuilder(
"Found index name ");
 
  360                 buffer.append(indexName);
 
  362                 for (Column indexColumn : indexColumns) {
 
  363                     if (logger.isDetailEnabled()) {
 
  364                         buffer.append(indexColumn.getName());
 
  369                 logger.detail(buffer.toString());
 
  372         index = fieldMapping.getValueIndex();
 
  376             if (logger.isDetailEnabled())  buffer = 
new StringBuffer(
"Found index ");
 
  377             String indexName = index.getName();
 
  378             if (logger.isDetailEnabled())  buffer.append(indexName + 
" [ ");
 
  379             Column[] indexColumns = index.getColumns();
 
  380             for (Column indexColumn : indexColumns) {
 
  381                 if (logger.isDetailEnabled()) buffer.append(indexColumn.getName() + 
" ");
 
  383             if (logger.isDetailEnabled()) buffer.append(
"]");
 
  384             if (logger.isDetailEnabled()) logger.detail(buffer.toString());
 
  387             indices = domainTypeHandler.createIndexHandler(
this, dictionary, indexName);
 
  389         this.
type = fieldMapping.getType();
 
  390         if (logger.isTraceEnabled()) {
 
  393                     " name: " + this.
name +
 
  396                     " strategy: " + toString(fieldMapping.getStrategy()) +
 
  412             if (isMappedBy && isToOne) {
 
  414                 this.relatedDomainTypeHandler = ((NdbOpenJPADomainTypeHandlerImpl<?>)domainTypeHandler)
 
  415                         .registerDependency(relatedTypeMapping);
 
  416                 this.relatedFieldName = relatedFieldMapping.getName();
 
  417                 relatedFieldLoadManager = 
new RelatedFieldLoadManager() {
 
  419                             JDBCFetchConfiguration fetch) 
throws SQLException {
 
  421                         session.startAutoTransaction();
 
  423                         Object related = null;
 
  425                             if (queryResult.next()) {
 
  427                                 related = store.
load(relatedTypeMapping, fetch, (BitSet) null, queryResult);
 
  429                             if (logger.isDetailEnabled()) logger.detail(
"related object is: " + related);
 
  432                             session.endAutoTransaction();
 
  433                         } 
catch (Exception e) {
 
  434                             session.failAutoTransaction();
 
  438                 if (logger.isDetailEnabled()) logger.detail(
"Single-valued relationship field " + 
name 
  439                         + 
" is mapped by " + relatedTypeName + 
" field " + relatedFieldName
 
  440                         + 
" with relatedDomainTypeHandler " + relatedDomainTypeHandler.getName());
 
  441             } 
else if (isMappedBy && !isToOne) {
 
  443                 this.relatedTypeMapping = mappedByMapping.getDeclaringMapping();
 
  444                 this.relatedDomainTypeHandler = ((NdbOpenJPADomainTypeHandlerImpl<?>)domainTypeHandler)
 
  445                         .registerDependency(relatedTypeMapping);
 
  446                 this.relatedFieldName = mappedByMapping.getName();
 
  447                 relatedTypeName = relatedDomainTypeHandler.getName();
 
  448                 if (logger.isDetailEnabled()) logger.detail(
"Multi-valued relationship field " + 
name 
  449                         + 
" is mapped by " + relatedTypeName + 
" field " + relatedFieldName);
 
  450                     relatedFieldLoadManager = 
new RelatedFieldLoadManager() {
 
  452                                 JDBCFetchConfiguration fetch) 
throws SQLException {
 
  454                             session.startAutoTransaction();
 
  457                                 while (queryResult.next()) {
 
  458                                     if (logger.isDetailEnabled()) logger.detail(
"loading related instance of type: " + relatedTypeMapping.getDescribedType().getName());
 
  459                                     store.
load(relatedTypeMapping, fetch, (BitSet) null, queryResult);
 
  461                                 fieldMapping.load(sm, store, fetch);
 
  462                                 session.endAutoTransaction();
 
  463                             } 
catch (Exception e) {
 
  464                                 session.failAutoTransaction();
 
  471                 if (logger.isDetailEnabled()) logger.detail(
"NdbOpenJPADomainFieldHandlerImpl.initializeRelations for "  
  472                         + fieldMapping.getName() + 
" column " + (column==null?
"null":column.getName())
 
  473                         + 
" relatedFieldName " + relatedFieldName
 
  474                         + 
" relatedFieldMapping " + relatedFieldMapping
 
  475                         + 
" relatedTypeMapping " + relatedTypeMapping);
 
  477                 if (relatedTypeMapping != null) {
 
  478                     this.relatedDomainTypeHandler = ((NdbOpenJPADomainTypeHandlerImpl<?>)domainTypeHandler)
 
  479                         .registerDependency(relatedTypeMapping);
 
  480                     relatedFieldLoadManager = 
new RelatedFieldLoadManager() {
 
  482                                 JDBCFetchConfiguration fetch) 
throws SQLException {
 
  483                             if (logger.isDetailEnabled()) logger.detail(
"Loading field " + 
name + 
"from stored key");
 
  484                             fieldMapping.load(sm, store, fetch);
 
  496     private ObjectOperationHandler getObjectOperationHandler(
int javaType) {
 
  498         ObjectOperationHandler result = objectOperationHandlerUnsupportedType;
 
  500         if (javaType < objectOperationHandlers.length) {
 
  501             result = objectOperationHandlers[
javaType];
 
  505             case JavaSQLTypes.SQL_DATE:
 
  506                 return objectOperationHandlerJavaSqlDate;
 
  507             case JavaSQLTypes.TIME:
 
  508                 return objectOperationHandlerJavaSqlTime;
 
  509             case JavaSQLTypes.TIMESTAMP:
 
  510                 return objectOperationHandlerJavaSqlTimestamp;
 
  511             case JavaSQLTypes.BYTES:
 
  515                         return objectOperationHandlerBytesLob;
 
  518                         return objectOperationHandlerBytes;
 
  521             case JavaTypes.STRING:
 
  524                         return objectOperationHandlerStringLob;
 
  528                         return objectOperationHandlerString;
 
  545             Column localColumn, Column pkColumn) {
 
  547         if (logger.isDetailEnabled()) logger.detail(
"NdbOpenJPADomainFieldHandlerImpl<init> for localColumn: " + localColumn + 
" pkColumn: " + pkColumn);
 
  548         this.column = localColumn;
 
  550         this.
storeColumn = table.getColumn(localColumn.getName());
 
  552             message = local.
message(
"ERR_No_Column", parent.getName(), table.getName(), 
columnName);
 
  553             setUnsupported(message);
 
  554             logger.info(message);
 
  557         this.javaType = column.getJavaType();
 
  566         this.relatedTypeMapping = parent.relatedTypeMapping;
 
  567         if (relatedTypeMapping != null) {
 
  568             relatedType = relatedTypeMapping.getDescribedType();
 
  569             if (relatedType != null) {
 
  570                 relatedTypeName = relatedType.getName();
 
  574         FieldMapping[] relatedFieldMappings = relatedTypeMapping.getPrimaryKeyFieldMappings();
 
  575         for (FieldMapping rfm: relatedFieldMappings) {
 
  576             Column[] rcs = rfm.getColumns();
 
  577             if (logger.isDetailEnabled()) logger.detail(
"NdbOpenJPADomainFieldHandlerImpl<init> trying primary key column: " + rcs[0]);
 
  578             if (rcs.length == 1 && rcs[0].equals(pkColumn)) {
 
  580                 String pkFieldName = rfm.getName();
 
  581                 oidField = getFieldForOidClass(
this, relatedTypeMapping.getObjectIdType(), pkFieldName);
 
  582             if (logger.isDetailEnabled()) logger.detail(
"NdbOpenJPADomainFieldHandlerImpl<init> found primary key column: " + rcs[0] + 
" for field: " + pkFieldName);
 
  586         if (oidField == null) {
 
  587             message = local.
message(
"ERR_No_Oid_Field", pkColumn);
 
  588             setUnsupported(message);
 
  589             logger.info(message);
 
  592         if (logger.isTraceEnabled()) {
 
  593             logger.trace(
" Relation Field Handler for column: " + 
columnName +
 
  595                     " name: " + this.
name +
 
  597                     " Java type: " + javaType +
 
  603     interface RelatedFieldLoadManager {
 
  605                 JDBCFetchConfiguration fetch) 
throws SQLException ;
 
  617             throws SQLException {
 
  619             relatedFieldLoadManager.load(sm, store, fetch);
 
  622                     + this.getName() + 
" mapped to column " + this.
columnName);
 
  633         OpenJPAId openJPAId = (OpenJPAId)sm.getObjectId();
 
  634         Object thisOid = openJPAId.getIdObject();
 
  635         QueryDomainType<?> queryDomainType = store.createQueryDomainType(relatedType);
 
  636         if (logger.isDetailEnabled()) logger.detail(
"created query for " + queryDomainType.getType().getName());
 
  638         Predicate predicate = queryDomainType.get(relatedFieldName).equal(queryDomainType.param(relatedFieldName));
 
  639         queryDomainType.where(predicate);
 
  640         Map<String, Object> parameterList = 
new HashMap<String, Object>();
 
  641         parameterList.put(relatedFieldName, thisOid);
 
  642         if (logger.isDetailEnabled()) logger.detail(parameterList.toString());
 
  645         if (logger.isDetailEnabled()) {
 
  647             Set<String> 
columnNames = queryResult.getColumnNames();
 
  649             buffer.append(handler.getName());
 
  650             buffer.append(
" returned columns: ");
 
  651             buffer.append(Arrays.toString(columnNames.toArray()));
 
  652             logger.detail(buffer.toString());
 
  657     public void load(OpenJPAStateManager sm, NdbOpenJPAStoreManager store, JDBCFetchConfiguration fetch, 
 
  658             NdbOpenJPAResult result) 
throws SQLException {
 
  659         fieldMapping.load(sm, store, fetch, result);
 
  672     public ObjectOperationHandler[] objectOperationHandlers =
 
  673             new ObjectOperationHandler[] {
 
  674         objectOperationHandlerBoolean,         
 
  675         objectOperationHandlerByte,            
 
  676         objectOperationHandlerUnsupportedType, 
 
  677         objectOperationHandlerDouble,          
 
  678         objectOperationHandlerFloat,           
 
  679         objectOperationHandlerInt,             
 
  680         objectOperationHandlerLong,            
 
  681         objectOperationHandlerShort,           
 
  682         objectOperationHandlerUnsupportedType, 
 
  683         objectOperationHandlerString,          
 
  684         objectOperationHandlerUnsupportedType, 
 
  685         objectOperationHandlerUnsupportedType, 
 
  686         objectOperationHandlerUnsupportedType, 
 
  687         objectOperationHandlerUnsupportedType, 
 
  688         objectOperationHandlerJavaUtilDate,    
 
  689         objectOperationHandlerUnsupportedType, 
 
  690         objectOperationHandlerObjectBoolean,   
 
  691         objectOperationHandlerObjectByte,      
 
  692         objectOperationHandlerUnsupportedType, 
 
  693         objectOperationHandlerObjectDouble,    
 
  694         objectOperationHandlerObjectFloat,     
 
  695         objectOperationHandlerObjectInteger,   
 
  696         objectOperationHandlerObjectLong,      
 
  697         objectOperationHandlerObjectShort,     
 
  698         objectOperationHandlerDecimal,         
 
  699         objectOperationHandlerBigInteger,      
 
  700         objectOperationHandlerUnsupportedType, 
 
  701         objectOperationHandlerUnsupportedType, 
 
  702         objectOperationHandlerUnsupportedType, 
 
  703         objectOperationHandlerUnsupportedType, 
 
  704         objectOperationHandlerUnsupportedType, 
 
  705         objectOperationHandlerUnsupportedType          
 
  708     public int compareTo(Object o) {
 
  709         return compareTo((NdbOpenJPADomainFieldHandlerImpl)o);
 
  712     protected String toString(Object o) {
 
  713         return o.getClass().getSimpleName();
 
  716     Column[] getColumns() {
 
  717         return fieldMapping.getColumns();
 
  720     protected Object getKeyValue(Object keys) {
 
  722         if (keys instanceof ObjectId) {
 
  723             key = ((ObjectId)keys).getId();
 
  725         return getKeyValue(oidField, key);
 
  728     protected static Object getKeyValue(
Field field, Object keys) {
 
  731             String fieldName = 
"none";
 
  733                 result = field.get(keys);
 
  734                 fieldName = field.getName();
 
  738             if (logger.isDetailEnabled()) logger.detail(
"For field " + fieldName + 
" keys: " + keys + 
" value returned is " + result);
 
  740         } 
catch (IllegalArgumentException ex) {
 
  741             String message = 
"IllegalArgumentException, field " + field.getDeclaringClass().getName() + 
":" + field.getName() + 
" keys: " + keys;
 
  742             logger.error(message);
 
  743             throw new ClusterJUserException(message, ex);
 
  744         } 
catch (IllegalAccessException ex) {
 
  745             String message = 
"IllegalAccessException, field " + field.getDeclaringClass().getName() + 
":" + field.getName() + 
" keys: " + keys;
 
  746             throw new ClusterJUserException(message, ex);
 
  750     public Field getOidField() {
 
  754     protected static Field getFieldForOidClass(
 
  755             NdbOpenJPADomainFieldHandlerImpl ndbOpenJPADomainFieldHandlerImpl,
 
  756             Class<?> oidClass, 
String fieldName) {
 
  759         if (logger.isDetailEnabled()) logger.detail(
"Oid class: " + oidClass.getName());
 
  761         if (OpenJPAId.class.isAssignableFrom(oidClass)) {
 
  766                 result = oidClass.getField(fieldName);
 
  767                 if (logger.isDetailEnabled()) logger.detail(
"OidField: " + result);
 
  769             } 
catch (NoSuchFieldException ex) {
 
  770                 message = local.
message(
"ERR_No_Field_In_Oid_Class", oidClass.getName(), fieldName);
 
  771                 logger.info(message);
 
  772                 ndbOpenJPADomainFieldHandlerImpl.setUnsupported(message);
 
  774             } 
catch (SecurityException ex) {
 
  775                 message = local.
message(
"ERR_Security_Violation_For_Oid_Class", oidClass.getName());
 
  776                 logger.info(message);
 
  777                 ndbOpenJPADomainFieldHandlerImpl.setUnsupported(message);
 
  783     protected ObjectOperationHandler getObjectOperationHandlerRelationDelegate(
int javaType) {
 
  787             case JavaTypes.INT_OBJ:
 
  788                 return objectOperationHandlerRelationIntField;
 
  791             case JavaTypes.LONG_OBJ:
 
  792                 return objectOperationHandlerRelationLongField;
 
  794             case JavaTypes.STRING:
 
  795                 return objectOperationHandlerRelationStringField;
 
  798                 message = local.
message(
"ERR_Illegal_Foreign_Key_Type",
 
  800                 setUnsupported(message);
 
  805     static abstract class ObjectOperationHandlerRelationField 
implements ObjectOperationHandler {
 
  807         public boolean isPrimitive() {
 
  818         public Map<String, Object> 
createParameterMap(NdbOpenJPADomainFieldHandlerImpl domainFieldHandler, QueryDomainType<?> queryDomainObject, Object oid) {
 
  820             PredicateOperand parameter = queryDomainObject.get(name);
 
  821             Predicate predicate = parameter.equal(parameter);
 
  822             queryDomainObject.where(predicate);
 
  825             Object value = domainFieldHandler.getKeyValue(oid);
 
  826             result.put(name, value);
 
  827             if (logger.isDetailEnabled()) logger.detail(
"Map.Entry key: " + name + 
", value: " + value);
 
  831         public void objectInitializeJavaDefaultValue(AbstractDomainFieldHandlerImpl fmd, ValueHandler handler) {
 
  832             throw new ClusterJFatalInternalException(
 
  833                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  836         public void operationGetValue(AbstractDomainFieldHandlerImpl fmd, Operation op) {
 
  837             op.getValue(fmd.getStoreColumn());
 
  841             throw new ClusterJFatalInternalException(
 
  842                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  845         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
  846             throw new ClusterJFatalInternalException(
 
  847                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  850         public void objectSetValue(AbstractDomainFieldHandlerImpl fmd, ResultData rs, ValueHandler handler) {
 
  851             throw new ClusterJFatalInternalException(
 
  852                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  855         public void operationSetBounds(AbstractDomainFieldHandlerImpl fmd, Object value, BoundType 
type, IndexScanOperation op) {
 
  856             throw new ClusterJFatalInternalException(
 
  857                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  860         public void filterCompareValue(AbstractDomainFieldHandlerImpl fmd, Object value, BinaryCondition condition, 
ScanFilter filter) {
 
  861             throw new ClusterJFatalInternalException(
 
  862                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  865         public void operationEqual(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
  866             throw new ClusterJFatalInternalException(
 
  867                     local.message(
"ERR_Implementation_Should_Not_Occur"));
 
  870         public boolean isValidIndexType(AbstractDomainFieldHandlerImpl fmd, 
boolean hashNotOrdered) {
 
  875         protected int getInt(Object objectId) {
 
  877             if (objectId instanceof IntId) {
 
  878                 return ((IntId)objectId).getId();
 
  879             } 
else if (objectId instanceof OpenJPAId) {
 
  880                 OpenJPAId openJPAId = (OpenJPAId)objectId;
 
  881                 Object 
id = openJPAId.getIdObject();
 
  882                 if (
id instanceof Integer) {
 
  883                     return ((Integer)
id).intValue();
 
  885                 throw new UnsupportedOperationException(
 
  886                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"int key", 
"OpenJPAId"));
 
  888                 String message = (objectId == null)?
"<null>":objectId.getClass().getName();
 
  889                 throw new UnsupportedOperationException(
 
  890                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"int key", message));
 
  894         protected long getLong(Object objectId) {
 
  896             if (objectId instanceof LongId) {
 
  897                 return ((LongId)objectId).getId();
 
  898             } 
else if (objectId instanceof OpenJPAId) {
 
  899                 OpenJPAId openJPAId = (OpenJPAId)objectId;
 
  900                 Object 
id = openJPAId.getIdObject();
 
  901                 if (
id instanceof Long) {
 
  902                     return ((Long)
id).longValue();
 
  904                 throw new UnsupportedOperationException(
 
  905                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"long key", 
"OpenJPAId"));
 
  907                 String message = (objectId == null)?
"<null>":objectId.getClass().getName();
 
  908                 throw new UnsupportedOperationException(
 
  909                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"long key", message));
 
  913         protected String getString(Object objectId) {
 
  915             if (objectId instanceof StringId) {
 
  916                 return ((StringId)objectId).getId();
 
  917             } 
else if (objectId instanceof OpenJPAId) {
 
  918                 OpenJPAId openJPAId = (OpenJPAId)objectId;
 
  919                 Object 
id = openJPAId.getIdObject();
 
  920                 if (
id instanceof 
String) {
 
  923                 throw new UnsupportedOperationException(
 
  924                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"String key", 
"OpenJPAId"));
 
  926                 String message = (objectId == null)?
"<null>":objectId.getClass().getName();
 
  927                 throw new UnsupportedOperationException(
 
  928                         local.message(
"ERR_Unsupported_Object_Id_Type", 
"String key", message));
 
  932         protected OpenJPAStateManager getRelatedStateManager(ValueHandler handler, AbstractDomainFieldHandlerImpl fmd) {
 
  934             OpenJPAStateManager sm = ((NdbOpenJPAValueHandler) handler).getStateManager();
 
  935             NdbOpenJPAStoreManager store = ((NdbOpenJPAValueHandler) handler).getStoreManager();
 
  936             OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.fetchObjectField(fmd.getFieldNumber()), store.getContext());
 
  940         public void partitionKeySetPart(AbstractDomainFieldHandlerImpl fmd,
 
  941                 PartitionKey 
partitionKey, ValueHandler keyValueHandler) {
 
  942             throw new ClusterJFatalInternalException(
 
  943                     local.message(
"ERR_Operation_Not_Supported",
"partitionKeySetPart", 
"non-key fields"));
 
  946         public Object getValue(QueryExecutionContext context, String 
index) {
 
  947             return context.getObject(index);
 
  951     static ObjectOperationHandler objectOperationHandlerRelationIntField =
 
  952             new ObjectOperationHandlerRelationField() {
 
  954         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, ValueHandler handler, Operation op) {
 
  955             OpenJPAStateManager rel = getRelatedStateManager(handler, fmd);
 
  958                 if (logger.isDetailEnabled()) logger.detail(
"Related object is null");
 
  959                 op.setNull(fmd.getStoreColumn());
 
  961                 Object objid = rel.getObjectId();
 
  964                     op.setNull(fmd.getStoreColumn());
 
  965                     if (logger.isDetailEnabled()) logger.detail(
"Related object class: " + rel.getMetaData().getTypeAlias() + 
" object id: " + objid);
 
  967                     int oid = getInt(objid);
 
  968                     if (logger.isDetailEnabled()) logger.detail(
"Related object class: " + rel.getMetaData().getTypeAlias() + 
" key: " + oid);
 
  969                     op.setInt(fmd.getStoreColumn(), oid);
 
  974         public String handler() {
 
  975             return "Object ToOne Int key.";
 
  979         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
  981                 op.setNull(fmd.getStoreColumn());
 
  983                 op.setInt(fmd.getStoreColumn(),(Integer) value);
 
  988         public void filterCompareValue(AbstractDomainFieldHandlerImpl fmd, Object oid, BinaryCondition condition, 
ScanFilter filter) {
 
  989             Field field = ((NdbOpenJPADomainFieldHandlerImpl)fmd).getOidField();
 
  990             Object value = getKeyValue(field, oid);
 
  991             if (logger.isDetailEnabled()) logger.detail(
"For column: " + fmd.getColumnName() + 
" oid: " + oid + 
" value: " + value);
 
  992             filter.cmpInt(condition, fmd.getStoreColumn(), ((Integer) value).intValue());
 
 1002         public void operationSetBounds(AbstractDomainFieldHandlerImpl fmd, Object value, BoundType type, IndexScanOperation op) {
 
 1003             op.setBoundInt(fmd.getStoreColumn(), 
type, (Integer)value);
 
 1008     static ObjectOperationHandler objectOperationHandlerRelationLongField =
 
 1009             new ObjectOperationHandlerRelationField() {
 
 1011         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, ValueHandler handler, Operation op) {
 
 1012             OpenJPAStateManager rel = getRelatedStateManager(handler, fmd);
 
 1015                 if (logger.isDetailEnabled()) logger.detail(
"Related object is null");
 
 1016                 op.setNull(fmd.getStoreColumn());
 
 1018                 long oid = getLong(rel.getObjectId());
 
 1019                 if (logger.isDetailEnabled()) logger.detail(
"Related object class: " + rel.getMetaData().getTypeAlias() + 
" key: " + oid);
 
 1020                 op.setLong(fmd.getStoreColumn(), oid);
 
 1024         public String handler() {
 
 1025             return "Object ToOne Long key.";
 
 1029         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
 1030             if (value == null) {
 
 1031                 op.setNull(fmd.getStoreColumn());
 
 1033                 op.setLong(fmd.getStoreColumn(),(Long) value);
 
 1038         public void filterCompareValue(AbstractDomainFieldHandlerImpl fmd, Object oid, BinaryCondition condition, 
ScanFilter filter) {
 
 1039             Field field = ((NdbOpenJPADomainFieldHandlerImpl)fmd).getOidField();
 
 1040             Object value = getKeyValue(field, oid);
 
 1041             if (logger.isDetailEnabled()) logger.detail(
"For column: " + fmd.getColumnName() + 
" oid: " + oid + 
" value: " + value);
 
 1042             filter.cmpLong(condition, fmd.getStoreColumn(), ((Long) value).longValue());
 
 1052         public void operationSetBounds(AbstractDomainFieldHandlerImpl fmd, Object value, BoundType type, IndexScanOperation op) {
 
 1053             op.setBoundLong(fmd.getStoreColumn(), 
type, (Long)value);
 
 1058     static ObjectOperationHandler objectOperationHandlerRelationStringField =
 
 1059             new ObjectOperationHandlerRelationField() {
 
 1061         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, ValueHandler handler, Operation op) {
 
 1062             OpenJPAStateManager rel = getRelatedStateManager(handler, fmd);
 
 1065                 if (logger.isDetailEnabled()) logger.detail(
"Related object is null");
 
 1066                 op.setNull(fmd.getStoreColumn());
 
 1068                 String oid = getString(rel.getObjectId());
 
 1069                 if (logger.isDetailEnabled()) logger.detail(
"Related object class: " + rel.getMetaData().getTypeAlias() + 
" key: " + oid);
 
 1070                 op.setString(fmd.getStoreColumn(), oid);
 
 1074         public String handler() {
 
 1075             return "Object ToOne String key.";
 
 1079         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
 1080             if (value == null) {
 
 1081                 op.setNull(fmd.getStoreColumn());
 
 1083                 op.setString(fmd.getStoreColumn(),(String) value);
 
 1088         public void filterCompareValue(AbstractDomainFieldHandlerImpl fmd, Object oid, BinaryCondition condition, 
ScanFilter filter) {
 
 1089             Field field = ((NdbOpenJPADomainFieldHandlerImpl)fmd).getOidField();
 
 1090             Object value = getKeyValue(field, oid);
 
 1091             if (logger.isDetailEnabled()) logger.detail(
"For column: " + fmd.getColumnName() + 
" oid: " + oid + 
" filter.cmpString: " + value);
 
 1092             filter.cmpString(condition, fmd.getStoreColumn(), (String) value);
 
 1102         public void operationSetBounds(AbstractDomainFieldHandlerImpl fmd, Object value, BoundType type, IndexScanOperation op) {
 
 1103             op.setBoundString(fmd.getStoreColumn(), 
type, (String)value);
 
 1108     static ObjectOperationHandlerRelationField objectOperationHandlerRelationCompositeField = 
new ObjectOperationHandlerRelationField() {
 
 1110         public String handler() {
 
 1111             return "Composite key.";
 
 1115         public void operationGetValue(AbstractDomainFieldHandlerImpl fmd, Operation op) {
 
 1116             for (AbstractDomainFieldHandlerImpl localHandler: fmd.compositeDomainFieldHandlers) {
 
 1117                 localHandler.operationGetValue(op);
 
 1122         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, Object value, Operation op) {
 
 1123             throw new ClusterJFatalInternalException(
 
 1124                     local.
message(
"ERR_Implementation_Should_Not_Occur"));
 
 1132         public void filterCompareValue(AbstractDomainFieldHandlerImpl fmd, Object value, BinaryCondition condition, 
ScanFilter filter) {
 
 1134             if (!BinaryCondition.COND_EQ.equals(condition)) {
 
 1135                 throw new ClusterJFatalInternalException(
 
 1136                         local.
message(
"ERR_Illegal_Filter_Condition", condition));
 
 1139             for (AbstractDomainFieldHandlerImpl localHandler : fmd.compositeDomainFieldHandlers) {
 
 1140                 if (value != null) {
 
 1142                     localHandler.filterCompareValue(value, condition, filter);
 
 1145                     localHandler.filterCompareValue((Object)null, condition, filter);
 
 1151         public void operationSetValue(AbstractDomainFieldHandlerImpl fmd, ValueHandler handler, Operation op) {
 
 1152             OpenJPAStateManager rel = getRelatedStateManager(handler, fmd);
 
 1153             OpenJPAId openJPAId = null;
 
 1156                 if (logger.isDetailEnabled()) logger.detail(
"Related object is null");
 
 1158                 if (logger.isDetailEnabled()) logger.detail(
"Related object class: " + rel.getMetaData().getTypeAlias() + 
" key: " + openJPAId);
 
 1159                 openJPAId = (OpenJPAId) rel.getObjectId();
 
 1160                 oid = openJPAId.getIdObject();
 
 1162             for (AbstractDomainFieldHandlerImpl localHandler : fmd.compositeDomainFieldHandlers) {
 
 1163                 Object value = null;
 
 1166                     Field field = ((NdbOpenJPADomainFieldHandlerImpl)localHandler).getOidField();
 
 1167                     value = getKeyValue(field, oid);
 
 1168                     localHandler.operationSetValue(value, op);
 
 1171                     localHandler.operationSetValue((Object)null, op);
 
 1177         public Map<String, Object> 
createParameterMap(NdbOpenJPADomainFieldHandlerImpl domainFieldHandler, 
 
 1178                 QueryDomainType<?> queryDomainObject, Object oid) {
 
 1180             Predicate predicate = null;
 
 1181             for (AbstractDomainFieldHandlerImpl localHandler: domainFieldHandler.compositeDomainFieldHandlers) {
 
 1182                 String name = localHandler.getColumnName();
 
 1183                 PredicateOperand parameter = queryDomainObject.param(name);
 
 1184                 PredicateOperand field = queryDomainObject.get(name);
 
 1185                 if (predicate == null) {
 
 1186                     predicate = field.equal(parameter);
 
 1188                     predicate.and(field.equal(parameter));
 
 1191                 Object value = domainFieldHandler.getKeyValue(oid);
 
 1192                 result.put(name, value);
 
 1193                 if (logger.isDetailEnabled()) logger.detail(
"Map.Entry key: " + name + 
", value: " + value);
 
 1195             queryDomainObject.where(predicate);
 
 1207         public void operationSetBounds(AbstractDomainFieldHandlerImpl fmd, Object oid, BoundType type, IndexScanOperation op) {
 
 1208             for (AbstractDomainFieldHandlerImpl localHandler : fmd.compositeDomainFieldHandlers) {
 
 1209                 Field field = ((NdbOpenJPADomainFieldHandlerImpl)localHandler).getOidField();
 
 1210                 Object columnData = getKeyValue(field, oid);
 
 1211                 localHandler.operationSetBounds(columnData, type, op);
 
 1217     public com.mysql.clusterj.core.store.Column[] getStoreColumns() {
 
 1218         return storeColumns;
 
 1221     public boolean isSupported() {
 
 1225     public boolean isRelation() {
 
 1229     public String getReason() {
 
 1233     private void setUnsupported(String reason) {
 
 1234         this.supported = 
false;
 
 1235         this.reason = reason;