/** * Walks through all fields of a descriptor and resolves relation {@link ClassDescriptor}s by * using mapping information or, if not present, resolution by file to support generated {@link * ClassDescriptor}s. Resolved {@link ClassDescriptor}s will be set as a field's descriptor. * * @param clsDesc The ClassDescriptor in focus. */ protected void resolveRelations(final ClassDescriptor clsDesc) { FieldDescriptor[] fields = clsDesc.getFields(); for (int i = 0; i < fields.length; ++i) { FieldDescriptor field = fields[i]; ClassDescriptor desc = getDescriptor(field.getFieldType().getName()); // Resolve ClassDescriptor from the file system as well. if (desc == null && !field.getFieldType().isPrimitive()) { ClassResolutionByFile resolutionCommand = new ClassResolutionByFile(); resolutionCommand.addNature(ClassLoaderNature.class.getName()); ClassLoaderNature clNature = new ClassLoaderNature(resolutionCommand); clNature.setClassLoader(getClassLoader()); desc = resolutionCommand.resolve(field.getFieldType()); ((FieldDescriptorImpl) field).setClassDescriptor(desc); } if ((desc != null) && (field instanceof FieldDescriptorImpl)) { ((FieldDescriptorImpl) field).setClassDescriptor(desc); } } }
/** * Construct a new field descriptor for the specified field. This is a JDO field descriptor * wrapping a field descriptor and adding JDO related properties and methods. * * @param fieldDesc The field descriptor * @throws MappingException Invalid mapping information */ public JDOFieldDescriptor( FieldDescriptorImpl fieldDesc, String[] sqlName, int[] sqlType, boolean dirtyCheck, String manyTable, String[] manyKey) throws MappingException { super(fieldDesc); if (fieldDesc.isTransient() || fieldDesc.getHandler() == null) throw new IllegalArgumentException( "Argument 'fieldDesc' is a transient field or has no handler"); // if ( sqlName == null ) // throw new IllegalArgumentException( "Argument 'sqlName' is null" ); _sqlName = (sqlName.length == 0 ? null : sqlName); _dirtyCheck = dirtyCheck; _manyTable = manyTable; _manyKey = (manyKey.length > 0 ? manyKey : null); _sqlType = sqlType; }
protected FieldDescriptorImpl createFieldDesc(final Class javaClass, final FieldMapping fieldMap) throws MappingException { // If not an SQL field, return a stock field descriptor. Sql sql = fieldMap.getSql(); if (sql == null) { return super.createFieldDesc(javaClass, fieldMap); } String fieldName = fieldMap.getName(); // If the field type is supplied, grab it and use it to locate the // field/accessor. Class fieldType = null; if (fieldMap.getType() != null) { fieldType = resolveType(fieldMap.getType()); } // If the field is declared as a collection, grab the collection type as // well and use it to locate the field/accessor. CollectionHandler colHandler = null; boolean isLazy = fieldMap.getLazy(); if (fieldMap.getCollection() != null) { Class colType = CollectionHandlers.getCollectionType(fieldMap.getCollection().toString()); colHandler = CollectionHandlers.getHandler(colType); if (colType.getName().equals("java.util.Iterator") && isLazy) { String err = "Lazy loading not supported for collection type 'iterator'"; throw new MappingException(err); } if (colType.getName().equals("java.util.Enumeration") && isLazy) { String err = "Lazy loading not supported for collection type 'enumerate'"; throw new MappingException(err); } } TypeInfo typeInfo = getTypeInfo(fieldType, colHandler, fieldMap); ExtendedFieldHandler exfHandler = null; FieldHandler handler = null; // -- check for user supplied FieldHandler if (fieldMap.getHandler() != null) { Class handlerClass = resolveType(fieldMap.getHandler()); if (!FieldHandler.class.isAssignableFrom(handlerClass)) { String err = "The class '" + fieldMap.getHandler() + "' must implement " + FieldHandler.class.getName(); throw new MappingException(err); } // -- get default constructor to invoke. We can't use the // -- newInstance method unfortunately becaue FieldHandler // -- overloads this method Constructor constructor = null; try { constructor = handlerClass.getConstructor(new Class[0]); handler = (FieldHandler) constructor.newInstance(new Object[0]); } catch (Exception except) { String err = "The class '" + handlerClass.getName() + "' must have a default public constructor."; throw new MappingException(err); } // -- ExtendedFieldHandler? if (handler instanceof ExtendedFieldHandler) { exfHandler = (ExtendedFieldHandler) handler; } // -- Fix for Castor JDO from Steve Vaughan, Castor JDO // -- requires FieldHandlerImpl or a ClassCastException // -- will be thrown... [KV 20030131 - also make sure this new handler // -- doesn't use it's own CollectionHandler otherwise // -- it'll cause unwanted calls to the getValue method during // -- unmarshalling] colHandler = typeInfo.getCollectionHandler(); typeInfo.setCollectionHandler(null); handler = new FieldHandlerImpl(handler, typeInfo); typeInfo.setCollectionHandler(colHandler); // -- End Castor JDO fix } boolean generalized = (exfHandler instanceof GeneralizedFieldHandler); // -- if generalized we need to change the fieldType to whatever // -- is specified in the GeneralizedFieldHandler so that the // -- correct getter/setter methods can be found FieldHandler custom = handler; if (generalized) { fieldType = ((GeneralizedFieldHandler) exfHandler).getFieldType(); } if (generalized || (handler == null)) { // -- create TypeInfoRef to get new TypeInfo from call // -- to createFieldHandler TypeInfoReference typeInfoRef = new TypeInfoReference(); typeInfoRef.typeInfo = typeInfo; handler = createFieldHandler(javaClass, fieldType, fieldMap, typeInfoRef); if (custom != null) { ((GeneralizedFieldHandler) exfHandler).setFieldHandler(handler); handler = custom; } else { typeInfo = typeInfoRef.typeInfo; } } String[] sqlName = sql.getName(); String[] sqlTypes = getSqlTypes(fieldMap); int[] sqlTypeNum; if (sqlTypes.length > 0) { sqlTypeNum = new int[sqlTypes.length]; for (int i = 0; i < sqlTypes.length; i++) { String sqlTypeString = definition2type(sqlTypes[i]); Class sqlType = SQLTypeInfos.sqlTypeName2javaType(sqlTypeString); if (_factory != null) { sqlType = _factory.adjustSqlType(sqlType); } sqlTypeNum[i] = SQLTypeInfos.javaType2sqlTypeNum(sqlType); } } else { Class sqlType = typeInfo.getFieldType(); if (_factory != null) { sqlType = _factory.adjustSqlType(sqlType); } sqlTypeNum = new int[] {SQLTypeInfos.javaType2sqlTypeNum(sqlType)}; } // create FieldDescriptor(Impl) instance, and apply JDO nature FieldDescriptorImpl fieldDescriptor = new FieldDescriptorImpl(fieldName, typeInfo, handler, fieldMap.getTransient()); fieldDescriptor.addNature(FieldDescriptorJDONature.class.getName()); fieldDescriptor.setRequired(fieldMap.getRequired()); // If we're using an ExtendedFieldHandler we need to set the FieldDescriptor if (exfHandler != null) { ((FieldHandlerFriend) exfHandler).setFieldDescriptor(fieldDescriptor); } // if SQL mapping declares transient // TODO: cross-check that this should be implemented like this if (sql.getTransient()) { fieldDescriptor.setTransient(true); } // set collection type as specified in mapping file fieldDescriptor.setCollection(fieldMap.getCollection()); fieldDescriptor.setComparator(fieldMap.getComparator()); fieldDescriptor.setCreateMethod(fieldMap.getCreateMethod()); fieldDescriptor.setGetMethod(fieldMap.getGetMethod()); fieldDescriptor.setSetMethod(fieldMap.getSetMethod()); fieldDescriptor.setDirect(fieldMap.getDirect()); // extract values for 'laziness' from field mapping fieldDescriptor.setLazy(isLazy); FieldDescriptorJDONature fieldJdoNature = new FieldDescriptorJDONature(fieldDescriptor); fieldJdoNature.setTypeConvertor(typeInfo.getConvertorFrom()); if (sqlName.length > 0) { fieldJdoNature.setSQLName(sqlName); } fieldJdoNature.setSQLType(sqlTypeNum); fieldJdoNature.setManyTable(sql.getManyTable()); if (sql.getManyKey().length > 0) { fieldJdoNature.setManyKey(sql.getManyKey()); } fieldJdoNature.setDirtyCheck(!SqlDirtyType.IGNORE.equals(sql.getDirty())); fieldJdoNature.setReadOnly(sql.getReadOnly()); fieldJdoNature.setCascading(sql.getCascading()); fieldJdoNature.setTransient(sql.getTransient()); return fieldDescriptor; }