package eu.etaxonomy.cdm.persistence.dao.initializer;\r
\r
import java.beans.PropertyDescriptor;\r
+import java.io.Serializable;\r
import java.lang.reflect.InvocationTargetException;\r
import java.util.ArrayList;\r
import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashSet;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Set;\r
\r
+import javax.persistence.Transient;\r
+\r
import org.apache.commons.beanutils.PropertyUtils;\r
-import org.apache.commons.lang.StringUtils;\r
import org.apache.log4j.Logger;\r
+import org.hibernate.Hibernate;\r
+import org.hibernate.HibernateException;\r
+import org.hibernate.Query;\r
+import org.hibernate.collection.internal.AbstractPersistentCollection;\r
+import org.hibernate.proxy.HibernateProxy;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;\r
import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;\r
\r
/**\r
*/\r
public class AdvancedBeanInitializer extends HibernateBeanInitializer {\r
\r
- public static final Logger logger = Logger.getLogger(AdvancedBeanInitializer.class);\r
+ public static final Logger logger = Logger.getLogger(AdvancedBeanInitializer.class);\r
\r
+ @Autowired\r
+ ICdmGenericDao genericDao;\r
+ \r
@Override\r
public void initialize(Object bean, List<String> propertyPaths) {\r
List<Object> beanList = new ArrayList<Object>(1);\r
System.out.println(rootPath.toStringTree());\r
\r
\r
- if(logger.isDebugEnabled()){\r
- logger.debug(">> starting to initialize beanlist ; class(e.g.):" + beanList.iterator().next().getClass().getSimpleName());\r
- }\r
+ if(logger.isDebugEnabled()){ logger.debug(">> starting to initialize beanlist ; class(e.g.):" + beanList.iterator().next().getClass().getSimpleName());}\r
rootPath.addBeans(beanList);\r
- initializeBean(rootPath);\r
+ initializeNodeRecursive(rootPath);\r
\r
\r
-// //old\r
-// if(logger.isDebugEnabled()){logger.debug("Start old initalizer ... ");};\r
-// Collections.sort(propertyPaths);\r
-// for(String propPath : propertyPaths){\r
-// initializePropertyPath(bean, propPath);\r
-// }\r
- if(logger.isDebugEnabled()){\r
- logger.debug(" Completed initialization of beanlist ");\r
+ //old - keep for safety (this may help to initialize those beans that are not yet correctly initialized by the AdvancedBeanInitializer\r
+ for (Object bean :beanList){\r
+ if(logger.isDebugEnabled()){logger.debug("Start old initalizer ... ");};\r
+ Collections.sort(propertyPaths);\r
+ for(String propPath : propertyPaths){\r
+ initializePropertyPath(bean, propPath);\r
+ }\r
}\r
+ \r
+ if(logger.isDebugEnabled()){ logger.debug(" Completed initialization of beanlist "); }\r
return beanList;\r
\r
}\r
\r
\r
//new\r
- private void initializeBean(BeanInitNode rootPath) {\r
- initializePropertyPath(rootPath);\r
+ private void initializeNodeRecursive(BeanInitNode rootPath) {\r
+ initializeNode(rootPath);\r
for (BeanInitNode childPath : rootPath.getChildrenList()){\r
- initializeBean(childPath);\r
+ initializeNodeRecursive(childPath);\r
}\r
rootPath.resetBeans();\r
}\r
* @param bean\r
* @param propPath\r
*/\r
- private void initializePropertyPath(BeanInitNode node) {\r
- if(logger.isDebugEnabled()){logger.debug("processing " + node.toString());}\r
- if (StringUtils.isBlank(node.getPath())){\r
+ private void initializeNode(BeanInitNode node) {\r
+ if(logger.isDebugEnabled()){logger.debug(" processing " + node.toString());}\r
+ if (node.isRoot()){\r
return;\r
- }\r
-\r
- if (node.isWildcard()){\r
- initializeWildcardPropertyPath(node);\r
+ }else if (node.isWildcard()){\r
+ initializeNodeWildcard(node);\r
} else {\r
- initializeNoWildcardPropertyPath(node);\r
+ initializeNodeNoWildcard(node);\r
}\r
}\r
\r
// if propPath only contains a wildcard (* or $)\r
// => do a batch initialization of *toOne or *toMany relations\r
- private void initializeWildcardPropertyPath(BeanInitNode node) {\r
- boolean initToMany = node.getPath().equals(LOAD_2ONE_2MANY_WILDCARD);\r
- for (Class<?> clazz : node.getParentBeans().keySet()){\r
- for (Object bean : node.getParentBeans().get(clazz)){\r
- \r
+ private void initializeNodeWildcard(BeanInitNode node) {\r
+ boolean initToMany = node.isToManyWildcard();\r
+ Map<Class<?>, Set<Object>> parentBeans = node.getParentBeans();\r
+ for (Class<?> clazz : parentBeans.keySet()){\r
+ //new\r
+ for (Object bean : parentBeans.get(clazz)){\r
+ \r
if(Collection.class.isAssignableFrom(bean.getClass())){\r
- initializeAllEntries((Collection<?>)bean, true, initToMany);\r
+// old: initializeAllEntries((Collection<?>)bean, true, initToMany); //TODO is this a possible case at all??\r
+ throw new RuntimeException("Collection no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");\r
} else if(Map.class.isAssignableFrom(bean.getClass())) {\r
- initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);\r
+ initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany); ////TODO is this a possible case at all?? \r
+ throw new RuntimeException("Map no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");\r
} else{\r
- initializeBean(bean, true, initToMany);\r
+ prepareBeanWildcardForBulkLoad(node, bean);\r
}\r
}\r
+ //end new\r
+ \r
+// initializeNodeWildcardOld(initToMany, beans, clazz); //if switched on move bulkLoadLazies up\r
}\r
+ \r
+ //\r
+ bulkLoadLazies(node);\r
+ }\r
+\r
+ /**\r
+ * @param initToMany\r
+ * @param beans\r
+ * @param clazz\r
+ */\r
+ private void initializeNodeWildcardOld(boolean initToMany,\r
+ Map<Class<?>, Set<Object>> beans, Class<?> clazz) {\r
+ for (Object bean : beans.get(clazz)){\r
+ \r
+ if(Collection.class.isAssignableFrom(bean.getClass())){\r
+ initializeAllEntries((Collection<?>)bean, true, initToMany);\r
+ } else if(Map.class.isAssignableFrom(bean.getClass())) {\r
+ initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);\r
+ } else{\r
+ initializeBean(bean, true, initToMany);\r
+ }\r
+ }\r
}\r
+ \r
+ private void prepareBeanWildcardForBulkLoad(BeanInitNode node, Object bean){\r
+\r
+ if(logger.isDebugEnabled()){logger.debug(">> prepare bulk wildcard initialization of a bean of type " + bean.getClass().getSimpleName()); }\r
+ Set<Class<?>> restrictions = new HashSet<Class<?>>();\r
+ restrictions.add(CdmBase.class);\r
+ if(node.isToManyWildcard()){\r
+ restrictions.add(Collections.class);\r
+ }\r
+ Set<PropertyDescriptor> props = getProperties(bean, restrictions);\r
+ for(PropertyDescriptor propertyDescriptor : props){\r
+ try {\r
+ String property = propertyDescriptor.getName();\r
+ \r
+// invokeInitialization(bean, propertyDescriptor);\r
+ Object propertyValue = PropertyUtils.getProperty( bean, property);\r
+ \r
+ preparePropertyValueForBulkLoad(node, bean, property, propertyValue );\r
+\r
+ } catch (IllegalAccessException e) {\r
+ logger.error("Illegal access on property " + propertyDescriptor.getName());\r
+ } catch (InvocationTargetException e) {\r
+ logger.info("Cannot invoke property " + propertyDescriptor.getName() + " not found");\r
+ } catch (NoSuchMethodException e) {\r
+ logger.info("Property " + propertyDescriptor.getName() + " not found");\r
+ }\r
+ }\r
+ if(logger.isDebugEnabled()){logger.debug(" completed bulk wildcard initialization of a bean");}\r
+ }\r
+\r
+ \r
\r
// propPath contains either a single field or a nested path\r
// split next path token off and keep the remaining as nestedPath\r
- private void initializeNoWildcardPropertyPath(BeanInitNode node) {\r
+ private void initializeNodeNoWildcard(BeanInitNode node) {\r
\r
String property = node.getPath();\r
int pos;\r
try {\r
//Class targetClass = HibernateProxyHelper.getClassWithoutInitializingProxy(bean); // used for debugging\r
\r
- // [1] initialize the bean named by property\r
- for (Class<?> clazz : node.getParentBeans().keySet()){\r
- Set<Object> beans = node.getParentBeans().get(clazz);\r
- if (logger.isDebugEnabled()){logger.debug("invoke initialization beans of class "+clazz+" ... ");}\r
- \r
- for (Object bean : beans){\r
- \r
- PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(bean, property);\r
- if (logger.isDebugEnabled()){logger.debug("invoke initialization "+node+" ... ");}\r
- Object unwrappedPropertyBean = invokeInitialization(bean, propertyDescriptor);\r
- if (logger.isDebugEnabled()){logger.debug("invoke initialization "+node+" - DONE ");}\r
- \r
- \r
- // [2]\r
- // recurse into nested properties\r
- if(unwrappedPropertyBean != null ){\r
- // for (BeanInitNode childNode : node.getChildrenList()){\r
- Collection<?> collection = null;\r
- if(Map.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
- collection = ((Map<?,?>)unwrappedPropertyBean).values();\r
- }else if (Collection.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
- collection = (Collection<?>) unwrappedPropertyBean; \r
- }\r
- if (collection != null){\r
- //collection or map\r
- if (logger.isDebugEnabled()){logger.debug(" initialize collection for " + node.toString() + " ... ");}\r
- int i = 0;\r
- for (Object entrybean : collection) {\r
- if(index == null){\r
- node.addBean(entrybean);\r
- // initializePropertyPath(entrybean, childNode);\r
- } else if(index.equals(i)){\r
- node.addBean(entrybean);\r
- // initializePropertyPath(entrybean, childNode);\r
- break;\r
- }\r
- i++;\r
- }\r
- if (logger.isDebugEnabled()){logger.debug(" initialize collection for " + node.toString() + " - DONE ");}\r
- \r
- }else {\r
- // nested bean\r
- node.addBean(unwrappedPropertyBean);\r
- // initializePropertyPath(unwrappedPropertyBean, childNode);\r
- setProperty(bean, property, unwrappedPropertyBean);\r
- }\r
- }\r
- }\r
-// }\r
+ for (Class<?> parentClazz : node.getParentBeans().keySet()){\r
+ if (logger.isDebugEnabled()){logger.debug(" invoke initialization on "+ node.toString()+ " beans of class " + parentClazz.getSimpleName() + " ... ");}\r
+ \r
+ Set<Object> parentBeans = node.getParentBeans().get(parentClazz);\r
+ \r
+ if (index != null){\r
+ logger.warn("Property path index not yet implemented for 'new'");\r
+ }\r
+ //new \r
+ for (Object parentBean : parentBeans){\r
+ Object propertyValue = PropertyUtils.getProperty(parentBean, property);\r
+ preparePropertyValueForBulkLoad(node, parentBean, property, propertyValue);\r
+ }\r
+ bulkLoadLazies(node);\r
+ \r
+ //end new\r
+ \r
+// initializeNodeNoWildcardOld(node, property, index, parentBeans);\r
} \r
\r
} catch (IllegalAccessException e) {\r
}\r
}\r
\r
+ /**\r
+ * @param node\r
+ * @param property\r
+ * @param index\r
+ * @param parentBeans\r
+ * @throws IllegalAccessException\r
+ * @throws InvocationTargetException\r
+ * @throws NoSuchMethodException\r
+ */\r
+ private void initializeNodeNoWildcardOld(BeanInitNode node,\r
+ String property, Integer index, Set<Object> parentBeans)\r
+ throws IllegalAccessException, InvocationTargetException,\r
+ NoSuchMethodException {\r
+ for (Object bean : parentBeans){\r
+\r
+ PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(bean, property);\r
+ if (logger.isDebugEnabled()){logger.debug(" unwrap " + node.toStringNoWildcard() + " ... ");}\r
+ // [1] initialize the bean named by property\r
+ Object unwrappedPropertyBean = invokeInitialization(bean, propertyDescriptor);\r
+ if (logger.isDebugEnabled()){logger.debug(" unwrap " + node.toStringNoWildcard() + " - DONE ");}\r
+\r
+\r
+ // [2]\r
+ // handle property\r
+ if(unwrappedPropertyBean != null ){\r
+ initializeNodeSinglePropertyOld(node, property, index, bean, unwrappedPropertyBean);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param node\r
+ * @param propertyValue\r
+ * @param parentBean \r
+ * @param param \r
+ */\r
+ private void preparePropertyValueForBulkLoad(BeanInitNode node, Object parentBean, String param, Object propertyValue) {\r
+ BeanInitNode sibling = node.getSibling(param);\r
+ if (propertyValue instanceof AbstractPersistentCollection ){\r
+ if (!node.hasWildcardToManySibling()){ //if wildcard exists the lazies are already prepared\r
+ Class<?> parentClass = parentBean.getClass();\r
+ int parentId = ((CdmBase)parentBean).getId();\r
+ if (sibling != null){\r
+ sibling.putLazyCollection(parentClass, param, parentId);\r
+ }else{\r
+ node.putLazyCollection(parentClass, param, parentId);\r
+ }\r
+ }\r
+ }else{\r
+ if (!node.hasWildcardToOneSibling()){ //if wildcard exists the lazies are already prepared\r
+ if (! Hibernate.isInitialized(propertyValue)){\r
+ if (propertyValue instanceof HibernateProxy){\r
+ Serializable id = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getIdentifier();\r
+ Class<?> persistedClass = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getPersistentClass();\r
+ if (sibling != null){\r
+ sibling.putLazyBean(persistedClass, id);\r
+ }else{\r
+ node.putLazyBean(persistedClass, id);\r
+ }\r
+ \r
+ }else{\r
+ logger.warn("Lazy value is not of type HibernateProxy. This is not yet handled.");\r
+ }\r
+ }else if (propertyValue == null){\r
+ // System.out.println("Single: property is null");\r
+ }else{\r
+ // System.out.println("Single: " + propertyValue);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private void bulkLoadLazies(BeanInitNode node) {\r
+ \r
+ if (logger.isDebugEnabled()){logger.debug("bulk load " + node);}\r
+ \r
+ //beans\r
+ for (Class<?> clazz : node.getLazyBeans().keySet()){\r
+ Set<Serializable> idSet = node.getLazyBeans().get(clazz);\r
+ if (idSet != null && ! idSet.isEmpty()){\r
+ \r
+ if (logger.isDebugEnabled()){logger.debug("bulk load beans of class " + clazz.getSimpleName());}\r
+ //TODO use entity name\r
+ String hql = " FROM " + clazz.getSimpleName() + " WHERE id IN (:idSet) ";\r
+ Query query = genericDao.getHqlQuery(hql);\r
+ query.setParameterList("idSet", idSet);\r
+ List<Object> list = query.list();\r
+ \r
+ if (logger.isDebugEnabled()){logger.debug("initialize bulk loaded beans of class " + clazz.getSimpleName());}\r
+ for (Object object : list){\r
+ if (object instanceof HibernateProxy){\r
+ object = initializeInstance(object);\r
+ }\r
+ node.addBean(object);\r
+ }\r
+ if (logger.isDebugEnabled()){logger.debug("bulk load - DONE");}\r
+ } \r
+ }\r
+ node.resetLazyBeans();\r
+ \r
+ //collections\r
+ for (Class<?> ownerClazz : node.getLazyCollections().keySet()){\r
+ Map<String, Set<Serializable>> lazyParams = node.getLazyCollections().get(ownerClazz);\r
+ for (String param : lazyParams.keySet()){\r
+ Set<Serializable> idSet = lazyParams.get(param);\r
+ if (idSet != null && ! idSet.isEmpty()){\r
+ if (logger.isDebugEnabled()){logger.debug("bulk load " + node + " collections ; ownerClass=" + ownerClazz.getSimpleName() + " ; param = " + param);}\r
+ \r
+ //TODO use entity name ??\r
+ //get from repository\r
+ List<Object> list;\r
+ try {\r
+ String hql = "SELECT oc.%s " +\r
+ " FROM %s as oc WHERE oc.id IN (:idSet) ";\r
+ param = workAroundBeanInconsistency(param, ownerClazz.getSimpleName());\r
+ hql = String.format(hql, param, ownerClazz.getSimpleName());\r
+ Query query = genericDao.getHqlQuery(hql);\r
+ query.setParameterList("idSet", idSet);\r
+ list = query.list();\r
+ } catch (HibernateException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ throw e;\r
+ }\r
+ \r
+ //getTarget and add to child node\r
+ if (logger.isDebugEnabled()){logger.debug("initialize bulk loaded " + node + " collections - DONE");}\r
+ for (Object newBean : list){\r
+ if (newBean instanceof HibernateProxy){\r
+ newBean = initializeInstance(newBean);\r
+ }\r
+ node.addBean(newBean);\r
+ }\r
+ if (logger.isDebugEnabled()){logger.debug("bulk load " + node + " collections - DONE");}\r
+ \r
+ \r
+ } \r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ }\r
+ node.resetLazyCollections();\r
+ \r
+ if (logger.isDebugEnabled()){logger.debug("bulk load " + node + " - DONE ");}\r
+ \r
+ }\r
+\r
+ \r
+ /**\r
+ * Rename bean attributes to hibernate (field) attribute, due to bean inconsistencies\r
+ * #3841\r
+ * @param param\r
+ * @param ownerClass \r
+ * @return\r
+ */\r
+ private String workAroundBeanInconsistency(String param, String ownerClass) {\r
+ if (ownerClass.contains("Description") && param.equals("elements")){\r
+ //DescriptionBase.descriptionElements -> elements\r
+ return "descriptionElements";\r
+ }else if(ownerClass.equals("Classification") && param.equals("childNodes")){\r
+ return "rootNodes";\r
+ }else{\r
+ return param;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param node\r
+ * @param property\r
+ * @param index\r
+ * @param bean\r
+ * @param unwrappedPropertyBean\r
+ */\r
+ private void initializeNodeSinglePropertyOld(BeanInitNode node, String property,\r
+ Integer index, Object bean, Object unwrappedPropertyBean) {\r
+ Collection<?> collection = null;\r
+ if(Map.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
+ collection = ((Map<?,?>)unwrappedPropertyBean).values();\r
+ }else if (Collection.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
+ collection = (Collection<?>) unwrappedPropertyBean; \r
+ }\r
+ if (collection != null){\r
+ //collection or map\r
+ if (logger.isDebugEnabled()){logger.debug(" initialize collection for " + node.toStringNoWildcard() + " ... ");}\r
+ int i = 0;\r
+ for (Object entrybean : collection) {\r
+ if(index == null){\r
+ node.addBean(entrybean);\r
+ } else if(index.equals(i)){\r
+ node.addBean(entrybean);\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ if (logger.isDebugEnabled()){logger.debug(" initialize collection for " + node.toString() + " - DONE ");}\r
+ \r
+ }else {\r
+ // nested bean\r
+ node.addBean(unwrappedPropertyBean);\r
+ setProperty(bean, property, unwrappedPropertyBean);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * This is an adaptation of {@link AbstractBeanInitializer#getProperties(Object, Set)}\r
+ * which handles typeRestrictions different (correct IMO).\r
+ * The only difference is that it handles type restrictions also when they have\r
+ * size = 1\r
+ * \r
+ * \r
+ * @param bean\r
+ * @param typeRestrictions\r
+ * @return\r
+ */\r
+ public static Set<PropertyDescriptor> getProperties(Object bean, Set<Class<?>> typeRestrictions) {\r
+\r
+ Set<PropertyDescriptor> properties = new HashSet<PropertyDescriptor>();\r
+ PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(bean);\r
+\r
+ for (PropertyDescriptor prop : props) {\r
+ //String propName = prop[i].getName();\r
+\r
+ // only read methods & skip transient getters\r
+ if( prop.getReadMethod() != null ){\r
+ try{\r
+ Class<Transient> transientClass = (Class<Transient>)Class.forName( "javax.persistence.Transient" );\r
+ if( prop.getReadMethod().getAnnotation( transientClass ) != null ){\r
+ continue;\r
+ }\r
+ }catch( ClassNotFoundException cnfe ){\r
+ // ignore\r
+ }\r
+ if(typeRestrictions != null ){\r
+ for(Class<?> restrictedType : typeRestrictions){\r
+ if(restrictedType.isAssignableFrom(prop.getPropertyType())){\r
+ properties.add(prop);\r
+ }\r
+ }\r
+ } else {\r
+ properties.add(prop);\r
+ }\r
+ }\r
+ }\r
+ return properties;\r
+ }\r
+\r
}\r
*/\r
package eu.etaxonomy.cdm.persistence.dao.initializer;\r
\r
+import java.io.Serializable;\r
import java.util.ArrayList;\r
import java.util.Collection;\r
import java.util.Collections;\r
import java.util.Map;\r
import java.util.Set;\r
\r
+import org.apache.commons.lang.StringUtils;\r
+\r
import eu.etaxonomy.cdm.common.CdmUtils;\r
\r
/**\r
*/\r
public class BeanInitNode implements Comparable<BeanInitNode>{\r
\r
+ // ************************ ATTRIBUTES *******************************/\r
+ \r
private BeanInitNode parent;\r
\r
private Map<String, BeanInitNode> children = new HashMap<String, BeanInitNode>();\r
\r
private boolean isToOneInitialized = false;\r
\r
+ private BeanInitNode wildcardChildCache;\r
+ \r
+ \r
private Map<Class<?>, Set<Object>> beans = new HashMap<Class<?>, Set<Object>>();\r
\r
+ private Map<Class<?>, Set<Serializable>> lazyBeans = new HashMap<Class<?>, Set<Serializable>>();\r
\r
+ private Map<Class<?>, Map<String, Set<Serializable>>> lazyCollections = new HashMap<Class<?>, Map<String,Set<Serializable>>>();\r
+ \r
+// *************************** STATIC METHODS *****************************************/\r
\r
- public BeanInitNode(BeanInitNode parent, String part) {\r
- this.path = CdmUtils.Nz(part);\r
- this.parent = parent;\r
- if (parent != null){\r
- parent.addChild(part, this);\r
- }\r
- }\r
-\r
- private void addChild(String part, BeanInitNode child) {\r
- children.put(part, child);\r
- if (child.isWildcard()){\r
- if (part.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD)){\r
- this.isToManyInitialized = true;\r
- }\r
- this.isToOneInitialized = true;\r
- }\r
- }\r
-\r
-\r
public static BeanInitNode createInitTree(List<String> propertyPaths) {\r
\r
//sort paths //TODO needed?\r
\r
return root;\r
}\r
-\r
-\r
- public List<BeanInitNode> getChildrenList() {\r
- List<BeanInitNode> result = new ArrayList<BeanInitNode>(children.values());\r
- Collections.sort(result);\r
- return result;\r
+ \r
+ private static boolean isWildcard(String pathPart) {\r
+ return pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) || \r
+ pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);\r
}\r
\r
\r
- public void addBean(Object bean) {\r
- if (bean != null){\r
- Class<?> key = bean.getClass();\r
- Set<Object> classedBeans = beans.get(key);\r
- if (classedBeans == null){\r
- classedBeans = new HashSet<Object>();\r
- beans.put(key, classedBeans);\r
- }\r
- classedBeans.add(bean);\r
+//***************************** CONSTRUCTOR RELATED ****************************************/ \r
+ \r
+ public BeanInitNode(BeanInitNode parent, String part) {\r
+ this.path = CdmUtils.Nz(part);\r
+ this.parent = parent;\r
+ this.isToManyInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);\r
+ this.isToOneInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) || this.isToManyInitialized;\r
+ if (parent != null){\r
+ parent.addChild(part, this);\r
}\r
}\r
- public void addBeans(Collection<?> beans) {\r
- for (Object bean : beans){\r
- addBean(bean);\r
+\r
+ private void addChild(String part, BeanInitNode child) {\r
+ children.put(part, child);\r
+ if (child.isWildcard()){\r
+ //set wildcard child if not exists or if child is stronger then existing wildcard child \r
+ if (this.wildcardChildCache == null || (! this.wildcardChildCache.isToManyInitialized) && child.isToManyInitialized ){\r
+ this.wildcardChildCache = child;\r
+ }\r
}\r
}\r
\r
- private Map<Class<?>, Set<Object>> getClassedBeans(){\r
- return this.beans;\r
- }\r
+// ************************** ***********************************************************/\r
\r
- public void resetBeans(){\r
- beans.clear();\r
+ public BeanInitNode getChild(String param){\r
+ return children.get(param);\r
}\r
\r
+\r
+\r
+ public List<BeanInitNode> getChildrenList() {\r
+ List<BeanInitNode> result = new ArrayList<BeanInitNode>(children.values());\r
+ Collections.sort(result);\r
+ return result;\r
+ }\r
+ \r
+ public BeanInitNode getSibling(String param) {\r
+ if (parent == null){\r
+ return null;\r
+ }else{\r
+ return parent.getChild(param);\r
+ }\r
+ }\r
+ \r
public String getPath() {\r
return path;\r
}\r
+ \r
+ public boolean isRoot() {\r
+ return StringUtils.isBlank(path);\r
+ }\r
\r
public boolean hasChildren() {\r
return children.size() > 0;\r
}\r
\r
-\r
+ public BeanInitNode getWildcardChild(){\r
+ return this.wildcardChildCache;\r
+ }\r
public boolean isWildcard() {\r
- return path.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) || \r
- path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);\r
+ return this.isToManyInitialized || this.isToOneInitialized;\r
}\r
+ public boolean hasWildcardChild() {\r
+ return this.wildcardChildCache != null;\r
+ }\r
+ public boolean hasToManyWildcardChild() {\r
+ return this.wildcardChildCache != null;\r
+ }\r
+\r
+ public boolean hasWildcardToManySibling() {\r
+ BeanInitNode sibl = getWildcardSibling();\r
+ return (sibl != null && sibl.isToManyInitialized);\r
+ }\r
+\r
+ private BeanInitNode getWildcardSibling() {\r
+ if (!isWildcard() && parent == null){\r
+ return parent.getWildcardChild();\r
+ }else{\r
+ return null;\r
+ }\r
+ }\r
+\r
\r
public boolean isToManyWildcard() {\r
return path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);\r
}\r
\r
\r
- public boolean isInitializedIfSingle(){\r
- return parent.isToOneInitialized;\r
+// ******************* LAZY COLLECTION *****************************************/\r
+ public void putLazyCollection(Class<?> ownerClazz, String parameter, Serializable id) {\r
+ if (ownerClazz != null && parameter != null && id != null){\r
+ Map<String, Set<Serializable>> lazyParams = lazyCollections.get(ownerClazz);\r
+ if (lazyParams == null){\r
+ lazyParams = new HashMap<String, Set<Serializable>>();\r
+ lazyCollections.put(ownerClazz, lazyParams);\r
+ }\r
+ Set<Serializable> layzIds = lazyParams.get(parameter);\r
+ if (layzIds == null){\r
+ layzIds = new HashSet<Serializable>();\r
+ lazyParams.put(parameter, layzIds);\r
+ }\r
+ layzIds.add(id);\r
+ }else{\r
+ throw new IllegalArgumentException("Class, parameter and id should not be null");\r
+ }\r
+ }\r
+ public Map<Class<?>, Map<String, Set<Serializable>>> getLazyCollections(){\r
+ return this.lazyCollections;\r
+ }\r
+ public void resetLazyCollections(){\r
+ this.lazyCollections.clear();\r
+ }\r
+\r
+ \r
+// ******************* LAZY BEAN *****************************************/\r
+ \r
+ public void putLazyBean(Class<?> clazz, Serializable id) {\r
+ if (clazz != null && id != null){\r
+ Set<Serializable> classedLazies= lazyBeans.get(clazz);\r
+ if (classedLazies == null){\r
+ classedLazies = new HashSet<Serializable>();\r
+ lazyBeans.put(clazz, classedLazies);\r
+ }\r
+ classedLazies.add(id);\r
+ }else{\r
+ throw new IllegalArgumentException("Class and id should not be null");\r
+ }\r
+ }\r
+ public Map<Class<?>, Set<Serializable>> getLazyBeans(){\r
+ return this.lazyBeans;\r
+ }\r
+ public void resetLazyBeans(){\r
+ this.lazyBeans.clear();\r
+ }\r
+ \r
+// ********************* BEANS ******************************/\r
+ \r
+ private Map<Class<?>, Set<Object>> getClassedBeans(){\r
+ return this.beans;\r
+ }\r
+ \r
+ \r
+ public Map<Class<?>, Set<Object>> getBeans() {\r
+ return this.beans;\r
}\r
\r
- public boolean isInitializedAny(){\r
- return parent.isToManyInitialized;\r
+ public Map<Class<?>, Set<Object>> getParentBeans() {\r
+ if (parent == null){\r
+ return new HashMap<Class<?>, Set<Object>>();\r
+ }else{\r
+ return parent.getClassedBeans();\r
+ }\r
}\r
\r
+ public void addBean(Object bean) {\r
+ if (! isWildcard()){\r
+ if (bean != null){\r
+ Class<?> key = bean.getClass();\r
+ Set<Object> classedBeans = beans.get(key);\r
+ if (classedBeans == null){\r
+ classedBeans = new HashSet<Object>();\r
+ beans.put(key, classedBeans);\r
+ }\r
+ classedBeans.add(bean);\r
+ }\r
+ }\r
+ }\r
+ public void addBeans(Collection<?> beans) {\r
+ for (Object bean : beans){\r
+ addBean(bean);\r
+ }\r
+ }\r
+ \r
+ public void resetBeans(){\r
+ beans.clear();\r
+ }\r
+\r
+\r
+// ************************* OVERRIDES **********************************/\r
+ \r
@Override\r
public int compareTo(BeanInitNode o) {\r
String toMany = AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD;\r
public String toString() {\r
\r
if(parent == null){\r
- return "/";\r
+ return "/"; //for root node\r
}else{\r
- return parent.toString() + ((parent.parent == null) ? "" : ".") + path;\r
+ String result = parent.toString() + ((parent.parent == null) ? "" : ".") + path;\r
+ return result;\r
}\r
}\r
\r
+ public String toStringNoWildcard(){\r
+ return toString().replace(".$", "").replace(".*", "");\r
+ }\r
+ \r
public String toStringTree() {\r
\r
- String result = (path.equals("")? "/": path) + "\n";\r
+ String result = (path.equals("") ? "/" : path) + "\n";\r
+ \r
for (BeanInitNode child : getChildrenList()){\r
- result += toString() + "." + child.toStringTree();\r
+ result += toString() + (result.endsWith("/\n") ? "" : ".") + child.toStringTree();\r
}\r
\r
return result;\r
}\r
\r
- public Map<Class<?>, Set<Object>> getParentBeans() {\r
- if (parent == null){\r
- return new HashMap<Class<?>, Set<Object>>();\r
- }else{\r
- return parent.getClassedBeans();\r
- }\r
+ public boolean hasWildcardToOneSibling() {\r
+ BeanInitNode sibl = getWildcardSibling();\r
+ return (sibl != null && sibl.isToOneInitialized);\r
}\r
\r
-\r
+ \r
}\r