1 package ru.indvdum.jpa.entities
3 import java.lang.reflect.Modifier
5 import javax.persistence.EmbeddedId
6 import javax.persistence.Entity
7 import javax.persistence.Id
8 import javax.persistence.Transient
10 import org.apache.openjpa.util.OpenJPAId
11 import org.codehaus.jackson.map.ObjectMapper
13 import ru.indvdum.jpa.dao.JPADataAccessObject;
16 * @author indvdum (gotoindvdum@gmail.com)
17 * @since 25.12.2011 13:26:57
20 abstract class AbstractEntity implements Serializable {
23 protected ObjectMapper mapper = new ObjectMapper()
26 public String toString() {
27 return getClass().getSimpleName() + '-' + getIdentifierValue()
31 * JSON-like representation of an object
35 public String toJSON() {
36 return mapper.writeValueAsString(this)
40 * HashCode, based on root class name of entity class hierarchy and id value
43 * @see java.lang.Object#hashCode()
46 public int hashCode() {
47 Class clazz = getClass()
49 clazz.superclass != null
50 && !Modifier.isAbstract(clazz.superclass.modifiers)
51 && clazz.superclass.annotations.find {it instanceof Entity} != null
53 clazz = clazz.superclass
54 String res = clazz.getName() + ': ' + getIdentifierValue()
59 * Comparison, based on entities id's
62 * @see java.lang.Object#equals(java.lang.Object)
65 public boolean equals(Object obj) {
68 if(!(obj.class.isAssignableFrom(this.class) || this.class.isAssignableFrom(obj.class)))
70 def id = getIdentifierValue()
71 def objId = (obj as AbstractEntity).getIdentifierValue()
72 return id == objId || id != null && id != this && id.equals(objId)
76 * @return The identifier value of an entity.
79 public Object getIdentifierValue() {
80 // an attempt to get id by EntityManagerFactory
81 Object identifier = JPADataAccessObject.emf.getPersistenceUnitUtil().getIdentifier(this)
82 if(identifier instanceof OpenJPAId)
83 return ((OpenJPAId)identifier).getIdObject()
87 // an attempt to find id by annotated fields
88 Class clazz = getClass()
90 Collection fields = clazz.declaredFields
91 while(clazz.superclass != null) {
92 clazz = clazz.superclass
93 fields.addAll(clazz.declaredFields)
97 !Modifier.isStatic(it.modifiers) &&
98 !Modifier.isTransient(it.modifiers)
100 it.annotations.find {
101 it instanceof Id || it instanceof EmbeddedId
104 boolean isAccessible = it.accessible
106 result = it.get(self)
107 it.accessible = isAccessible
109 if(result != null && !(result instanceof Reference && (result as Reference).value == null))
112 // an attempt to represent id as a aggregate of all fields
113 // TODO check, why toJSON method don't work
118 !Modifier.isStatic(it.modifiers) &&
119 !Modifier.isTransient(it.modifiers)
121 it.annotations.find {
122 it instanceof Transient
125 boolean isAccessible = it.accessible
127 result += '"' + it.name + '": "' + it.get(self) + '", '
128 it.accessible = isAccessible
133 protected def callMethod(method, Object ... args) {