##### Coverage Report - controllers.CRUD

Classes in this File | Line Coverage | Branch Coverage | Complexity
CRUD |
0 % | 0/123
0 % | 0/64
| 0.0;0
CRUD$For |
N/A | N/A
N/A | N/A
| 0.0;0
CRUD$ObjectType |
19 % | 17/86
3 % | 3/78
| 0.0;0
CRUD$ObjectType$ObjectField |
0 % | 0/56
0 % | 0/56
| 0.0;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 |  |