author | indvdum (gotoindvdum[at]gmail[dot]com) |
Fri, 04 Jan 2013 02:22:39 +0400 | |
changeset 22 | 55cb40622c14 |
parent 12 | 92ecc43feb3a |
permissions | -rw-r--r-- |
indvdum@2 | 1 |
package ru.indvdum.jpa.entities |
indvdum@2 | 2 |
|
indvdum@2 | 3 |
import java.lang.reflect.Modifier |
indvdum@2 | 4 |
|
indvdum@2 | 5 |
import javax.persistence.EmbeddedId |
indvdum@2 | 6 |
import javax.persistence.Entity |
indvdum@2 | 7 |
import javax.persistence.Id |
indvdum@2 | 8 |
import javax.persistence.Transient |
indvdum@2 | 9 |
|
indvdum@2 | 10 |
import org.apache.openjpa.util.OpenJPAId |
indvdum@2 | 11 |
import org.codehaus.jackson.map.ObjectMapper |
indvdum@2 | 12 |
|
indvdum@2 | 13 |
import ru.indvdum.jpa.dao.JPADataAccessObject; |
indvdum@2 | 14 |
|
indvdum@2 | 15 |
/** |
indvdum@2 | 16 |
* @author indvdum (gotoindvdum@gmail.com) |
indvdum@2 | 17 |
* @since 25.12.2011 13:26:57 |
indvdum@2 | 18 |
* |
indvdum@2 | 19 |
*/ |
indvdum@2 | 20 |
abstract class AbstractEntity implements Serializable { |
indvdum@2 | 21 |
|
indvdum@2 | 22 |
@Transient |
indvdum@2 | 23 |
protected ObjectMapper mapper = new ObjectMapper() |
indvdum@2 | 24 |
|
indvdum@2 | 25 |
@Override |
indvdum@2 | 26 |
public String toString() { |
indvdum@22 | 27 |
return getClass().getSimpleName() + '-' + getIdentifierValue() |
indvdum@2 | 28 |
} |
indvdum@2 | 29 |
|
indvdum@2 | 30 |
/** |
indvdum@2 | 31 |
* JSON-like representation of an object |
indvdum@2 | 32 |
* |
indvdum@2 | 33 |
* @return |
indvdum@2 | 34 |
*/ |
indvdum@2 | 35 |
public String toJSON() { |
indvdum@2 | 36 |
return mapper.writeValueAsString(this) |
indvdum@2 | 37 |
} |
indvdum@2 | 38 |
|
indvdum@2 | 39 |
/* |
indvdum@2 | 40 |
* HashCode, based on root class name of entity class hierarchy and id value |
indvdum@2 | 41 |
* |
indvdum@2 | 42 |
* (non-Javadoc) |
indvdum@2 | 43 |
* @see java.lang.Object#hashCode() |
indvdum@2 | 44 |
*/ |
indvdum@2 | 45 |
@Override |
indvdum@2 | 46 |
public int hashCode() { |
indvdum@2 | 47 |
Class clazz = getClass() |
indvdum@2 | 48 |
while ( |
indvdum@2 | 49 |
clazz.superclass != null |
indvdum@2 | 50 |
&& !Modifier.isAbstract(clazz.superclass.modifiers) |
indvdum@2 | 51 |
&& clazz.superclass.annotations.find {it instanceof Entity} != null |
indvdum@2 | 52 |
) |
indvdum@2 | 53 |
clazz = clazz.superclass |
indvdum@2 | 54 |
String res = clazz.getName() + ': ' + getIdentifierValue() |
indvdum@2 | 55 |
return res.hashCode() |
indvdum@2 | 56 |
} |
indvdum@2 | 57 |
|
indvdum@2 | 58 |
/* |
indvdum@2 | 59 |
* Comparison, based on entities id's |
indvdum@2 | 60 |
* |
indvdum@2 | 61 |
* (non-Javadoc) |
indvdum@2 | 62 |
* @see java.lang.Object#equals(java.lang.Object) |
indvdum@2 | 63 |
*/ |
indvdum@2 | 64 |
@Override |
indvdum@2 | 65 |
public boolean equals(Object obj) { |
indvdum@2 | 66 |
if(obj == null) |
indvdum@2 | 67 |
return false |
indvdum@2 | 68 |
if(!(obj.class.isAssignableFrom(this.class) || this.class.isAssignableFrom(obj.class))) |
indvdum@2 | 69 |
return false |
indvdum@2 | 70 |
def id = getIdentifierValue() |
indvdum@2 | 71 |
def objId = (obj as AbstractEntity).getIdentifierValue() |
indvdum@2 | 72 |
return id == objId || id != null && id != this && id.equals(objId) |
indvdum@2 | 73 |
} |
indvdum@2 | 74 |
|
indvdum@2 | 75 |
/** |
indvdum@2 | 76 |
* @return The identifier value of an entity. |
indvdum@2 | 77 |
*/ |
indvdum@2 | 78 |
@Transient |
indvdum@2 | 79 |
public Object getIdentifierValue() { |
indvdum@2 | 80 |
// an attempt to get id by EntityManagerFactory |
indvdum@2 | 81 |
Object identifier = JPADataAccessObject.emf.getPersistenceUnitUtil().getIdentifier(this) |
indvdum@2 | 82 |
if(identifier instanceof OpenJPAId) |
indvdum@2 | 83 |
return ((OpenJPAId)identifier).getIdObject() |
indvdum@2 | 84 |
|
indvdum@2 | 85 |
def result |
indvdum@2 | 86 |
|
indvdum@2 | 87 |
// an attempt to find id by annotated fields |
indvdum@2 | 88 |
Class clazz = getClass() |
indvdum@2 | 89 |
def self = this |
indvdum@2 | 90 |
Collection fields = clazz.declaredFields |
indvdum@2 | 91 |
while(clazz.superclass != null) { |
indvdum@2 | 92 |
clazz = clazz.superclass |
indvdum@2 | 93 |
fields.addAll(clazz.declaredFields) |
indvdum@2 | 94 |
} |
indvdum@2 | 95 |
fields.grep { |
indvdum@2 | 96 |
!it.synthetic && |
indvdum@2 | 97 |
!Modifier.isStatic(it.modifiers) && |
indvdum@2 | 98 |
!Modifier.isTransient(it.modifiers) |
indvdum@2 | 99 |
}.grep { |
indvdum@2 | 100 |
it.annotations.find { |
indvdum@2 | 101 |
it instanceof Id || it instanceof EmbeddedId |
indvdum@2 | 102 |
} != null |
indvdum@2 | 103 |
}.each { |
indvdum@2 | 104 |
boolean isAccessible = it.accessible |
indvdum@2 | 105 |
it.accessible = true |
indvdum@2 | 106 |
result = it.get(self) |
indvdum@2 | 107 |
it.accessible = isAccessible |
indvdum@2 | 108 |
} |
indvdum@2 | 109 |
if(result != null && !(result instanceof Reference && (result as Reference).value == null)) |
indvdum@2 | 110 |
return result |
indvdum@2 | 111 |
|
indvdum@2 | 112 |
// an attempt to represent id as a aggregate of all fields |
indvdum@2 | 113 |
// TODO check, why toJSON method don't work |
indvdum@2 | 114 |
// return toJSON() |
indvdum@2 | 115 |
result = '{' |
indvdum@2 | 116 |
fields.grep { |
indvdum@2 | 117 |
!it.synthetic && |
indvdum@2 | 118 |
!Modifier.isStatic(it.modifiers) && |
indvdum@2 | 119 |
!Modifier.isTransient(it.modifiers) |
indvdum@2 | 120 |
}.grep { |
indvdum@2 | 121 |
it.annotations.find { |
indvdum@2 | 122 |
it instanceof Transient |
indvdum@2 | 123 |
} == null |
indvdum@2 | 124 |
}.each { |
indvdum@2 | 125 |
boolean isAccessible = it.accessible |
indvdum@2 | 126 |
it.accessible = true |
indvdum@2 | 127 |
result += '"' + it.name + '": "' + it.get(self) + '", ' |
indvdum@2 | 128 |
it.accessible = isAccessible |
indvdum@2 | 129 |
} |
indvdum@2 | 130 |
return result |
indvdum@2 | 131 |
} |
indvdum@12 | 132 |
|
indvdum@12 | 133 |
protected def callMethod(method, Object ... args) { |
indvdum@12 | 134 |
"$method"(*args) |
indvdum@12 | 135 |
} |
indvdum@2 | 136 |
} |