Coverage Report - controllers.CRUD
 
Classes in this File Line Coverage Branch Coverage Complexity
CRUD
0 %
0/123
0 %
0/64
0
CRUD$For
N/A
N/A
0
CRUD$ObjectType
19 %
17/86
3 %
3/78
0
CRUD$ObjectType$ObjectField
0 %
0/56
0 %
0/56
0
 
 1  6
 package controllers;
 2  
 
 3  
 import play.Logger;
 4  
 import play.Play;
 5  
 import play.data.validation.MaxSize;
 6  
 import play.data.validation.Password;
 7  
 import play.data.validation.Required;
 8  
 import play.db.jpa.FileAttachment;
 9  
 import play.db.jpa.JPA;
 10  
 import play.db.jpa.JPASupport;
 11  
 import play.exceptions.TemplateNotFoundException;
 12  
 import play.i18n.Messages;
 13  
 import play.mvc.Before;
 14  
 import play.mvc.Controller;
 15  
 import play.mvc.Router;
 16  
 
 17  
 import javax.persistence.*;
 18  
 import java.lang.annotation.ElementType;
 19  
 import java.lang.annotation.Retention;
 20  
 import java.lang.annotation.RetentionPolicy;
 21  
 import java.lang.annotation.Target;
 22  
 import java.lang.reflect.Field;
 23  
 import java.lang.reflect.Modifier;
 24  
 import java.lang.reflect.ParameterizedType;
 25  
 import java.util.*;
 26  
 
 27  0
 public abstract class CRUD extends Controller {
 28  
 
 29  
     @Before
 30  
     static void addType() {
 31  0
         ObjectType type = ObjectType.get(getControllerClass());
 32  0
         renderArgs.put("type", type);
 33  0
     }
 34  
 
 35  
     public static void index() {
 36  
         try {
 37  0
             render();
 38  0
         } catch (TemplateNotFoundException e) {
 39  0
             render("CRUD/index.html");
 40  
         }
 41  0
     }
 42  
 
 43  
     public static void list(int page, String search, String searchFields, String orderBy, String order) {
 44  0
         ObjectType type = ObjectType.get(getControllerClass());
 45  0
         notFoundIfNull(type);
 46  0
         if (page < 1) {
 47  0
             page = 1;
 48  
         }
 49  0
         List<JPASupport> objects = type.findPage(page, search, searchFields, orderBy, order, (String) request.args.get("where"));
 50  0
         Long count = type.count(search, searchFields, (String) request.args.get("where"));
 51  0
         Long totalCount = type.count(null, null, (String) request.args.get("where"));
 52  
         try {
 53  0
             render(type, objects, count, totalCount, page, orderBy, order);
 54  0
         } catch (TemplateNotFoundException e) {
 55  0
             render("CRUD/list.html", type, objects, count, totalCount, page, orderBy, order);
 56  
         }
 57  0
     }
 58  
 
 59  
     public static void show(String id) {
 60  0
         ObjectType type = ObjectType.get(getControllerClass());
 61  0
         notFoundIfNull(type);
 62  0
         JPASupport object = type.findById(id);
 63  
         try {
 64  0
             render(type, object);
 65  0
         } catch (TemplateNotFoundException e) {
 66  0
             render("CRUD/show.html", type, object);
 67  
         }
 68  0
     }
 69  
 
 70  
     public static void attachment(String id, String field) throws Exception {
 71  0
         ObjectType type = ObjectType.get(getControllerClass());
 72  0
         notFoundIfNull(type);
 73  0
         JPASupport object = type.findById(id);
 74  0
         FileAttachment attachment = (FileAttachment) object.getClass().getField(field).get(object);
 75  0
         if (attachment == null) {
 76  0
             notFound();
 77  
         }
 78  0
         renderBinary(attachment.get(), attachment.filename);
 79  0
     }
 80  
 
 81  
     public static void save(String id) throws Exception {
 82  0
         ObjectType type = ObjectType.get(getControllerClass());
 83  0
         notFoundIfNull(type);
 84  0
         JPASupport object = type.findById(id);
 85  0
         object = object.edit("object", params);
 86  
         // Look if we need to deserialize
 87  0
         for (ObjectType.ObjectField field : type.getFields()) {
 88  0
             if (field.type.equals("serializedText") && params.get("object." + field.name) != null) {
 89  0
                 Field f = object.getClass().getDeclaredField(field.name);
 90  0
                 f.set(object, CRUD.collectionDeserializer(params.get("object." + field.name),(Class)((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0]));
 91  
             }
 92  
         }
 93  
                
 94  0
         validation.valid(object);
 95  0
         if (validation.hasErrors()) {
 96  0
             renderArgs.put("error", Messages.get("crud.hasErrors"));
 97  
             try {
 98  0
                 render(request.controller.replace(".", "/") + "/show.html", type, object);
 99  0
             } catch (TemplateNotFoundException e) {
 100  0
                 render("CRUD/show.html", type, object);
 101  
             }
 102  
         }
 103  0
         object.save();
 104  0
         flash.success(Messages.get("crud.saved", type.modelName, object.getEntityId()));
 105  0
         if (params.get("_save") != null) {
 106  0
             redirect(request.controller + ".list");
 107  
         }
 108  0
         redirect(request.controller + ".show", object.getEntityId());
 109  0
     }
 110  
 
 111  
     public static void blank() {
 112  0
         ObjectType type = ObjectType.get(getControllerClass());
 113  0
         notFoundIfNull(type);
 114  
         try {
 115  0
             render(type);
 116  0
         } catch (TemplateNotFoundException e) {
 117  0
             render("CRUD/blank.html", type);
 118  
         }
 119  0
     }
 120  
 
 121  
     public static void create() throws Exception {
 122  0
         ObjectType type = ObjectType.get(getControllerClass());
 123  0
         notFoundIfNull(type);
 124  0
         JPASupport object = type.entityClass.newInstance();
 125  0
         validation.valid(object.edit("object", params));
 126  0
         if (validation.hasErrors()) {
 127  0
             renderArgs.put("error", Messages.get("crud.hasErrors"));
 128  
             try {
 129  0
                 render(request.controller.replace(".", "/") + "/blank.html", type);
 130  0
             } catch (TemplateNotFoundException e) {
 131  0
                 render("CRUD/blank.html", type);
 132  
             }
 133  
         }
 134  0
         object.save();
 135  0
         flash.success(Messages.get("crud.created", type.modelName, object.getEntityId()));
 136  0
         if (params.get("_save") != null) {
 137  0
             redirect(request.controller + ".list");
 138  
         }
 139  0
         if (params.get("_saveAndAddAnother") != null) {
 140  0
             redirect(request.controller + ".blank");
 141  
         }
 142  0
         redirect(request.controller + ".show", object.getEntityId());
 143  0
     }
 144  
 
 145  
     public static void delete(String id) {
 146  0
         ObjectType type = ObjectType.get(getControllerClass());
 147  0
         notFoundIfNull(type);
 148  0
         JPASupport object = type.findById(id);
 149  
         try {
 150  0
             object.delete();
 151  0
         } catch (Exception e) {
 152  0
             flash.error(Messages.get("crud.delete.error", type.modelName, object.getEntityId()));
 153  0
             redirect(request.controller + ".show", object.getEntityId());
 154  
         }
 155  0
         flash.success(Messages.get("crud.deleted", type.modelName, object.getEntityId()));
 156  0
         redirect(request.controller + ".list");
 157  0
     }
 158  
 
 159  
     // ~~~~~~~~~~~~~
 160  
     @Retention(RetentionPolicy.RUNTIME)
 161  
     @Target(ElementType.TYPE)
 162  
     public @interface For {
 163  
 
 164  
         Class value();
 165  
     }
 166  
 
 167  
     // ~~~~~~~~~~~~~
 168  
     static int getPageSize() {
 169  0
         return Integer.parseInt(Play.configuration.getProperty("crud.pageSize", "30"));
 170  
     }
 171  
 
 172  
     public static class ObjectType implements Comparable<ObjectType> {
 173  
 
 174  
         public Class<? extends CRUD> controllerClass;
 175  
         public Class<? extends JPASupport> entityClass;
 176  
         public String name;
 177  
         public String modelName;
 178  
         public String controllerName;
 179  
 
 180  4
         public ObjectType(Class modelClass) {
 181  4
             this.modelName = modelClass.getSimpleName();
 182  4
             this.entityClass = modelClass;
 183  4
         }
 184  
 
 185  
         public ObjectType(String modelClass) throws ClassNotFoundException {
 186  0
             this(Play.classloader.loadClass(modelClass));
 187  0
         }
 188  
 
 189  
         public static ObjectType forClass(String modelClass) throws ClassNotFoundException {
 190  0
             return new ObjectType(modelClass);
 191  
         }
 192  
 
 193  
         public static ObjectType get(Class controllerClass) {
 194  4
             Class entityClass = getEntityClassForController(controllerClass);
 195  4
             if (entityClass == null || !JPASupport.class.isAssignableFrom(entityClass)) {
 196  0
                 return null;
 197  
             }
 198  4
             ObjectType type = new ObjectType(entityClass);
 199  4
             type.name = controllerClass.getSimpleName();
 200  4
             type.controllerName = controllerClass.getSimpleName().toLowerCase();
 201  4
             type.controllerClass = controllerClass;
 202  4
             return type;
 203  
         }
 204  
 
 205  
         public static Class getEntityClassForController(Class controllerClass) {
 206  4
             if (controllerClass.isAnnotationPresent(For.class)) {
 207  0
                 return ((For) (controllerClass.getAnnotation(For.class))).value();
 208  
             }
 209  4
             String name = controllerClass.getSimpleName();
 210  4
             name = "models." + name.substring(0, name.length() - 1);
 211  
             try {
 212  4
                 return Play.classloader.loadClass(name);
 213  0
             } catch (ClassNotFoundException e) {
 214  0
                 return null;
 215  
             }
 216  
         }
 217  
 
 218  
         public Object getListAction() {
 219  0
             return Router.reverse(controllerClass.getName() + ".list");
 220  
         }
 221  
 
 222  
         public Object getBlankAction() {
 223  0
             return Router.reverse(controllerClass.getName() + ".blank");
 224  
         }
 225  
 
 226  
         public Long count(String search, String searchFields, String where) {
 227  0
             String q = "select count(e) from " + entityClass.getName() + " e";
 228  0
             if (search != null && !search.equals("")) {
 229  0
                 String searchQuery = getSearchQuery(searchFields);
 230  0
                 if (!searchQuery.equals("")) {
 231  0
                     q += " where (" + searchQuery + ")";
 232  
                 }
 233  0
                 q += (where != null ? " and " + where : "");
 234  
             } else {
 235  0
                 q += (where != null ? " where " + where : "");
 236  
             }
 237  0
             Query query = JPA.em().createQuery(q);
 238  0
             if (search != null && !search.equals("") && q.indexOf("?1") != -1) {
 239  0
                 query.setParameter(1, "%" + search.toLowerCase() + "%");
 240  
             }
 241  0
             return Long.decode(query.getSingleResult().toString());
 242  
         }
 243  
 
 244  
         public List findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
 245  0
             int pageLength = getPageSize();
 246  0
             String q = "from " + entityClass.getName();
 247  0
             if (search != null && !search.equals("")) {
 248  0
                 String searchQuery = getSearchQuery(searchFields);
 249  0
                 if (!searchQuery.equals("")) {
 250  0
                     q += " where (" + searchQuery + ")";
 251  
                 }
 252  0
                 q += (where != null ? " and " + where : "");
 253  
             } else {
 254  0
                 q += (where != null ? " where " + where : "");
 255  
             }
 256  0
             if (orderBy == null && order == null) {
 257  0
                 orderBy = "id";
 258  0
                 order = "ASC";
 259  
             }
 260  0
             if (orderBy == null && order != null) {
 261  0
                 orderBy = "id";
 262  
             }
 263  0
             if (order == null || (!order.equals("ASC") && !order.equals("DESC"))) {
 264  0
                 order = "ASC";
 265  
             }
 266  0
             q += " order by " + orderBy + " " + order;
 267  0
             Query query = JPA.em().createQuery(q);
 268  0
             if (search != null && !search.equals("") && q.indexOf("?1") != -1) {
 269  0
                 query.setParameter(1, "%" + search.toLowerCase() + "%");
 270  
             }
 271  0
             query.setFirstResult((page - 1) * pageLength);
 272  0
             query.setMaxResults(pageLength);
 273  0
             return query.getResultList();
 274  
         }
 275  
 
 276  
         public String getSearchQuery(String searchFields) {
 277  0
             List<String> fields = null;
 278  0
             if (searchFields != null && !searchFields.equals("")) {
 279  0
                 fields = Arrays.asList(searchFields.split("[ ]"));
 280  
             }
 281  0
             String q = "";
 282  0
             for (ObjectField field : getFields()) {
 283  0
                 if (field.searchable && (fields == null ? true : fields.contains(field.name))) {
 284  0
                     if (!q.equals("")) {
 285  0
                         q += " or ";
 286  
                     }
 287  0
                     q += "lower(" + field.name + ") like ?1";
 288  
                 }
 289  
             }
 290  0
             return q;
 291  
         }
 292  
 
 293  
         public JPASupport findById(Object id) {
 294  0
             Query query = JPA.em().createQuery("from " + entityClass.getName() + " where id = ?");
 295  
             try {
 296  0
                 query.setParameter(1, play.data.binding.Binder.directBind(id + "", play.db.jpa.JPASupport.findKeyType(entityClass)));
 297  0
             } catch (Exception e) {
 298  0
                 throw new RuntimeException("Something bad with id type ?", e);
 299  
             }
 300  0
             return (JPASupport) query.getSingleResult();
 301  
         }
 302  
 
 303  
         public List<ObjectField> getFields() {
 304  0
             List fields = new ArrayList();
 305  0
             for (Field f : entityClass.getFields()) {
 306  0
                 if (Modifier.isTransient(f.getModifiers()) || Modifier.isFinal(f.getModifiers())) {
 307  0
                     continue;
 308  
                 }
 309  0
                 ObjectField of = new ObjectField(f);
 310  0
                 if (of.type != null) {
 311  0
                     fields.add(of);
 312  
                 }
 313  
             }
 314  0
             return fields;
 315  
         }
 316  
 
 317  
         public ObjectField getField(String name) {
 318  0
             for (ObjectField field : getFields()) {
 319  0
                 if (field.name.equals(name)) {
 320  0
                     return field;
 321  
                 }
 322  
             }
 323  0
             return null;
 324  
         }
 325  
 
 326  
         public int compareTo(ObjectType other) {
 327  6
             return modelName.compareTo(other.modelName);
 328  
         }
 329  
 
 330  
         public static class ObjectField {
 331  
 
 332  0
             public String type = "unknown";
 333  
             public String name;
 334  
             public String relation;
 335  
             public boolean multiple;
 336  
             public boolean searchable;
 337  
             public Object[] choices;
 338  
             public boolean required;
 339  
             public String serializedValue;
 340  
 
 341  0
             public ObjectField(Field field) {
 342  0
                 if (CharSequence.class.isAssignableFrom(field.getType())) {
 343  0
                     type = "text";
 344  0
                     searchable = true;
 345  0
                     if (field.isAnnotationPresent(MaxSize.class)) {
 346  0
                         int maxSize = field.getAnnotation(MaxSize.class).value();
 347  0
                         if (maxSize > 100) {
 348  0
                             type = "longtext";
 349  
                         }
 350  
                     }
 351  0
                     if (field.isAnnotationPresent(Password.class)) {
 352  0
                         type = "password";
 353  
                     }
 354  
                 }
 355  0
                 if (Number.class.isAssignableFrom(field.getType()) || field.getType().equals(double.class) || field.getType().equals(int.class) || field.getType().equals(long.class)) {
 356  0
                     type = "number";
 357  
                 }
 358  0
                 if (Boolean.class.isAssignableFrom(field.getType()) || field.getType().equals(boolean.class)) {
 359  0
                     type = "boolean";
 360  
                 }
 361  0
                 if (Date.class.isAssignableFrom(field.getType())) {
 362  0
                     type = "date";
 363  
                 }
 364  0
                 if (FileAttachment.class.isAssignableFrom(field.getType())) {
 365  0
                     type = "file";
 366  
                 }
 367  0
                 if (JPASupport.class.isAssignableFrom(field.getType())) {
 368  0
                     if (field.isAnnotationPresent(OneToOne.class)) {
 369  0
                         if (field.getAnnotation(OneToOne.class).mappedBy().equals("")) {
 370  0
                             type = "relation";
 371  0
                             relation = field.getType().getName();
 372  
                         }
 373  
                     }
 374  0
                     if (field.isAnnotationPresent(ManyToOne.class)) {
 375  0
                         type = "relation";
 376  0
                         relation = field.getType().getName();
 377  
                     }
 378  
                 }
 379  0
                 if (Collection.class.isAssignableFrom(field.getType())) {
 380  0
                     Class fieldType = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
 381  0
                     if (field.isAnnotationPresent(OneToMany.class)) {
 382  0
                         if (field.getAnnotation(OneToMany.class).mappedBy().equals("")) {
 383  0
                             type = "relation";
 384  0
                             relation = fieldType.getName();
 385  0
                             multiple = true;
 386  
                         }
 387  
                     }
 388  0
                     if (field.isAnnotationPresent(ManyToMany.class)) {
 389  0
                         if (field.getAnnotation(ManyToMany.class).mappedBy().equals("")) {
 390  0
                             type = "relation";
 391  0
                             relation = fieldType.getName();
 392  0
                             multiple = true;
 393  
                         }
 394  
                     }
 395  
                 }
 396  0
                 if (Collection.class.isAssignableFrom(field.getType())) {
 397  0
                     if (!(field.isAnnotationPresent(OneToMany.class) ||
 398  0
                             (field.isAnnotationPresent(ManyToMany.class)))) {
 399  0
                         type = "serializedText";
 400  
                     }
 401  
                 }
 402  0
                 if (field.getType().isEnum()) {
 403  0
                     type = "enum";
 404  0
                     relation = field.getType().getSimpleName();
 405  0
                     choices = field.getType().getEnumConstants();
 406  
                 }
 407  0
                 if (field.isAnnotationPresent(Id.class)) {
 408  0
                     type = null;
 409  
                 }
 410  0
                 if (field.isAnnotationPresent(Transient.class)) {
 411  0
                     type = null;
 412  
                 }
 413  0
                 if (field.isAnnotationPresent(Required.class)) {
 414  0
                     required = true;
 415  
                 }
 416  0
                 name = field.getName();
 417  0
             }
 418  
 
 419  
             public Object[] getChoices() {
 420  0
                 return choices;
 421  
             }
 422  
         }
 423  
     }
 424  
 
 425  
     public static String collectionSerializer(Collection<?> coll) {
 426  0
         StringBuffer sb = new StringBuffer();
 427  0
         for (Object obj : coll) {
 428  0
             sb.append("\"" + obj.toString() + "\",");
 429  
         }
 430  0
         if (sb.length() > 2) {
 431  0
             return sb.substring(0, sb.length() - 1);
 432  
         }
 433  0
         return null;
 434  
 
 435  
     }
 436  
 
 437  
     public static String arraySerializer(Object[] coll) {
 438  0
        return collectionSerializer(Arrays.asList(coll));
 439  
     }
 440  
 
 441  
     public static Collection<?> collectionDeserializer(String target, Class<?> type) {
 442  0
         String[] targets = target.trim().split(",");
 443  
         Collection results;
 444  0
         Logger.info("type [" + type + "]");
 445  0
         if (List.class.isAssignableFrom(type)) {
 446  0
             results = new ArrayList();
 447  
         } else {
 448  0
             results = new TreeSet();
 449  
         }
 450  0
         for (String targ : targets) {
 451  0
             if (targ.length() > 1) {
 452  0
                 targ = targ.substring(1, targ.length() - 1);
 453  
             }
 454  0
             if (type.isEnum()) {
 455  0
                 Object[] constants = type.getEnumConstants();
 456  0
                 for (Object c : constants) {
 457  0
                     if  (c.toString().equals(targ)) {
 458  0
                         results.add(c);
 459  
                     }
 460  
                 }
 461  0
             } else if (CharSequence.class.isAssignableFrom(type)) {
 462  0
                 results.add(targ);
 463  0
             } else if (Integer.class.isAssignableFrom(type)) {
 464  0
                 results.add(Integer.valueOf(targ));
 465  0
             } else if (Float.class.isAssignableFrom(type)) {
 466  0
                 results.add(Float.valueOf(targ));
 467  0
             } else if (Boolean.class.isAssignableFrom(type)) {
 468  0
                  results.add(Boolean.valueOf(targ));
 469  0
             } else if (Double.class.isAssignableFrom(type)) {
 470  0
                  results.add(Double.valueOf(targ));
 471  0
             } else if (Long.class.isAssignableFrom(type)) {
 472  0
                 results.add(Long.valueOf(targ));
 473  0
             }  else if (Byte.class.isAssignableFrom(type)) {
 474  0
                  results.add(Byte.valueOf(targ));
 475  
             }
 476  
         }
 477  
 
 478  0
         return results;
 479  
 
 480  
     }
 481  
 }
 482