Package models.crudsiena

Source Code of models.crudsiena.SienaSupport

package models.crudsiena;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import play.Logger;
import play.Play;
import play.data.binding.BeanWrapper;
import play.data.binding.Binder;
import play.data.validation.Validation;
import play.exceptions.UnexpectedException;
import play.modules.crudsiena.SienaUtils;
import play.mvc.Scope.Params;
import siena.Filter;
import siena.Json;
import siena.Model;
import siena.Query;
import siena.embed.Embedded;

import com.google.appengine.api.datastore.Blob;
import com.google.gson.JsonParseException;

/**
* All entity classes requirement CRUD Siena support should
* inherit from SienaSupport Class
*
* @author mandubian
*
*
*/
public abstract class SienaSupport
  extends Model implements Serializable {
  private static final long serialVersionUID = 7939730889902489690L;
 
  public static <T extends SienaSupport> T create(Class type, String name, Map<String, String[]> params) {
        try {
            Object model = type.newInstance();
            return (T) edit(model, name, params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
 
  public <T extends SienaSupport> T edit(String name, Params params) {
      return (T) edit(this, name, params.all());
  }
 
  public static <T extends SienaSupport> T edit(Object o, String name, Map<String, String[]> params) {
    try {
      BeanWrapper bw = new BeanWrapper(o.getClass());
      // Start with relations
      Set<Field> fields = new HashSet<Field>();
      Class clazz = o.getClass();
      while (!clazz.equals(SienaSupport.class)) {
        Collections.addAll(fields, clazz.getDeclaredFields());
        clazz = clazz.getSuperclass();
      }
      for (Field field : fields) {
        boolean isEntity = false;
        boolean isJson = false;
        boolean isEmbedded = false;
        String relation = null;
        boolean multiple = false;
        String owner = null;
        String embedType = null;
        Class embedClass = null;

        // ONE TO MANY association
        // entity = type inherits SienaSupport
        if(SienaSupport.class.isAssignableFrom(field.getType())) {
          isEntity = true;
          relation = field.getType().getName();
        }

        // MANY TO ONE association
        // type QUERY<T> + annotation @Filter
        else if(Query.class.isAssignableFrom(field.getType())){
          isEntity = true;
          multiple = true;
          Class fieldType =
            (Class) ((ParameterizedType)
                field.getGenericType()).getActualTypeArguments()[0];
          relation = fieldType.getName();
          owner = field.getAnnotation(Filter.class).value();
          // by default, takes the type of the parent entity in lower case
          if(owner == null || "".equals(owner)){
            owner = o.getClass().getName().toLowerCase();
          }
        }
        else if(Json.class.isAssignableFrom(field.getType())){
          isJson = true;
        }
        else if(field.isAnnotationPresent(Embedded.class)){
          isEmbedded = true;
         
          if(List.class.isAssignableFrom(field.getType())){
            multiple = true;
                }
          else if(Map.class.isAssignableFrom(field.getType())){
            multiple = true;
                }
                else {
                  multiple = false;
                }
        }
        else if(byte[].class.isAssignableFrom(field.getType())
            || Blob.class.isAssignableFrom(field.getType()))
        {
          // if params is present but empty, resets the older value
          String[] posted = params.get(name + "." + field.getName());
          // TODO
          Object val = field.get(o)
          //params.put(name + "." + field.getName(), val);
        }
       
        if (isEntity) {
          // builds entity list for many to one
          if (multiple) {
            //Collection l = new ArrayList();

            String[] ids = params.get(name + "." + field.getName() + "@id");
            if(ids == null) {
              ids = params.get(name + "." + field.getName() + ".id");
            }

            if (ids != null) {
              params.remove(name + "." + field.getName() + ".id");
              params.remove(name + "." + field.getName() + "@id");
              for (String _id : ids) {
                if (_id.equals("")) {
                  continue;
                }
                Class relClass = Play.classloader.loadClass(relation);
                Object res =
                  Model.all(relClass)
                    .filter("id", Binder.directBind(_id, SienaUtils.findKeyType(relClass)))
                    .get();
                if(res!=null){
                  // sets the object to the owner field into the relation entity
                  relClass.getField(owner).set(res, o);
                }
                 
                else Validation.addError(name+"."+field.getName(), "validation.notFound", _id);
              }
              // can't set arraylist to Query<T>
              // bw.set(field.getName(), o, l);
            }
          }
          // builds simple entity for simple association
          else {
            String[] ids = params.get(name + "." + field.getName() + "@id");
            if(ids == null) {
              ids = params.get(name + "." + field.getName() + ".id");
            }
            if (ids != null && ids.length > 0 && !ids[0].equals("")) {
              params.remove(name + "." + field.getName() + ".id");
              params.remove(name + "." + field.getName() + "@id");

              Class relClass = Play.classloader.loadClass(relation);
              Object res =
                Model.all(relClass)
                  .filter("id", Binder.directBind(ids[0], SienaUtils.findKeyType(relClass)))
                  .get();
              if(res!=null)
                bw.set(field.getName(), o, res);
              else Validation.addError(name+"."+field.getName(), "validation.notFound", ids[0]);

            } else if(ids != null && ids.length > 0 && ids[0].equals("")) {
              bw.set(field.getName(), o , null);
              params.remove(name + "." + field.getName() + ".id");
              params.remove(name + "." + field.getName() + "@id");
            }
          }                   
        }
        else if(isJson){
          String[] jsonStr = params.get(name + "." + field.getName());
          if (jsonStr != null && jsonStr.length > 0 && !jsonStr[0].equals("")) {
            try {
              com.google.gson.JsonParser parser = new com.google.gson.JsonParser();
              parser.parse(jsonStr[0]);
             
              params.remove(name + "." + field.getName());
              Json json = Json.loads(jsonStr[0]);
              if(json!=null)
                bw.set(field.getName(), o, json);
              else Validation.addError(name+"."+field.getName(), "validation.notParsable");
            }catch(JsonParseException ex){
              ex.printStackTrace();
              Logger.error("json parser exception:%s",
                  ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
              Validation.addError(
                  name+"."+field.getName(),
                  "validation.notParsable",
                  ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
            }
            catch(IllegalArgumentException ex){
              ex.printStackTrace();
              Logger.error("json parser exception:%s",
                  ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
              Validation.addError(
                  name+"."+field.getName(),
                  "validation.notParsable",
                  ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
            }
          }
        } 
      }
      // Then bind
      // all composites objects (simple entity, list and maps) are managed
      // by this function
      // v1.0.x code
      // bw.bind(name, o.getClass(), params, "", o);

      // v1.1 compliant
      bw.bind(name, (Type)o.getClass(), params, "", o, o.getClass().getAnnotations());
     
      return (T) o;
    } catch (Exception e) {
      throw new UnexpectedException(e);
    }
  }

  // validates and inserts the entity
    public boolean validateAndSave() {
        if(Validation.current().valid(this).ok) {
            this.insert();
            return true;
        }
        return false;
    }
     
    private Object key;
   
    public Object getEntityId(){
      if(key == null) return SienaUtils.findKey(this);
      else return key;
    }
   
    public <T extends SienaSupport> T addListElement(String name) {
      return (T) addListElement(this, name);
  }
   
    public static <T extends SienaSupport> T addListElement(Object o, String fieldName) {
      try {
        Class clazz = o.getClass();
      BeanWrapper bw = new BeanWrapper(o.getClass());
      Field field = clazz.getField(fieldName);
     
      if(List.class.isAssignableFrom(field.getType())){
        List l = (List)field.get(o);
        if(l == null)
          l = new ArrayList();
       
        Class embedClass =
          (Class) ((ParameterizedType)
              field.getGenericType()).getActualTypeArguments()[0];
        BeanWrapper embedbw = new BeanWrapper(embedClass);
        Object embedObj = embedClass.newInstance();
       
        l.add(embedObj);
       
        Logger.debug(embedObj.toString());
       
        bw.set(field.getName(), o, l);     
      }
      else Validation.addError(
          clazz.getName() + "."+field.getName(),
          "validation.fieldList.badType", fieldName);     
     
      ((SienaSupport)o).update();
      return (T) o;
      } catch (Exception e) {
      throw new UnexpectedException(e);
    }
  }
   
    public <T extends SienaSupport> T deleteListElement(String name, int idx) {
      return (T) deleteListElement(this, name, idx);
  }
   
    public static <T extends SienaSupport> T deleteListElement(Object o, String fieldName, int idx) {
      try {
        Class clazz = o.getClass();
      BeanWrapper bw = new BeanWrapper(o.getClass());
      Field field = clazz.getField(fieldName);
     
      if(List.class.isAssignableFrom(field.getType())){
        List l = (List)field.get(o);
        if(l == null)
          Validation.addError(
              clazz.getName() + "."+field.getName(),
              "validation.fieldList.empty", fieldName);
        else {
          if(idx < 0 || idx > l.size()-1)
            Validation.addError(
              clazz.getName() + "."+field.getName(),
              "validation.fieldList.indexOutOfBound", fieldName);
          else l.remove(idx);
        }
      }
      else Validation.addError(
          clazz.getName() + "."+field.getName(),
          "validation.fieldList.badType", fieldName);

      ((SienaSupport)o).update();
     
        return (T) o;
      } catch (Exception e) {
      throw new UnexpectedException(e);
    }
    }
   
    public <T extends SienaSupport> T addMapElement(String fieldName, String key) {
      return (T) addMapElement(this, fieldName, key);
  }
   
    public static <T extends SienaSupport> T addMapElement(
        Object o, String fieldName, String key)
    {
      try {
        Class clazz = o.getClass();
      BeanWrapper bw = new BeanWrapper(o.getClass());
      Field field = clazz.getField(fieldName);
     
      if(Map.class.isAssignableFrom(field.getType())){
        Map l = (Map)field.get(o);
               
        Class embedKeyClass =
          (Class) ((ParameterizedType)
              field.getGenericType()).getActualTypeArguments()[0];
       
        Class embedClass =
          (Class) ((ParameterizedType)
            field.getGenericType()).getActualTypeArguments()[1];
         
        if(l == null){
          l = new HashMap();
        }

        Object embedObj = embedClass.newInstance();
        Object embedKey = Binder.directBind(key, embedKeyClass);
       
        if(l.get(embedKey) != null){
          Logger.debug("element with key %s already existing", embedKey);
          Validation.addError(
              fieldName,
              "validation.fieldMap.alreadyExists", embedKey.toString())
        }
        else {
          l.put(embedKey, embedObj);
          Logger.debug("map added {%s:%s}", embedKey, embedObj);
        }   
       
        bw.set(field.getName(), o, l);     
      }
      else Validation.addError(
          clazz.getName() + "."+field.getName(),
          "validation.fieldMap.badType", fieldName);     
     
      ((SienaSupport)o).update();
      return (T) o;
      } catch (Exception e) {
      throw new UnexpectedException(e);
    }
  }
   
    public <T extends SienaSupport> T deleteMapElement(String fieldName, String key) {
      return (T) deleteMapElement(this, fieldName, key);
  }
   
    public static <T extends SienaSupport> T deleteMapElement(
        Object o, String fieldName, String key)
    {
      try {
        Class clazz = o.getClass();
      BeanWrapper bw = new BeanWrapper(o.getClass());
      Field field = clazz.getField(fieldName);
     
      if(Map.class.isAssignableFrom(field.getType())){
        Map l = (Map)field.get(o);
        if(l == null)
          Validation.addError(
              clazz.getName() + "."+field.getName(),
              "validation.fieldMap.empty", fieldName);
        else {
          Class embedKeyClass =
            (Class) ((ParameterizedType)
                field.getGenericType()).getActualTypeArguments()[0];
          BeanWrapper keybw = new BeanWrapper(embedKeyClass);
          try {
            Object embedKey = Binder.directBind(key, embedKeyClass);
            l.remove(embedKey);
          }catch(Exception ex){
            Validation.addError(
              clazz.getName() + "."+field.getName() + "." + key,
              "validation.fieldMap.keyBadFormat", fieldName, key);
          }         
        }
      }
      else Validation.addError(
          clazz.getName() + "."+field.getName(),
          "validation.fieldMap.badType", fieldName);

      ((SienaSupport)o).update();
     
        return (T) o;
      } catch (Exception e) {
      throw new UnexpectedException(e);
    }
    }
}
TOP

Related Classes of models.crudsiena.SienaSupport

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.