Package org.reverspring.engine

Source Code of org.reverspring.engine.BeanSet

/*
* Copyright 2007 Luigi Dell'Aquila (luigi.dellaquila@assetdata.it)
*
* 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.
*/
package org.reverspring.engine;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.reverspring.annotations.ClassProperties;
import org.reverspring.strategy.DescriptionStrategy;
import org.reverspring.strategy.annotation.AnnotationDescriptionStrategy;
import org.reverspring.xml.XmlGenerator;

/**
* This class represents an abstraction of a Spring IoC xml descriptor. To generate
* a Spring descriptor you should create a {@link BeanSet} object and add your Java beans
* with the method {@link BeanSet#addBeanDescriptor(Object, String)}. A {@link BeanSet}
* can be written on a Spring IoC descriptor using {@link XmlGenerator} class<br/><br/>
* See the example below
* <pre>
* Person me = new Person();
* Person you = new Person();
* ....
* BeanSet set = new BeanSet();
* set.addBeanDescriptor(me, "myId");
* set.addBeanDescriptor(you, "yourId");
* XmlGenerator.save(set, new File("./mySpringDescriptor.xml"));
* </pre>
* @see DescriptorGenerator
* @see XmlGenerator
* @author Luigi Dell'Aquila
*
*/
public class BeanSet {
  private Set<String> assignedIds;

  private List<BeanDescriptor> beans;

  private Map<BeanDescriptor, ObjectBinding> beanToBinding;

  private DescriptionStrategy strategy;
 
  /**
   * creates a BeanSet with the given DescriptionStrategy.
   * @param strategy the strategy to be adopted to represent objects and fieds in the XML.
   * If this parameter is null, the BeanSet will use the default strategy, that is
   * {@link AnnotationDescriptionStrategy}
   */
  public BeanSet(DescriptionStrategy strategy) {
    this.beans = new ArrayList<BeanDescriptor>();
    this.beanToBinding = new HashMap<BeanDescriptor, ObjectBinding>();
    this.assignedIds = new HashSet<String>();
    this.strategy=strategy;
    if(this.strategy==null){
      this.strategy=new AnnotationDescriptionStrategy();
    }
  }
 
  /**
   * creates a BeanSet with {@link AnnotationDescriptionStrategy} strategy
   * @see BeanSet#BeanSet(DescriptionStrategy)
   */
  public BeanSet() {
    this(new AnnotationDescriptionStrategy());
  }

  /**
   * returns the strategy used by this BeanSet
   * @return the strategy used by this BeanSet
   */
  public DescriptionStrategy getStrategy(){
    return strategy;
  }
 
  /**
   * this method adds a bean to the current BeanSet. The bean will be
   * written in the Spring IoC descriptor
   * @param bean the bean to be added to the set
   * @param id the id that the bean will have in the xml
   */
  public void addBeanDescriptor(Object bean, String id) {
      newBeanDescriptor(bean, id);
  }
    
  public List<BeanDescriptor> getBeans() {
    return beans;
  }
 
 

  /**
   * gets all the properties that can be set in a Spring descriptor for this
   * object
   *
   * @param o
   *          the object
   * @return
   */
  private Set<String> getSpringProperties(Object o) {
    return strategy.getPropertyNames(o);
  }

  /**
   * Check if the bean is a a singleton class
   *
   * @param o
   * @return is singleton class
   */
  private static boolean isSingletonClass(Object o) {
    if (o == null)
      return false;
    ClassProperties annotation = o.getClass().getAnnotation(ClassProperties.class);

    if (annotation == null) {
      return false;
    } else if (annotation.singletonClass() == true) {
      return true;
    }

    return false;
  }

//  /**
//   * gets the constructor that has to be used in the spring descriptor for this
//   * object
//   *
//   * @param o
//   *          the object
//   * @return
//   * @deprecated use {@link DescriptionStrategy#getConstructor(Object)} instead
//   */
//  public Constructor<?> getSpringConstructor(Object o) {
//    return strategy.getConstructor(o);
//  }

