Package org.broadleafcommerce.openadmin.server.service.persistence.module

Source Code of org.broadleafcommerce.openadmin.server.service.persistence.module.FieldManager

/*
* #%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.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];
            field = getSingleField(clazz, propertyName);
            if (field != null && j < tokens.length - 1) {
                Class<?>[] entities = persistenceManager.getUpDownInheritance(field.getType());
                if (!ArrayUtils.isEmpty(entities)) {
                    String peekAheadToken = tokens[j+1];
                    List<Class<?>> matchedClasses = new ArrayList<Class<?>>();
                    for (Class<?> entity : entities) {
                        Field peekAheadField = null;
                        try {
                            peekAheadField = entity.getDeclaredField(peekAheadToken);
                        } catch (NoSuchFieldException nsf) {
                            //do nothing
                        }
                        if (peekAheadField != null) {
                            matchedClasses.add(entity);
                        }
                    }
                    if (matchedClasses.size() > 1) {
                        LOG.warn("Found the property (" + peekAheadToken + ") 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;
                    }
                    if (getSingleField(matchedClasses.get(0), peekAheadToken) != null) {
                        clazz = matchedClasses.get(0);
                        Class<?>[] entities2 = persistenceManager.getUpDownInheritance(clazz);
                        if (!ArrayUtils.isEmpty(entities2) && matchedClasses.size() == 1 && clazz.isInterface()) {
                            try {
                                clazz = entityConfiguration.lookupEntityClass(field.getType().getName());
                            } catch (Exception e) {
                                // Do nothing - we'll use the matchedClass
                            }
                        }
                    } else {
                        clazz = field.getType();
                    }
                } else {
                    //may be an embedded class - try the class directly
                    clazz = field.getType();
                }
            } else {
                break;
            }
        }
       
        if (field != null) {
            field.setAccessible(true);
        }
        return field;
    }
   
    public Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException, FieldNotAvailableException {
        StringTokenizer tokens = new StringTokenizer(fieldName, ".");
        Class<?> componentClass = bean.getClass();
        Field field;
        Object value = 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;
        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 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;
        }

        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;
        }

    }
   
}
TOP

Related Classes of org.broadleafcommerce.openadmin.server.service.persistence.module.FieldManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.