Java tutorial
/* * #%L * BroadleafCommerce Open Admin Platform * %% * Copyright (C) 2009 - 2013 Broadleaf Commerce * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package org.broadleafcommerce.openadmin.server.service.persistence.module; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.broadleafcommerce.common.persistence.EntityConfiguration; import org.broadleafcommerce.common.util.HibernateUtils; import org.broadleafcommerce.common.util.dao.DynamicDaoHelper; import org.broadleafcommerce.common.util.dao.DynamicDaoHelperImpl; import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManager; import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManagerFactory; import org.broadleafcommerce.openadmin.server.service.persistence.TargetModeType; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.persistence.EntityManager; /** * * @author jfischer * */ public class FieldManager { private static final Log LOG = LogFactory.getLog(FieldManager.class); public static final String MAPFIELDSEPARATOR = "---"; protected EntityConfiguration entityConfiguration; protected EntityManager entityManager; protected DynamicDaoHelper helper = new DynamicDaoHelperImpl(); protected List<SortableValue> middleFields = new ArrayList<SortableValue>(5); public FieldManager(EntityConfiguration entityConfiguration, EntityManager entityManager) { this.entityConfiguration = entityConfiguration; this.entityManager = entityManager; } public static Field getSingleField(Class<?> clazz, String fieldName) throws IllegalStateException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException nsf) { // Try superclass if (clazz.getSuperclass() != null) { return getSingleField(clazz.getSuperclass(), fieldName); } return null; } } public Field getField(Class<?> clazz, String fieldName) throws IllegalStateException { PersistenceManager persistenceManager = getPersistenceManager(); String[] tokens = fieldName.split("\\."); Field field = null; for (int j = 0; j < tokens.length; j++) { String propertyName = tokens[j]; Class<?>[] myEntities = persistenceManager.getUpDownInheritance(clazz); Class<?> myClass; if (ArrayUtils.isEmpty(myEntities)) { myClass = clazz; } else { myClass = getClassForField(persistenceManager, propertyName, null, myEntities); } if (myClass == null) { LOG.debug(String.format( "Unable to find the field (%s) anywhere in the inheritance hierarchy for (%s)", propertyName, clazz.getName())); return null; } field = getSingleField(myClass, propertyName); if (field != null && j < tokens.length - 1) { Class<?>[] fieldEntities = persistenceManager.getUpDownInheritance(field.getType()); if (!ArrayUtils.isEmpty(fieldEntities)) { clazz = getClassForField(persistenceManager, tokens[j + 1], field, fieldEntities); if (clazz == null) { return null; } } else { //may be an embedded class - try the class directly clazz = field.getType(); } } else { break; } } if (field != null) { field.setAccessible(true); } return field; } protected Class<?> getClassForField(PersistenceManager persistenceManager, String token, Field field, Class<?>[] entities) { Class<?> clazz; List<Class<?>> matchedClasses = new ArrayList<Class<?>>(); for (Class<?> entity : entities) { Field peekAheadField = null; try { peekAheadField = entity.getDeclaredField(token); } catch (NoSuchFieldException nsf) { //do nothing } if (peekAheadField != null) { matchedClasses.add(entity); } } if (matchedClasses.size() > 1) { LOG.warn("Found the property (" + token + ") in more than one class of an inheritance hierarchy. " + "This may lead to unwanted behavior, as the system does not know which class was intended. Do not " + "use the same property name in different levels of the inheritance hierarchy. Defaulting to the " + "first class found (" + matchedClasses.get(0).getName() + ")"); } if (matchedClasses.isEmpty()) { //probably an artificial field (i.e. passwordConfirm on AdminUserImpl) return null; } Class<?> myClass = field != null ? field.getType() : entities[0]; if (getSingleField(matchedClasses.get(0), token) != null) { clazz = matchedClasses.get(0); Class<?>[] entities2 = persistenceManager.getUpDownInheritance(clazz); if (!ArrayUtils.isEmpty(entities2) && matchedClasses.size() == 1 && clazz.isInterface()) { try { clazz = entityConfiguration.lookupEntityClass(myClass.getName()); } catch (Exception e) { // Do nothing - we'll use the matchedClass } } } else { clazz = myClass; } return clazz; } public Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException, FieldNotAvailableException { StringTokenizer tokens = new StringTokenizer(fieldName, "."); Class<?> componentClass = bean.getClass(); Field field; Object value = HibernateUtils.deproxy(bean); while (tokens.hasMoreTokens()) { String fieldNamePart = tokens.nextToken(); String mapKey = null; if (fieldNamePart.contains(FieldManager.MAPFIELDSEPARATOR)) { mapKey = fieldNamePart.substring(fieldNamePart.indexOf(FieldManager.MAPFIELDSEPARATOR) + FieldManager.MAPFIELDSEPARATOR.length(), fieldNamePart.length()); fieldNamePart = fieldNamePart.substring(0, fieldNamePart.indexOf(FieldManager.MAPFIELDSEPARATOR)); } field = getSingleField(componentClass, fieldNamePart); if (field != null) { field.setAccessible(true); value = field.get(value); if (value != null && mapKey != null) { value = ((Map) value).get(mapKey); } if (value != null) { componentClass = value.getClass(); } else { break; } } else { throw new FieldNotAvailableException( "Unable to find field (" + fieldNamePart + ") on the class (" + componentClass + ")"); } } return value; } public Object setFieldValue(Object bean, String fieldName, Object newValue) throws IllegalAccessException, InstantiationException { StringTokenizer tokens = new StringTokenizer(fieldName, "."); Class<?> componentClass = bean.getClass(); Field field; bean = HibernateUtils.deproxy(bean); Object value = bean; int count = tokens.countTokens(); int j = 0; StringBuilder sb = new StringBuilder(); while (tokens.hasMoreTokens()) { String fieldNamePart = tokens.nextToken(); sb.append(fieldNamePart); String mapKey = null; if (fieldNamePart.contains(FieldManager.MAPFIELDSEPARATOR)) { mapKey = fieldNamePart.substring(fieldNamePart.indexOf(FieldManager.MAPFIELDSEPARATOR) + FieldManager.MAPFIELDSEPARATOR.length(), fieldNamePart.length()); fieldNamePart = fieldNamePart.substring(0, fieldNamePart.indexOf(FieldManager.MAPFIELDSEPARATOR)); } field = getSingleField(componentClass, fieldNamePart); field.setAccessible(true); if (j == count - 1) { if (mapKey != null) { Map map = (Map) field.get(value); if (newValue == null) { map.remove(mapKey); } else { map.put(mapKey, newValue); } } else { field.set(value, newValue); } } else { Object myValue = field.get(value); if (myValue != null) { componentClass = myValue.getClass(); value = myValue; } else { //consult the entity configuration manager to see if there is a user //configured entity for this class try { Object newEntity = entityConfiguration.createEntityInstance(field.getType().getName()); SortableValue val = new SortableValue(bean, (Serializable) newEntity, j, sb.toString()); middleFields.add(val); field.set(value, newEntity); componentClass = newEntity.getClass(); value = newEntity; } catch (Exception e) { //Use the most extended type based on the field type PersistenceManager persistenceManager = getPersistenceManager(); Class<?>[] entities = persistenceManager.getUpDownInheritance(field.getType()); if (!ArrayUtils.isEmpty(entities)) { Object newEntity = entities[entities.length - 1].newInstance(); SortableValue val = new SortableValue(bean, (Serializable) newEntity, j, sb.toString()); middleFields.add(val); field.set(value, newEntity); componentClass = newEntity.getClass(); value = newEntity; LOG.info("Unable to find a reference to (" + field.getType().getName() + ") in the EntityConfigurationManager. " + "Using the most extended form of this class identified as (" + entities[0].getName() + ")"); } else { //Just use the field type Object newEntity = field.getType().newInstance(); field.set(value, newEntity); componentClass = newEntity.getClass(); value = newEntity; LOG.info("Unable to find a reference to (" + field.getType().getName() + ") in the EntityConfigurationManager. " + "Using the type of this class."); } } } } sb.append("."); j++; } return value; } public Class<?> getFieldType(Field field) { //consult the entity configuration manager to see if there is a user //configured entity for this class Class<?> response; try { response = entityConfiguration.lookupEntityClass(field.getType().getName()); } catch (Exception e) { //Use the most extended type based on the field type PersistenceManager persistenceManager = getPersistenceManager(); Class<?>[] entities = persistenceManager.getUpDownInheritance(field.getType()); if (!ArrayUtils.isEmpty(entities)) { response = entities[entities.length - 1]; LOG.info("Unable to find a reference to (" + field.getType().getName() + ") in the EntityConfigurationManager. " + "Using the most extended form of this class identified as (" + entities[0].getName() + ")"); } else { //Just use the field type response = field.getType(); LOG.info("Unable to find a reference to (" + field.getType().getName() + ") in the EntityConfigurationManager. " + "Using the type of this class."); } } return response; } public Map<String, Serializable> persistMiddleEntities() throws InstantiationException, IllegalAccessException { Map<String, Serializable> persistedEntities = new HashMap<String, Serializable>(); Collections.sort(middleFields); for (SortableValue val : middleFields) { Serializable s = entityManager.merge(val.entity); persistedEntities.put(val.getContainingPropertyName(), s); setFieldValue(val.getBean(), val.getContainingPropertyName(), s); } return persistedEntities; } public EntityConfiguration getEntityConfiguration() { return entityConfiguration; } protected PersistenceManager getPersistenceManager() { PersistenceManager persistenceManager; try { persistenceManager = PersistenceManagerFactory.getPersistenceManager(); } catch (IllegalStateException e) { persistenceManager = PersistenceManagerFactory.getPersistenceManager(TargetModeType.SANDBOX); } return persistenceManager; } private class SortableValue implements Comparable<SortableValue> { private Integer pos; private Serializable entity; private Class<?> entityClass; private String containingPropertyName; private Object bean; public SortableValue(Object bean, Serializable entity, Integer pos, String containingPropertyName) { this.bean = bean; this.entity = entity; this.pos = pos; this.entityClass = entity.getClass(); this.containingPropertyName = containingPropertyName; } @Override public int compareTo(SortableValue o) { return pos.compareTo(o.pos) * -1; } public String getContainingPropertyName() { return containingPropertyName; } private Object getBean() { return bean; } @Override public int hashCode() { int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + (entityClass == null ? 0 : entityClass.hashCode()); result = prime * result + (pos == null ? 0 : pos.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!getClass().isAssignableFrom(obj.getClass())) return false; SortableValue other = (SortableValue) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (entityClass == null) { if (other.entityClass != null) return false; } else if (!entityClass.equals(other.entityClass)) return false; if (pos == null) { if (other.pos != null) return false; } else if (!pos.equals(other.pos)) return false; return true; } private FieldManager getOuterType() { return FieldManager.this; } } }