  /**
   * gets the value of a property by the object (by getter method or directly)
   *
   * @param obj
   *          the object
   * @param property
   *          the object name
   * @return
   */
  private static Object getPropertyValue(Object obj, String property) {
    Object value = null;
    // try to load through getter method
    try {
      String getter = "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
      Method method = obj.getClass().getMethod(getter);
      value = method.invoke(obj, new Object[0]);
    } catch (Exception e) {
      value = null;
    }
    if (value == null) {
      try {
        String getter = "is" + property.substring(0, 1).toUpperCase() + property.substring(1);
        Method method = obj.getClass().getMethod(getter);
        value = method.invoke(obj, new Object[0]);
      } catch (Exception e) {
        value = null;
      }
    }
    return value;
  }

  /**
   *
   * @param obj
   *          an objec
   * @return true if the object is a Number, a String or a Boolean.
   */
  private static boolean isBaseType(Object obj) {
    if (obj == null)
      return false;
    if (obj instanceof String)
      return true;
    if (obj instanceof Number)
      return true;
    if (obj instanceof Boolean)
      return true;
    if (obj instanceof Class<?>)
      return true;
    return false;
  }

  private static boolean isSetType(Object obj) {
    if (obj instanceof Set<?>)
      return true;
    return false;
  }

  private static boolean isListType(Object obj) {
    if (obj instanceof List<?>)
      return true;
    if (obj.getClass().isArray())
      return true; // the object is an array
    return false;
  }

  private static boolean isSetOfBaseTypeType(Object obj) {
    if (!(obj instanceof Set<?>))
      return false;
    Set<?> set = (Set<?>) obj;
    for (Object element : set) {
      if (!isBaseType(element))
        return false;
    }
    return true;
  }

  private static boolean isListOfBaseTypeType(Object obj) {
    if (!(obj instanceof List<?>))
      return false;
    List<?> set = (List<?>) obj;
    for (Object element : set) {
      if (!isBaseType(element))
        return false;
    }
    return true;
  }

  /**
   * @param obj
   * @return
   */
  private static boolean isMapType(Object obj) {
    if (!(obj instanceof Map<?, ?>))
      return false;
    return true;
  }

  private static boolean isKeyBaseType(Map<?, ?> map) {
    if (map == null)
      return false;
    boolean isBase = true;
    for (Object key : map.keySet()) {
      if (!isBaseType(key)) {
        isBase = false;
        break;
      }
    }
    return isBase;
  }

  private static boolean isValueBaseType(Map<?, ?> map) {
    if (map == null)
      return false;
    boolean isBase = true;
    for (Object value : map.values()) {
      if (!isBaseType(value)) {
        isBase = false;
        break;
      }
    }
    return isBase;
  }
 
