1 package eu
.etaxonomy
.cdm
.model
.common
;
3 import java
.beans
.PropertyChangeEvent
;
4 import java
.beans
.PropertyChangeListener
;
5 import java
.beans
.PropertyChangeSupport
;
6 import java
.io
.Serializable
;
7 import java
.lang
.reflect
.Method
;
8 import java
.util
.Calendar
;
11 import javax
.persistence
.Basic
;
12 import javax
.persistence
.FetchType
;
13 import javax
.persistence
.GeneratedValue
;
14 import javax
.persistence
.Id
;
15 import javax
.persistence
.ManyToOne
;
16 import javax
.persistence
.MappedSuperclass
;
17 import javax
.persistence
.Temporal
;
18 import javax
.persistence
.TemporalType
;
19 import javax
.persistence
.Transient
;
21 import javax
.xml
.bind
.annotation
.XmlAccessType
;
22 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
23 import javax
.xml
.bind
.annotation
.XmlAttribute
;
24 import javax
.xml
.bind
.annotation
.XmlElement
;
25 import javax
.xml
.bind
.annotation
.XmlID
;
26 import javax
.xml
.bind
.annotation
.XmlRootElement
;
27 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
28 import javax
.xml
.bind
.annotation
.XmlTransient
;
29 import javax
.xml
.bind
.annotation
.XmlType
;
30 import javax
.xml
.bind
.annotation
.adapters
.CollapsedStringAdapter
;
31 import javax
.xml
.bind
.annotation
.adapters
.XmlJavaTypeAdapter
;
33 import org
.hibernate
.annotations
.Cascade
;
34 import org
.hibernate
.annotations
.CascadeType
;
36 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
42 * The base class for all CDM domain classes implementing UUIDs and bean property change event firing.
43 * It provides a globally unique UUID and keeps track of creation date and person.
44 * The UUID is the same for different versions (see {@link VersionableEntity}) of a CDM object, so a locally unique id exists in addition
45 * that allows to safely access and store several objects (=version) with the same UUID.
47 * This class together with the {@link eu.etaxonomy.cdm.aspectj.PropertyChangeAspect}
48 * will fire bean change events to all registered listeners. Listener registration and event firing
49 * is done with the help of the {@link PropertyChangeSupport} class.
54 @XmlAccessorType(XmlAccessType
.PROPERTY
)
55 @XmlType(name
= "CdmBase", propOrder
= {
59 @XmlRootElement(name
= "CdmBase")
61 public abstract class CdmBase
implements Serializable
, ICdmBase
{
63 private PropertyChangeSupport propertyChangeSupport
= new PropertyChangeSupport(this);
66 private Calendar created
;
67 private Person createdBy
;
70 * Class constructor assigning a unique UUID and creation date.
71 * UUID can be changed later via setUuid method.
74 this.uuid
= UUID
.randomUUID();
75 this.setCreated(Calendar
.getInstance());
79 * see {@link PropertyChangeSupport#addPropertyChangeListener(PropertyChangeListener)}
82 public void addPropertyChangeListener(PropertyChangeListener listener
) {
83 propertyChangeSupport
.addPropertyChangeListener(listener
);
87 * see {@link PropertyChangeSupport#addPropertyChangeListener(String, PropertyChangeListener)}
89 public void addPropertyChangeListener(String propertyName
, PropertyChangeListener listener
) {
90 propertyChangeSupport
.addPropertyChangeListener(propertyName
, listener
);
94 * see {@link PropertyChangeSupport#addPropertyChangeListener(PropertyChangeListener)}
96 public void removePropertyChangeListener(PropertyChangeListener listener
) {
97 propertyChangeSupport
.removePropertyChangeListener(listener
);
101 * @see PropertyChangeSupport#addPropertyChangeListener(String, PropertyChangeListener)
103 public void removePropertyChangeListener(String propertyName
, PropertyChangeListener listener
) {
104 propertyChangeSupport
.removePropertyChangeListener(propertyName
, listener
);
108 public boolean hasListeners(String propertyName
) {
109 return propertyChangeSupport
.hasListeners(propertyName
);
112 public void firePropertyChange(String property
, String oldval
, String newval
) {
113 propertyChangeSupport
.firePropertyChange(property
, oldval
, newval
);
115 public void firePropertyChange(String property
, int oldval
, int newval
) {
116 propertyChangeSupport
.firePropertyChange(property
, oldval
, newval
);
118 public void firePropertyChange(String property
, float oldval
, float newval
) {
119 propertyChangeSupport
.firePropertyChange(property
, oldval
, newval
);
121 public void firePropertyChange(String property
, boolean oldval
, boolean newval
) {
122 propertyChangeSupport
.firePropertyChange(property
, oldval
, newval
);
124 public void firePropertyChange(String property
, Object oldval
, Object newval
) {
125 propertyChangeSupport
.firePropertyChange(property
, oldval
, newval
);
127 public void firePropertyChange(PropertyChangeEvent evt
) {
128 propertyChangeSupport
.firePropertyChange(evt
);
132 * Method for hibernate only to read the UUID value as a simple string from the object and persist it (e.g. in a database).
133 * For reading the UUID please use getUuid method
134 * @return String representation of the UUID
136 @XmlAttribute(name
= "uuid", required
= true)
138 @XmlSchemaType(name
= "ID")
139 private String
getStrUuid() {
140 return this.uuid
.toString();
143 * Method for hibernate only to set the UUID value as a simple string as it was stored in the persistence layer (e.g. a database).
144 * For setting the UUID please use setUuid method
146 private void setStrUuid(String uuid
) {
147 this.uuid
= UUID
.fromString(uuid
);
152 * @see eu.etaxonomy.cdm.model.common.ICdmBase#getId()
154 @XmlAttribute(name
= "id", required
= true)
156 @GeneratedValue(generator
= "system-increment")
161 * @see eu.etaxonomy.cdm.model.common.ICdmBase#setId(int)
163 public void setId(int id
) {
168 * @see eu.etaxonomy.cdm.model.common.ICdmBase#getUuid()
172 public UUID
getUuid() {
176 * @see eu.etaxonomy.cdm.model.common.ICdmBase#setUuid(java.util.UUID)
178 public void setUuid(UUID uuid
) {
184 * @see eu.etaxonomy.cdm.model.common.ICdmBase#getCreated()
186 @XmlElement (name
= "Created")
187 @Temporal(TemporalType
.TIMESTAMP
)
188 @Basic(fetch
= FetchType
.LAZY
)
189 public Calendar
getCreated() {
193 * @see eu.etaxonomy.cdm.model.common.ICdmBase#setCreated(java.util.Calendar)
195 public void setCreated(Calendar created
) {
196 if (created
!= null){
197 created
.set(Calendar
.MILLISECOND
, 0);
199 this.created
= created
;
204 * @see eu.etaxonomy.cdm.model.common.ICdmBase#getCreatedBy()
206 @XmlElement (name
= "CreatedBy")
207 @ManyToOne(fetch
=FetchType
.LAZY
)
208 @Cascade( { CascadeType
.SAVE_UPDATE
})
209 public Person
getCreatedBy() {
210 return this.createdBy
;
213 * @see eu.etaxonomy.cdm.model.common.ICdmBase#setCreatedBy(eu.etaxonomy.cdm.model.agent.Person)
215 public void setCreatedBy(Person createdBy
) {
216 this.createdBy
= createdBy
;
221 * Is true if UUID is the same for the passed Object and this one.
222 * @see java.lang.Object#equals(java.lang.Object)
223 * See {@link http://www.hibernate.org/109.html hibernate109}, {@link http://www.geocities.com/technofundo/tech/java/equalhash.html geocities}
224 * or {@link http://www.ibm.com/developerworks/java/library/j-jtp05273.html ibm}
225 * for more information about equals and hashcode.
228 public boolean equals(Object obj
) {
235 if (!CdmBase
.class.isAssignableFrom(obj
.getClass())){
238 ICdmBase cdmObj
= (ICdmBase
)obj
;
239 boolean uuidEqual
= cdmObj
.getUuid().equals(this.getUuid());
240 boolean createdEqual
= cdmObj
.getCreated().equals(this.getCreated());
241 if (! uuidEqual
|| !createdEqual
){
248 /** Overrides {@link java.lang.Object#hashCode()}
249 * See {@link http://www.hibernate.org/109.html hibernate109}, {@link http://www.geocities.com/technofundo/tech/java/equalhash.html geocities}
250 * or {@link http://www.ibm.com/developerworks/java/library/j-jtp05273.html ibm}
251 * for more information about equals and hashcode.
254 public int hashCode() {
256 hashCode
= 29 * hashCode
+ this.getUuid().hashCode();
261 * Overrides {@link java.lang.Object#toString()}.
262 * This returns an String that identifies the object well without beeing necessarily unique.
263 * Specification: This method should never call other object' methods so it can be well used for debugging
264 * without problems like lazy loading, unreal states etc.
265 * Note: If overriding this method's javadoc always copy or link the above requirement.
266 * If not overwritten by a subclass method returns the class, id and uuid as a string for any CDM object.
267 * For example: Taxon#13<b5938a98-c1de-4dda-b040-d5cc5bfb3bc0>
268 * @see java.lang.Object#toString()
271 public String
toString() {
272 return this.getClass().getSimpleName()+"#"+this.getId()+"<"+this.getUuid()+">";
275 protected void invokeSetMethod(Method method
, Object object
){
277 method
.invoke(object
, this);
278 } catch (Exception e
) {
280 //TODO handle exceptioin;
284 protected void invokeSetMethodWithNull(Method method
, Object object
){
286 Object
[] nul
= new Object
[]{null};
287 method
.invoke(object
, nul
);
288 } catch (Exception e
) {
290 //TODO handle exceptioin;
294 //********************** CLONE *****************************************/
296 protected void clone(CdmBase clone
){
297 clone
.setCreatedBy(createdBy
);
299 //Constructor Attributes
300 //clone.setCreated(created);
301 //clone.setUuid(getUuid());
306 * @see java.lang.Object#clone()
308 public Object
clone() throws CloneNotSupportedException
{
309 CdmBase result
= (CdmBase
)super.clone();
313 result
.setUuid(UUID
.randomUUID());
314 result
.setCreated(Calendar
.getInstance());
315 result
.setCreatedBy(null);