//$Id: HibernateEntityContext.java May 3, 2008 9:13:49 PM chaostone Exp $
/*
* Copyright c 2005-2009
* Licensed under GNU LESSER General Public License, Version 3.
* http://www.gnu.org/licenses
*/
/********************************************************************************
* @author chaostone
*
* MODIFICATION DESCRIPTION
*
* Name Date Description
* ============ ============ ============
* chaostone May 3, 2008 Created
*
********************************************************************************/
package org.beanfuse.entity.context;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.beanfuse.entity.Type;
import org.beanfuse.entity.types.CollectionType;
import org.beanfuse.entity.types.ComponentType;
import org.beanfuse.entity.types.EntityType;
import org.hibernate.EntityMode;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HibernateEntityContext extends AbstractEntityContext {
private static final Logger logger = LoggerFactory
.getLogger(HibernateEntityContext.class);
private final Map collectionTypes = new HashMap();
public void initFrom(SessionFactory sessionFactory) {
if (null != sessionFactory && entityTypes.isEmpty()) {
Map classMetadatas = sessionFactory.getAllClassMetadata();
for (Iterator iter = classMetadatas.values().iterator(); iter
.hasNext();) {
ClassMetadata cm = (ClassMetadata) iter.next();
buildEntityType(sessionFactory, cm.getEntityName());
}
logger.info("success confiure {} entity types from hibernate!",
new Integer(entityTypes.size()));
logger.info("success confiure {} collection types from hibernate!",
new Integer(collectionTypes.size()));
if (logger.isDebugEnabled()) {
loggerTypeInfo();
}
collectionTypes.clear();
}
}
private void loggerTypeInfo() {
List names = new ArrayList(entityTypes.keySet());
Collections.sort(names);
for (Iterator iter = names.iterator(); iter.hasNext();) {
String entityName = (String) iter.next();
EntityType entityType = (EntityType) entityTypes.get(entityName);
logger.debug("entity:{}-->{}", entityType.getEntityName(),
entityType.getEntityClass().getName());
logger.debug("propertyType size:{}", new Integer(entityType
.getPropertyTypes().size()));
}
names.clear();
names.addAll(collectionTypes.keySet());
Collections.sort(names);
for (Iterator iter = names.iterator(); iter.hasNext();) {
String entityName = (String) iter.next();
CollectionType collectionType = (CollectionType) collectionTypes
.get(entityName);
logger.debug("collection:{}", collectionType.getName());
logger.debug("class:{}", collectionType.getCollectionClass());
logger.debug("elementType:{}", collectionType.getElementType()
.getReturnedClass());
}
}
/**
* 按照实体名,构建或者查找实体类型信息.<br>
* 调用后,实体类型则存放与entityTypes中.
*
* @param entityName
* @return
*/
private EntityType buildEntityType(SessionFactory sessionFactory,
String entityName) {
EntityType entityType = (EntityType) entityTypes.get(entityName);
if (null == entityType) {
ClassMetadata cm = sessionFactory.getClassMetadata(entityName);
if (null == cm) {
logger.error("Cannot find ClassMetadata for {}", entityName);
return null;
}
entityType = new EntityType();
entityType.setEntityName(cm.getEntityName());
entityType.setIdPropertyName(cm.getIdentifierPropertyName());
entityType.setEntityClass(cm.getMappedClass(EntityMode.POJO));
entityTypes.put(cm.getEntityName(), entityType);
Map propertyTypes = entityType.getPropertyTypes();
String[] ps = cm.getPropertyNames();
for (int i = 0; i < ps.length; i++) {
org.hibernate.type.Type type = cm.getPropertyType(ps[i]);
if (type.isEntityType()) {
propertyTypes.put(ps[i], buildEntityType(sessionFactory,
type.getName()));
} else if (type.isComponentType()) {
propertyTypes.put(ps[i], buildComponentType(sessionFactory,
entityName, ps[i]));
} else if (type.isCollectionType()) {
propertyTypes.put(ps[i], buildCollectionType(
sessionFactory, defaultCollectionClass(type),
entityName + "." + ps[i]));
}
}
}
return entityType;
}
private CollectionType buildCollectionType(SessionFactory sessionFactory,
Class collectionClass, String role) {
CollectionMetadata cm = sessionFactory.getCollectionMetadata(role);
org.hibernate.type.Type type = cm.getElementType();
EntityType elementType = null;
if (type.isEntityType()) {
elementType = (EntityType) entityTypes.get(type.getName());
if (null == elementType) {
elementType = buildEntityType(sessionFactory, type.getName());
}
} else {
elementType = new EntityType(type.getReturnedClass());
}
CollectionType collectionType = new CollectionType();
collectionType.setElementType(elementType);
collectionType.setArray(cm.isArray());
collectionType.setCollectionClass(collectionClass);
if (!collectionTypes.containsKey(collectionType.getName())) {
collectionTypes.put(collectionType.getName(), collectionType);
}
return collectionType;
}
private ComponentType buildComponentType(SessionFactory sessionFactory,
String entityName, String propertyName) {
EntityType entityType = (EntityType) entityTypes.get(entityName);
if (null != entityType) {
Type propertyType = (Type) entityType.getPropertyTypes().get(
propertyName);
if (null != propertyType) {
return (ComponentType) propertyType;
}
}
ClassMetadata cm = sessionFactory.getClassMetadata(entityName);
org.hibernate.type.ComponentType hcType = (org.hibernate.type.ComponentType) cm
.getPropertyType(propertyName);
String[] propertyNames = hcType.getPropertyNames();
ComponentType cType = new ComponentType(hcType.getReturnedClass());
Map propertyTypes = cType.getPropertyTypes();
for (int j = 0; j < propertyNames.length; j++) {
org.hibernate.type.Type type = cm.getPropertyType(propertyName
+ "." + propertyNames[j]);
if (type.isEntityType()) {
propertyTypes.put(propertyNames[j], buildEntityType(
sessionFactory, type.getName()));
} else if (type.isComponentType()) {
propertyTypes.put(propertyNames[j], buildComponentType(
sessionFactory, entityName, propertyName + "."
+ propertyNames[j]));
} else if (type.isCollectionType()) {
propertyTypes.put(propertyNames[j], buildCollectionType(
sessionFactory, defaultCollectionClass(type),
entityName + "." + propertyName + "."
+ propertyNames[j]));
}
}
return cType;
}
private Class defaultCollectionClass(org.hibernate.type.Type collectionType) {
if (collectionType.isAnyType()) {
return null;
} else if (org.hibernate.type.SetType.class
.isAssignableFrom(collectionType.getClass())) {
return HashSet.class;
} else if (org.hibernate.type.MapType.class
.isAssignableFrom(collectionType.getClass())) {
return HashMap.class;
} else {
return ArrayList.class;
}
}
}