  private ObjectBinding newBeanDescriptor(Object o, String id) {
    BeanDescriptor descriptor = new BeanDescriptor(o);
    if (o == null) {
      ObjectBinding nullBind = new ObjectBinding();
      nullBind.setDescriptor(descriptor);
      return nullBind;
    }

    descriptor.setSingletonClass(isSingletonClass(o));
    if (beans.contains(descriptor))
      return beanToBinding.get(descriptor);
    assignId(id, descriptor);

    beans.add(descriptor);
    ObjectBinding newBind = new ObjectBinding();
    newBind.setDescriptor(descriptor);
    beanToBinding.put(descriptor, newBind);
   
    //constructor arguments
    Constructor<?> constructor = strategy.getConstructor(o);
    if(constructor!=null && !(o instanceof String)){
      descriptor.setConstructor(constructor);
      try {
        Object[] parameters=strategy.getConstructorArgs(o);
        if(parameters==null) parameters=new Object[0];
        for (Object paramValue : parameters) {
          ObjectBinding binding;
          if (isBaseType(paramValue)) {
            if (paramValue instanceof Class<?>)
              paramValue = ((Class<?>) paramValue).getName();
            BeanDescriptor tmpDesc = new BeanDescriptor(paramValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            binding = new ObjectBinding();
            binding.setDescriptor(tmpDesc);
          } else {
            binding = beanToBinding.get(new BeanDescriptor(paramValue));
            if (binding == null) {
              binding = newBeanDescriptor(paramValue, "constArgument");
            }
          }
          descriptor.addConstructorArgument(binding);
        }
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }else{ //for collections
      ObjectBinding binding;
      BeanDescriptor tmpDesc = new BeanDescriptor(o.toString());
      tmpDesc.setType(BeanDescriptor.TYPE_BASE);
      binding = new ObjectBinding();
      binding.setDescriptor(tmpDesc);
      descriptor.addConstructorArgument(binding);
    }
   
    Set<String> properties = getSpringProperties(o);
    for (String property : properties) {
      Object value = getPropertyValue(o, property);
      if (value == null) {
        descriptor.setPropertyBinding(property, null);
        continue;
      }

      if (value instanceof Class<?>)
        value = ((Class<?>) value).getName();

      if (isBaseType(value)) {
        BeanDescriptor tmpDesc = new BeanDescriptor(value);
        tmpDesc.setType(BeanDescriptor.TYPE_BASE);
        ObjectBinding binding = new ObjectBinding();
        binding.setDescriptor(tmpDesc);
        if(strategy.nested(o, property)){
          binding.setNested(true);
        }
        descriptor.setPropertyBinding(property, binding);
        continue;
      }

      if (isListOfBaseTypeType(value)) { // the property is a list and
        // its elements are base type
        // elements
        descriptor.addListProperty(property);
        if (value instanceof Object[]) {
          for (Object itemValue : ((Object[]) value)) {
            BeanDescriptor tmpDesc = new BeanDescriptor(itemValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            ObjectBinding binding = new ObjectBinding();
            binding.setDescriptor(tmpDesc);

            descriptor.addListPropertyValue(property, binding);
          }
        } else {
          for (Object itemValue : ((Collection<?>) value)) {
            BeanDescriptor tmpDesc = new BeanDescriptor(itemValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            ObjectBinding binding = new ObjectBinding();
            binding.setDescriptor(tmpDesc);

            descriptor.addListPropertyValue(property, binding);
          }
        }
        continue;
      }

      if (isListType(value)) { // the property is a generic list of
        // objects
        descriptor.addListProperty(property);

        if (value instanceof Object[]) {
          for (Object itemValue : ((Object[]) value)) {
            ObjectBinding ref = newBeanDescriptor(itemValue, property + "_item");
            if(strategy.nested(o, property))
              ref.setNested(true);
            descriptor.addListPropertyValue(property, ref);
          }
        } else {
          for (Object itemValue : ((Collection<?>) value)) {
            ObjectBinding ref = newBeanDescriptor(itemValue, property + "_item");
            if(strategy.nested(o, property))
              ref.setNested(true);
            descriptor.addListPropertyValue(property, ref);
          }
        }
        continue;
      }

      if (isSetOfBaseTypeType(value)) { // the property is a set and its
        // elements are base type
        // elements
        descriptor.addSetProperty(property);
        for (Object itemValue : ((Collection<?>) value)) {
          BeanDescriptor tmpDesc = new BeanDescriptor(itemValue);
          tmpDesc.setType(BeanDescriptor.TYPE_BASE);
          ObjectBinding binding = new ObjectBinding();
          binding.setDescriptor(tmpDesc);

          descriptor.addSetPropertyValue(property, binding);
        }
        continue;
      }

      if (isSetType(value)) { // the property is a generic set of objects
        descriptor.addSetProperty(property);
        for (Object itemValue : ((Collection<?>) value)) {
          ObjectBinding ref = newBeanDescriptor(itemValue, property + "_item");
          if(strategy.nested(o, property))
            ref.setNested(true);
          descriptor.addSetPropertyValue(property, ref);
        }
        continue;
      }

      if (isMapType(value)) {
        descriptor.addMapProperty(property);

        Map<?, ?> castedValue = (Map<?, ?>) value;
        boolean keysAreBaseType = isKeyBaseType(castedValue);
        boolean valuesAreBaseType = isValueBaseType(castedValue);
        for (Object mapKey : castedValue.keySet()) {
          Object mapValue = castedValue.get(mapKey);
          ObjectBinding keyBinding;
          ObjectBinding valueBinding;
          if (keysAreBaseType) {
            BeanDescriptor tmpDesc = new BeanDescriptor(mapKey);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            keyBinding = new ObjectBinding();
            keyBinding.setDescriptor(tmpDesc);
          } else {
            keyBinding = newBeanDescriptor(mapKey, property + "_key");
          }
          keyBinding.setNested(strategy.nested(o, property));

          if (valuesAreBaseType) {
            BeanDescriptor tmpDesc = new BeanDescriptor(mapValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            valueBinding = new ObjectBinding();
            valueBinding.setDescriptor(tmpDesc);
          } else if(mapValue instanceof List){
                      valueBinding = addListBeanDescriptor((List)mapValue, property + "_value");
                    } else if(mapValue instanceof Set){
                      valueBinding = addSetBeanDescriptor((Set)mapValue, property + "_value");
                    } else if(mapValue instanceof Map){
                      valueBinding = addMapBeanDescriptor((Map)mapValue, property + "_value");
                    } else {
            valueBinding = newBeanDescriptor(mapValue, property + "_value");
          }
          valueBinding.setNested(strategy.nested(o, property));

          descriptor.addMapPropertyValue(property, keyBinding, valueBinding);
        }
        continue;
      }

      ObjectBinding ref = newBeanDescriptor(value, property);
      if(strategy.nested(o, property)){
        ref.setNested(true);
      }
      descriptor.setPropertyBinding(property, ref);
    }
    ObjectBinding bind = new ObjectBinding();
    bind.setDescriptor(descriptor);
    return bind;
  }

  private ObjectBinding addListBeanDescriptor(List list, String id) {
    BeanDescriptor descriptor = new BeanDescriptor(list);
    descriptor.setType(BeanDescriptor.TYPE_LIST);
    if (beans.contains(descriptor))
        return beanToBinding.get(descriptor);
      assignId(id, descriptor);
 
      beans.add(descriptor);
      ObjectBinding newBind = new ObjectBinding();
      newBind.setDescriptor(descriptor);
      beanToBinding.put(descriptor, newBind);
     
      descriptor.addListProperty(BeanDescriptor.PROPERTY_CONTENT);
     
      if (isListOfBaseTypeType(list)) { // the property is a list and
        // its elements are base type
        // elements
       
        for (Object itemValue : ((Collection<?>) list)) {
            BeanDescriptor tmpDesc = new BeanDescriptor(itemValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            ObjectBinding binding = new ObjectBinding();
            binding.setDescriptor(tmpDesc);

            descriptor.addListPropertyValue(BeanDescriptor.PROPERTY_CONTENT, binding);
        }
      }else{
        for (Object itemValue : list) {
          ObjectBinding ref;
          if(itemValue instanceof List){
            ref = addListBeanDescriptor((List)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else if(itemValue instanceof Set){
            ref = addSetBeanDescriptor((Set)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else if(itemValue instanceof Map){
            ref = addMapBeanDescriptor((Map)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else {
            ref = newBeanDescriptor(itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          }
          descriptor.addListPropertyValue(BeanDescriptor.PROPERTY_CONTENT, ref);
        }
      }
      ObjectBinding bind = new ObjectBinding();
      bind.setDescriptor(descriptor);
      bind.setNested(true);
      return bind;
  }
 
  private ObjectBinding addSetBeanDescriptor(Set set, String id) {
    BeanDescriptor descriptor = new BeanDescriptor(set);
      descriptor.setType(BeanDescriptor.TYPE_SET);
      if (beans.contains(descriptor))
        return beanToBinding.get(descriptor);
      assignId(id, descriptor);
 
      beans.add(descriptor);
      ObjectBinding newBind = new ObjectBinding();
      newBind.setDescriptor(descriptor);
      beanToBinding.put(descriptor, newBind);
     
      descriptor.addSetProperty(BeanDescriptor.PROPERTY_CONTENT);
     
      if (isSetOfBaseTypeType(set)) { // the property is a list and
        // its elements are base type
        // elements
       
        for (Object itemValue : ((Collection<?>) set)) {
            BeanDescriptor tmpDesc = new BeanDescriptor(itemValue);
            tmpDesc.setType(BeanDescriptor.TYPE_BASE);
            ObjectBinding binding = new ObjectBinding();
            binding.setDescriptor(tmpDesc);

            descriptor.addSetPropertyValue(BeanDescriptor.PROPERTY_CONTENT, binding);
        }
      }else{
        for (Object itemValue : ((Collection<?>) set)) {
          ObjectBinding ref;
       
          if(itemValue instanceof List){
            ref = addListBeanDescriptor((List)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else if(itemValue instanceof Set){
            ref = addSetBeanDescriptor((Set)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else if(itemValue instanceof Map){
            ref = addMapBeanDescriptor((Map)itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          } else {
            ref = newBeanDescriptor(itemValue, BeanDescriptor.PROPERTY_CONTENT + "_item");
          }
          descriptor.addSetPropertyValue(BeanDescriptor.PROPERTY_CONTENT, ref);
        }
      }
      ObjectBinding bind = new ObjectBinding();
      bind.setDescriptor(descriptor);
      bind.setNested(true);
      return bind;
    }

  private ObjectBinding addMapBeanDescriptor(Map map, String id) {
    BeanDescriptor descriptor = new BeanDescriptor(map);
      descriptor.setType(BeanDescriptor.TYPE_MAP);
      if (beans.contains(descriptor))
        return beanToBinding.get(descriptor);
      assignId(id, descriptor);
 
      beans.add(descriptor);
      ObjectBinding newBind = new ObjectBinding();
      newBind.setDescriptor(descriptor);
      beanToBinding.put(descriptor, newBind);
     
    descriptor.addMapProperty(BeanDescriptor.PROPERTY_CONTENT);

      Map<?, ?> castedValue = (Map<?, ?>) map;
      boolean keysAreBaseType = isKeyBaseType(castedValue);
      boolean valuesAreBaseType = isValueBaseType(castedValue);
      for (Object mapKey : castedValue.keySet()) {
          Object mapValue = castedValue.get(mapKey);
          ObjectBinding keyBinding;
          ObjectBinding valueBinding;
          if (keysAreBaseType) {
              BeanDescriptor tmpDesc = new BeanDescriptor(mapKey);
              tmpDesc.setType(BeanDescriptor.TYPE_BASE);
              keyBinding = new ObjectBinding();
              keyBinding.setDescriptor(tmpDesc);
          } else {
              keyBinding = newBeanDescriptor(mapKey, BeanDescriptor.PROPERTY_CONTENT + "_key");
          }
          keyBinding.setNested(true);

          if (valuesAreBaseType) {
              BeanDescriptor tmpDesc = new BeanDescriptor(mapValue);
              tmpDesc.setType(BeanDescriptor.TYPE_BASE);
              valueBinding = new ObjectBinding();
              valueBinding.setDescriptor(tmpDesc);
          } else if(mapValue instanceof List){
            valueBinding = addListBeanDescriptor((List)mapValue, BeanDescriptor.PROPERTY_CONTENT + "_value");
          } else if(mapValue instanceof Set){
            valueBinding = addSetBeanDescriptor((Set)mapValue, BeanDescriptor.PROPERTY_CONTENT + "_value");
          } else if(mapValue instanceof Map){
            valueBinding = addMapBeanDescriptor((Map)mapValue, BeanDescriptor.PROPERTY_CONTENT + "_value");
          } else {
              valueBinding = newBeanDescriptor(mapValue, BeanDescriptor.PROPERTY_CONTENT + "_value");
          }
          valueBinding.setNested(true);

          descriptor.addMapPropertyValue(BeanDescriptor.PROPERTY_CONTENT, keyBinding, valueBinding);
      }
      ObjectBinding bind = new ObjectBinding();
      bind.setDescriptor(descriptor);
      bind.setNested(true);
      return bind;
  }
  /**
   * Assigne an id to beanDescriptor
   *
   * @param id
   * @param descriptor
   */
  private void assignId(String id, BeanDescriptor descriptor) {
    if (id == null)
      id = getNewId();
    id = getIdSourceValue(descriptor.getBean(), id);
    String baseId = id;

    while (assignedIds.contains(id))
      id = getNewId(baseId);
    assignedIds.add(id);
    descriptor.setId(id);
  }

  private String getIdSourceValue(Object o, final String initialId) {
    try{
      String desired=strategy.getDesiredId(o);
      if(desired!=null) return desired;
    }catch(Exception e){
      return initialId;
    }
    return initialId;
  }

  private static int prog = 0;

  private static String getNewId() {
    return getNewId("bean");
  }

  private static String getNewId(String baseName) {
    if (baseName == null)
      baseName = "bean";
    return baseName + (prog++);
  }
 
}
TOP

Related Classes of org.reverspring.engine.BeanSet

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.