// field accessor will ignore all methods not annotated
return null;
}
// Create the Field/Property MetaData so we have something to add to
AbstractMemberMetaData mmd = newMetaDataForMember(cmd, member, annotations);
// Check if this is marked as an element collection
boolean elementCollection = false;
for (int i=0;i<annotations.length;i++)
{
String annName = annotations[i].getName();
if (annName.equals(JPAAnnotationUtils.ELEMENT_COLLECTION))
{
elementCollection = true;
break;
}
}
// Process other annotations
ColumnMetaData[] columnMetaData = null;
JoinMetaData joinmd = null;
KeyMetaData keymd = null;
boolean oneToMany = false;
boolean manyToMany = false;
for (int i=0;annotations != null && i<annotations.length;i++)
{
String annName = annotations[i].getName();
HashMap<String, Object> annotationValues = annotations[i].getNameValueMap();
if (annName.equals(JPAAnnotationUtils.JOIN_COLUMNS))
{
// 1-1 FK columns, or 1-N FK columns, or N-1 FK columns
JoinColumn[] cols = (JoinColumn[])annotationValues.get("value");
if (cols != null)
{
columnMetaData = new ColumnMetaData[cols.length];
for (int j=0;j<cols.length;j++)
{
columnMetaData[j] = new ColumnMetaData();
columnMetaData[j].setName(cols[j].name());
columnMetaData[j].setTarget(cols[j].referencedColumnName());
columnMetaData[j].setAllowsNull(cols[j].nullable());
columnMetaData[j].setInsertable(cols[j].insertable());
columnMetaData[j].setUpdateable(cols[j].updatable());
columnMetaData[j].setUnique(cols[j].unique());
}
}
}
else if (annName.equals(JPAAnnotationUtils.JOIN_COLUMN))
{
// 1-1 FK column, or 1-N FK column, or N-1 FK column
columnMetaData = new ColumnMetaData[1];
String colNullable = null;
String colInsertable = null;
String colUpdateable = null;
String colUnique = null;
if (annotationValues.get("nullable") != null)
{
colNullable = annotationValues.get("nullable").toString();
}
if (annotationValues.get("insertable") != null)
{
colInsertable = annotationValues.get("insertable").toString();
}
if (annotationValues.get("updatable") != null)
{
// Note : "updatable" is spelt incorrectly in the JPA spec.
colUpdateable = annotationValues.get("updatable").toString();
}
if (annotationValues.get("unique") != null)
{
colUnique = annotationValues.get("unique").toString();
}
columnMetaData[0] = new ColumnMetaData();
columnMetaData[0].setName((String)annotationValues.get("name"));
columnMetaData[0].setTarget((String)annotationValues.get("referencedColumnName"));
columnMetaData[0].setAllowsNull(colNullable);
columnMetaData[0].setInsertable(colInsertable);
columnMetaData[0].setUpdateable(colUpdateable);
columnMetaData[0].setUnique(colUnique);
}
else if (annName.equals(JPAAnnotationUtils.PRIMARY_KEY_JOIN_COLUMNS))
{
// 1-1 FK columns
PrimaryKeyJoinColumn[] cols = (PrimaryKeyJoinColumn[])annotationValues.get("value");
if (cols != null)
{
columnMetaData = new ColumnMetaData[cols.length];
for (int j=0;j<cols.length;j++)
{
columnMetaData[j] = new ColumnMetaData();
columnMetaData[j].setName(cols[j].name());
columnMetaData[j].setTarget(cols[j].referencedColumnName());
}
}
}
else if (annName.equals(JPAAnnotationUtils.PRIMARY_KEY_JOIN_COLUMN))
{
// 1-1 FK column
columnMetaData = new ColumnMetaData[1];
columnMetaData[0] = new ColumnMetaData();
columnMetaData[0].setName((String)annotationValues.get("name"));
columnMetaData[0].setTarget((String)annotationValues.get("referencedColumnName"));
}
else if (annName.equals(JPAAnnotationUtils.ATTRIBUTE_OVERRIDES) && mmd.isEmbedded())
{
// Embedded field overrides
AttributeOverride[] attributeOverride = (AttributeOverride[])annotationValues.get("value");
for (int j=0; j<attributeOverride.length; j++)
{
processEmbeddedAttributeOverride(mmd, attributeOverride[j].name(),
member.getType(), attributeOverride[j].column());
}
}
else if (annName.equals(JPAAnnotationUtils.ATTRIBUTE_OVERRIDE) && mmd.isEmbedded())
{
// Embedded field override
processEmbeddedAttributeOverride(mmd, (String)annotationValues.get("name"),
member.getType(), (Column)annotationValues.get("column"));
}
else if (annName.equals(JPAAnnotationUtils.JOIN_TABLE))
{
// Process @JoinTable to generate JoinMetaData
String tableName = (String)annotationValues.get("name");
if (!StringUtils.isWhitespace(tableName))
{
mmd.setTable(tableName);
}
String catalogName = (String)annotationValues.get("catalog");
if (!StringUtils.isWhitespace(catalogName))
{
mmd.setCatalog(catalogName);
}
String schemaName = (String)annotationValues.get("schema");
if (!StringUtils.isWhitespace(schemaName))
{
mmd.setSchema(schemaName);
}
joinmd = new JoinMetaData();
mmd.setJoinMetaData(joinmd);
if (annotationValues.get("joinColumns") != null)
{
ArrayList<JoinColumn> joinColumns = new ArrayList<JoinColumn>();
joinColumns.addAll(Arrays.asList((JoinColumn[])annotationValues.get("joinColumns")));
for (int j = 0; j < joinColumns.size(); j++)
{
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(joinColumns.get(j).name());
colmd.setTarget(joinColumns.get(j).referencedColumnName());
colmd.setAllowsNull(joinColumns.get(j).nullable());
joinmd.addColumn(colmd);
}
}
if (annotationValues.get("inverseJoinColumns") != null)
{
ArrayList<JoinColumn> elementColumns = new ArrayList<JoinColumn>();
elementColumns.addAll(Arrays.asList((JoinColumn[])annotationValues.get("inverseJoinColumns")));
AbstractElementMetaData aemd = null;
if (Map.class.isAssignableFrom(member.getType()))
{
aemd = new ValueMetaData();
mmd.setValueMetaData((ValueMetaData)aemd);
}
else
{
aemd = new ElementMetaData();
mmd.setElementMetaData((ElementMetaData)aemd);
}
for (int j = 0; j < elementColumns.size(); j++)
{
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(elementColumns.get(j).name());
colmd.setTarget(elementColumns.get(j).referencedColumnName());
colmd.setAllowsNull(elementColumns.get(j).nullable());
aemd.addColumn(colmd);
}
}
UniqueConstraint[] joinUniqueConstraints = (UniqueConstraint[])annotationValues.get("uniqueConstraints");
if (joinUniqueConstraints != null && joinUniqueConstraints.length > 0)
{
// Unique constraints on the join table
for (int j=0;j<joinUniqueConstraints.length;j++)
{
UniqueMetaData unimd = new UniqueMetaData();
for (int k=0;k<joinUniqueConstraints[j].columnNames().length;k++)
{
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(joinUniqueConstraints[j].columnNames()[k]);
unimd.addColumn(colmd);
}
joinmd.setUniqueMetaData(unimd); // JDO only supports a single unique constraint on a join table
}
}
}
else if (annName.equals(JPAAnnotationUtils.COLLECTION_TABLE))
{
// Process @CollectionTable to generate JoinMetaData
String tableName = (String)annotationValues.get("name");
if (!StringUtils.isWhitespace(tableName))
{
mmd.setTable(tableName);
}
String catalogName = (String)annotationValues.get("catalog");
if (!StringUtils.isWhitespace(catalogName))
{
mmd.setCatalog(catalogName);
}
String schemaName = (String)annotationValues.get("schema");
if (!StringUtils.isWhitespace(schemaName))
{
mmd.setSchema(schemaName);
}
joinmd = mmd.getJoinMetaData();
if (joinmd == null)
{
// Should always be set by @ElementCollection but add just in case
joinmd = new JoinMetaData();
mmd.setJoinMetaData(joinmd);
}
if (annotationValues.get("joinColumns") != null)
{
ArrayList<JoinColumn> joinColumns = new ArrayList<JoinColumn>();
joinColumns.addAll(Arrays.asList((JoinColumn[])annotationValues.get("joinColumns")));
for (int j = 0; j < joinColumns.size(); j++)
{
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(joinColumns.get(j).name());
colmd.setTarget(joinColumns.get(j).referencedColumnName());
colmd.setAllowsNull(joinColumns.get(j).nullable());
joinmd.addColumn(colmd);
}
}
UniqueConstraint[] joinUniqueConstraints = (UniqueConstraint[])annotationValues.get("uniqueConstraints");
if (joinUniqueConstraints != null && joinUniqueConstraints.length > 0)
{
// Unique constraints on the join table
for (int j=0;j<joinUniqueConstraints.length;j++)
{
UniqueMetaData unimd = new UniqueMetaData();
for (int k=0;k<joinUniqueConstraints[j].columnNames().length;k++)
{
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(joinUniqueConstraints[j].columnNames()[k]);
unimd.addColumn(colmd);
}
joinmd.setUniqueMetaData(unimd); // JDO only supports a single unique constraint on a join table
}
}
}
else if (annName.equals(JPAAnnotationUtils.MAP_KEY_COLUMN))
{
if (keymd == null)
{
keymd = new KeyMetaData();
mmd.setKeyMetaData(keymd);
}
String name = (String)annotationValues.get("name");
if (name != null)
{
keymd.setMappedBy(name);
}
Class keyType = mmd.getMap() != null && mmd.getMap().getKeyType() != null ? clr.classForName(mmd.getMap().getKeyType()) : Object.class;
keymd.addColumn(newColumnMetaData(keymd, keyType, annotations));
}
else if (annName.equals(JPAAnnotationUtils.MAP_KEY))
{
String keyMappedBy = (String)annotationValues.get("name");
if (keyMappedBy != null)
{
if (keymd == null)
{
keymd = new KeyMetaData();
mmd.setKeyMetaData(keymd);
}
keymd.setMappedBy(keyMappedBy);
if (mmd.getMap() != null &&
(mmd.getMap().getKeyType() == null || mmd.getMap().getKeyType().equals(Object.class.getName())))
{
// Set keyType based on mapped-by field of value class
String valueType = mmd.getMap().getValueType();
try
{
Class cls = clr.classForName(valueType);
try
{
Field fld = cls.getDeclaredField(keyMappedBy);
mmd.getMap().setKeyType(fld.getType().getName());
}
catch (NoSuchFieldException nsfe)
{
try
{
String getterName = ClassUtils.getJavaBeanGetterName(keyMappedBy, false);
Method mthd = cls.getDeclaredMethod(getterName, (Class[])null);
mmd.getMap().setKeyType(mthd.getReturnType().getName());
}
catch (NoSuchMethodException nsme)
{
}
}
}
catch (Exception e)
{
}
}
}
}
else if (annName.equals(JPAAnnotationUtils.MAP_KEY_ENUMERATED))
{
EnumType type = (EnumType)annotationValues.get("value");
if (keymd == null)
{
keymd = new KeyMetaData();
mmd.setKeyMetaData(keymd);
}
// TODO Merge with any @MapKey specification of the column
ColumnMetaData colmd = keymd.newColumnMetaData();
colmd.setJdbcType(type == EnumType.STRING ? "VARCHAR" : "INTEGER");
}
else if (annName.equals(JPAAnnotationUtils.ORDER_BY))
{
if (mmd.getOrderMetaData() != null)
{
throw new NucleusException("@OrderBy found yet field=" +
cmd.getFullClassName() + "." + member.getName() +
" already has ordering information!");
}
String orderBy = (String)annotationValues.get("value");
if (orderBy != null)
{
// "Ordered List"
OrderMetaData ordmd = new OrderMetaData();
ordmd.setOrdering(orderBy);
mmd.setOrderMetaData(ordmd);
}
}
else if (annName.equals(JPAAnnotationUtils.ORDER_COLUMN))
{
if (mmd.getOrderMetaData() != null)
{
throw new NucleusException("@OrderColumn found yet field=" +
cmd.getFullClassName() + "." + member.getName() +
" already has ordering information!");
}
String columnName = (String)annotationValues.get("name");
OrderMetaData ordermd = new OrderMetaData();
ordermd.setColumnName(columnName);
String colNullable = null;
String colInsertable = null;
String colUpdateable = null;
if (annotationValues.get("nullable") != null)
{
colNullable = annotationValues.get("nullable").toString();
}
if (annotationValues.get("insertable") != null)
{
colInsertable = annotationValues.get("insertable").toString();
}
if (annotationValues.get("updatable") != null)
{
// Note : "updatable" is spelt incorrectly in the JPA spec.
colUpdateable = annotationValues.get("updatable").toString();
}
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(columnName);
colmd.setAllowsNull(colNullable);
colmd.setInsertable(colInsertable);
colmd.setUpdateable(colUpdateable);
String tmp = (String)annotationValues.get("columnDefinition");
if (!StringUtils.isWhitespace(tmp))
{
colmd.setColumnDdl(tmp);
}
ordermd.addColumn(colmd);
mmd.setOrderMetaData(ordermd);
}
else if (annName.equals(JPAAnnotationUtils.ONE_TO_MANY))
{
// 1-N relation
oneToMany = true;
}
else if (annName.equals(JPAAnnotationUtils.MANY_TO_MANY))
{
// M-N relation
manyToMany = true;
}
}
// Post-processing to apply JPA rules for field relationships etc
if (oneToMany && mmd.getJoinMetaData() == null && mmd.getMappedBy() == null &&
jpaLevel.equalsIgnoreCase("JPA1"))
{
// 1-N with no join specified and unidirectional so JPA says it has to be via join (no 1-N uni FKs)
mmd.setJoinMetaData(new JoinMetaData());
}
if (manyToMany && mmd.getJoinMetaData() == null && mmd.getMappedBy() == null)
{
// M-N with no join specified and unidir so add the join for them
mmd.setJoinMetaData(new JoinMetaData());
}
if (mmd.getOrderMetaData() == null && Collection.class.isAssignableFrom(member.getType()))
{
// @OrderBy not specified but is a Collection so use ordering of element using PK field(s)
OrderMetaData ordmd = new OrderMetaData();
ordmd.setOrdering("#PK"); // Special value recognised by OrderMetaData
mmd.setOrderMetaData(ordmd);
}
if (columnMetaData == null)
{
// Column specified (at least in part) via @Column/@Lob/@Enumerated/@Temporal
ColumnMetaData colmd = newColumnMetaData(mmd, member.getType(), annotations);
if (colmd != null)
{
columnMetaData = new ColumnMetaData[1];
columnMetaData[0] = colmd;
}
}
if (columnMetaData != null)
{
// Column definition provided so apply to the respective place
if ((mmd.hasCollection() || mmd.hasArray()) && joinmd == null)
{
// Column is for the FK of the element of the collection/array
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd == null)
{
elemmd = new ElementMetaData();
mmd.setElementMetaData(elemmd);
}
for (int i=0;i<columnMetaData.length;i++)
{
elemmd.addColumn(columnMetaData[i]);
}
}
else if (mmd.hasMap() && joinmd == null)
{
// Column is for the FK value of the map
ValueMetaData valmd = mmd.getValueMetaData();
if (valmd == null)
{
valmd = new ValueMetaData();
mmd.setValueMetaData(valmd);
}
for (int i=0;i<columnMetaData.length;i++)
{
valmd.addColumn(columnMetaData[i]);
}
}
else if (elementCollection)
{
// Column is for element/value column(s) of join table of 1-N of non-PCs
if (mmd.hasCollection() || mmd.hasArray())
{
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd == null)
{
elemmd = new ElementMetaData();
mmd.setElementMetaData(elemmd);
}
for (int i=0;i<columnMetaData.length;i++)
{
elemmd.addColumn(columnMetaData[i]);
}
}
else if (mmd.hasMap())
{
ValueMetaData valmd = mmd.getValueMetaData();
if (valmd == null)
{
valmd = new ValueMetaData();
mmd.setValueMetaData(valmd);
}
for (int i=0;i<columnMetaData.length;i++)
{
valmd.addColumn(columnMetaData[i]);
}
}
}
else
{
// Column is for the member
for (int i=0;i<columnMetaData.length;i++)
{
mmd.addColumn(columnMetaData[i]);
}
}
}
return mmd;
}