private ClassMetaData parseClassAnnotations() {
// Check to see if there is cached metadata for the class that we are currently parsing. It
// is possible that one of the annotations (Entity, Embeddable, MappedSuperclass) is in the
// orm.xml. We still need to look at these files for other annotations and more importantly
// setup defaults (ie: Basic fields).
ClassMetaData m = getRepository().getCachedMetaData(_cls);
if (m == null) {
if (!(AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls, Entity.class)))
.booleanValue()
&& !(AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls, Embeddable.class)))
.booleanValue()
&& !(AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls,
MappedSuperclass.class))).booleanValue())
return null;
}
// find / create metadata
ClassMetaData meta = (m == null) ? getMetaData() : m;
if (meta == null)
return null;
Entity entity = _cls.getAnnotation(Entity.class);
MappedSuperclass mapped = _cls.getAnnotation(MappedSuperclass.class);
Embeddable embeddable = _cls.getAnnotation(Embeddable.class);
if (isMetaDataMode()) {
meta.setAbstract(mapped != null);
if (embeddable != null) meta.setEmbeddable();
// while the spec only provides for embedded exclusive, it doesn't
// seem hard to support otherwise
if (entity == null)
meta.setEmbeddedOnly(true);
else {
meta.setEmbeddedOnly(false);
if (!StringUtils.isEmpty(entity.name()))
meta.setTypeAlias(entity.name());
}
}
// track fetch groups to parse them after fields, since they
// rely on field metadata
FetchGroup[] fgs = null;
DetachedState detached = null;
// track listeners since we need to merge them with entity callbacks
Collection<LifecycleCallbacks>[] listeners = null;
MetaDataTag tag;
for (Annotation anno : _cls.getDeclaredAnnotations()) {
tag = _tags.get(anno.annotationType());
if (tag == null) {
handleUnknownClassAnnotation(meta, anno);
continue;
}
switch (tag) {
case ENTITY_LISTENERS:
if (isMetaDataMode())
listeners = parseEntityListeners(meta,
(EntityListeners) anno);
break;
case EXCLUDE_DEFAULT_LISTENERS:
if (isMetaDataMode())
meta.getLifecycleMetaData()
.setIgnoreSystemListeners(true);
break;
case EXCLUDE_SUPERCLASS_LISTENERS:
if (isMetaDataMode())
meta.getLifecycleMetaData().setIgnoreSuperclassCallbacks
(LifecycleMetaData.IGNORE_HIGH);
break;
case FLUSH_MODE:
if (isMetaDataMode())
warnFlushMode(meta);
break;
case ID_CLASS:
if (isMetaDataMode()) {
Class<?> idClass = ((IdClass)anno).value();
if (!Serializable.class.isAssignableFrom(idClass)) {
_log.warn(_loc.get("id-class-not-serializable", idClass, _cls).toString());
}
meta.setObjectIdType(((IdClass) anno).value(), true);
}
break;
case NATIVE_QUERIES:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
parseNamedNativeQueries(_cls,
((NamedNativeQueries) anno).value());
break;
case NATIVE_QUERY:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
parseNamedNativeQueries(_cls, (NamedNativeQuery) anno);
break;
case QUERIES:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
parseNamedQueries(_cls, ((NamedQueries) anno).value());
break;
case QUERY:
if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
parseNamedQueries(_cls, (NamedQuery) anno);
break;
case SEQ_GENERATOR:
if (isMappingOverrideMode())
parseSequenceGenerator(_cls, (SequenceGenerator) anno);
break;
case DATA_CACHE:
if (isMetaDataMode())
parseDataCache(meta, (DataCache) anno);
break;
case DATASTORE_ID:
if (isMetaDataMode())
parseDataStoreId(meta, (DataStoreId) anno);
break;
case DETACHED_STATE:
detached = (DetachedState) anno;
break;
case FETCH_GROUP:
if (isMetaDataMode())
fgs = new FetchGroup[]{ (FetchGroup) anno };
break;
case FETCH_GROUPS:
if (isMetaDataMode())
fgs = ((FetchGroups) anno).value();
break;
case MANAGED_INTERFACE:
if (isMetaDataMode())
parseManagedInterface(meta, (ManagedInterface) anno);
break;
case ACCESS:
if (isMetaDataMode())
parseAccess(meta, (Access)anno);
break;
case CACHEABLE:
if (isMetaDataMode()) {
parseCache(meta, (Cacheable) anno);
}
break;
default:
throw new UnsupportedException(_loc.get("unsupported", _cls,
anno.toString()));
}
}
if (isMetaDataMode()) {
parseDetachedState(meta, detached);
// merge callback methods with declared listeners
int[] highs = null;
if (listeners != null) {
highs = new int[listeners.length];
for (int i = 0; i < listeners.length; i++)
if (listeners[i] != null)
highs[i] = listeners[i].size();
}
recordCallbacks(meta, parseCallbackMethods(_cls, listeners, false,
false, getRepository()), highs, false);
// scan possibly non-PC hierarchy for callbacks.
// redundant for PC superclass but we don't know that yet
// so let LifecycleMetaData determine that
if (_cls.getSuperclass() != null &&
!Object.class.equals(_cls.getSuperclass())) {
recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
null, true, false, getRepository()), null, true);
}
}
for (FieldMetaData fmd : meta.getDeclaredFields())
if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
parseMemberAnnotations(fmd);
// parse fetch groups after fields
if (fgs != null)
parseFetchGroups(meta, fgs);
// always parse mapping after metadata in case there are dependencies
if (isMappingOverrideMode()) {
parseClassMappingAnnotations(meta);
for (FieldMetaData fmd : meta.getDeclaredFields())
if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
parseMemberMappingAnnotations(fmd);
}
return meta;
}