// can only have one field with this extension
for (String extension : ONE_OR_ZERO_EXTENSIONS) {
if (ammd.hasExtension(extension)) {
if (!foundOneOrZeroExtensions.add(extension)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.MoreThanOneFieldWithExtension",
acmd.getFullClassName(), extension);
}
}
}
if (ammd.hasExtension(DatastoreManager.ENCODED_PK)) {
if (!ammd.isPrimaryKey() || !ammd.getType().equals(String.class)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ExtensionForStringPK",
ammd.getFullFieldName(), DatastoreManager.ENCODED_PK);
}
}
if (ammd.hasExtension(DatastoreManager.PK_NAME)) {
if (!ammd.getType().equals(String.class)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ExtensionForStringField",
ammd.getFullFieldName(), DatastoreManager.PK_NAME);
}
}
if (ammd.hasExtension(DatastoreManager.PK_ID)) {
if (!ammd.getType().equals(Long.class) && !ammd.getType().equals(long.class)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ExtensionForLongField",
ammd.getFullFieldName(), DatastoreManager.PK_ID);
}
}
if (ammd.hasExtension(DatastoreManager.PARENT_PK)) {
if (noParentAllowed) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.PKAndParentPKInvalid",
ammd.getFullFieldName(), pkClass.getName());
}
if (!ammd.getType().equals(String.class) && !ammd.getType().equals(Key.class)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ParentPKType",
ammd.getFullFieldName());
}
}
for (String extension : NOT_PRIMARY_KEY_EXTENSIONS) {
if (ammd.hasExtension(extension) && ammd.isPrimaryKey()) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.FieldWithExtensionNotPK",
ammd.getFullFieldName(), extension);
}
}
// pk-name and pk-id only supported in conjunction with an encoded string
if (pkMemberMetaData != null) {
for (String extension : REQUIRES_ENCODED_STRING_PK_EXTENSIONS) {
if (ammd.hasExtension(extension)) {
if (!pkMemberMetaData.hasExtension(DatastoreManager.ENCODED_PK)) {
// we've already verified that encoded-pk is on a a String pk field
// so we don't need to check the type of the pk here.
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.FieldWithExtensionForEncodedString",
ammd.getFullFieldName(), extension);
}
}
}
}
if (ammd.hasCollection() && ammd.getCollection().isSerializedElement()) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.CollectionWithSerializedElementInvalid",
ammd.getFullFieldName());
}
else if (ammd.hasArray() && ammd.getArray().isSerializedElement()) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ArrayWithSerializedElementInvalid",
ammd.getFullFieldName());
}
checkForIllegalChildField(ammd, noParentAllowed);
if (ammd.getRelationType(clr) != RelationType.NONE) {
// Look for "eager" relationships. Not supported but not necessarily an error
// since we can always fall back to "lazy."
if (ammd.isDefaultFetchGroup() && !ammd.isEmbedded()) {
warn(String.format(
"Meta-data warning for %s.%s: %s %s %s",
acmd.getFullClassName(), ammd.getName(), GAE_LOCALISER.msg("AppEngine.MetaData.JoinsNotSupported", ammd.getFullFieldName()), "The field will be fetched lazily on first access.", ADJUST_WARNING_MSG));
// handleIgnorableMapping(acmd, ammd, "AppEngine.MetaData.JoinsNotSupported", "The field will be fetched lazily on first access.");
}
if (ammd.getRelationType(clr) == RelationType.MANY_TO_MANY_BI && MetaDataUtils.isOwnedRelation(ammd, storeMgr)) {
// We only support many-to-many for unowned relations
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ManyToManyRelationNotSupported",
ammd.getFullFieldName());
}
RelationType relType = ammd.getRelationType(clr);
if (ammd.getEmbeddedMetaData() == null &&
(relType == RelationType.ONE_TO_ONE_UNI || relType == RelationType.ONE_TO_ONE_BI ||
relType == RelationType.ONE_TO_MANY_UNI || relType == RelationType.ONE_TO_MANY_BI) &&
!getBooleanConfigProperty(ALLOW_MULTIPLE_RELATIONS_OF_SAME_TYPE) &&
!storeMgr.storageVersionAtLeast(StorageVersion.READ_OWNED_CHILD_KEYS_FROM_PARENTS)) {
// Check on multiple relations of the same type for early storage versions
Class<?> relationClass;
if (ammd.getCollection() != null) {
relationClass = clr.classForName(ammd.getCollection().getElementType());
} else if (ammd.getArray() != null) {
relationClass = clr.classForName(ammd.getArray().getElementType());
} else {
relationClass = clr.classForName(ammd.getTypeName());
}
// Add the actual type of the field to the list of types that can't
// repeat. If that type was already present, problem.
for (Class<?> existingRelationClass : nonRepeatableRelationTypes.keySet()) {
if (existingRelationClass.isAssignableFrom(relationClass) ||
relationClass.isAssignableFrom(existingRelationClass)) {
throw new InvalidMetaDataException(GAE_LOCALISER, "AppEngine.MetaData.ClassWithMultipleFieldsOfType",
acmd.getFullClassName(), relationClass.getName(), ammd.getName(), nonRepeatableRelationTypes.get(existingRelationClass));
}
}
nonRepeatableRelationTypes.put(relationClass, ammd.getName());
}