001package co.codewizards.cloudstore.local.persistence; 002 003import static co.codewizards.cloudstore.core.util.Util.*; 004 005import java.util.Date; 006 007import javax.jdo.JDOHelper; 008import javax.jdo.annotations.IdGeneratorStrategy; 009import javax.jdo.annotations.IdentityType; 010import javax.jdo.annotations.Inheritance; 011import javax.jdo.annotations.InheritanceStrategy; 012import javax.jdo.annotations.NullValue; 013import javax.jdo.annotations.PersistenceCapable; 014import javax.jdo.annotations.Persistent; 015import javax.jdo.annotations.PrimaryKey; 016 017/** 018 * Base class of all persistence-capable (a.k.a. entity) classes. 019 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co 020 */ 021@PersistenceCapable(identityType=IdentityType.APPLICATION) 022@Inheritance(strategy=InheritanceStrategy.SUBCLASS_TABLE) 023public abstract class Entity implements AutoTrackChanged 024{ 025 @PrimaryKey 026 @Persistent(valueStrategy=IdGeneratorStrategy.NATIVE) 027 private long id = -1; 028 029 // We always initialise this, though the value might be overwritten when DataNucleus loads 030 // the object's data from the DB. There's no need to defer the Date instantiation. 031 // Creating 1 million instances of Date costs less than 68 ms (I tested creating them and 032 // putting them into a LinkedList (preventing optimizer short-cuts), so the LinkedList 033 // overhead is included in this time). 034 @Persistent(nullValue=NullValue.EXCEPTION) 035 private Date created = new Date(); 036 037 @Persistent(nullValue=NullValue.EXCEPTION) 038 private Date changed = new Date(); 039 040 /** 041 * Get the unique identifier of this object. 042 * <p> 043 * This identifier is unique per entity type (the first sub-class of this class 044 * having an own table - which is usually the direct sub-class of {@link Entity}). 045 * <p> 046 * This identifier is assigned when the object is persisted into the DB. 047 * @return the unique identifier of this object. 048 */ 049 public long getId() { 050 return id; 051 } 052 053 @Override 054 public boolean equals(Object obj) { 055 if (this == obj) { 056 return true; 057 } 058 if (obj == null) { 059 return false; 060 } 061 062 Object thisOid = JDOHelper.getObjectId(this); 063 if (thisOid == null) { 064 return false; 065 } 066 067 Object otherOid = JDOHelper.getObjectId(obj); 068 return thisOid.equals(otherOid); 069 } 070 071 @Override 072 public int hashCode() { 073 Object thisOid = JDOHelper.getObjectId(this); 074 if (thisOid == null) { 075 return super.hashCode(); 076 } 077 return thisOid.hashCode(); 078 } 079 080 @Override 081 public String toString() { 082 return String.format("%s[%s]", getClass().getSimpleName(), JDOHelper.getObjectId(this)); 083 } 084 085 /** 086 * Gets the timestamp of the creation of this entity. 087 * @return the timestamp of the creation of this entity. Never <code>null</code>. 088 */ 089 public Date getCreated() { 090 return created; 091 } 092 /** 093 * Sets the timestamp of the creation of this entity. 094 * <p> 095 * <b>Important: You should normally never invoke this method!</b> The {@code created} property 096 * is supposed to be read-only (assigned once during object creation and never again). 097 * This setter merely exists for extraordinary, unforeseen use cases as well as tests. 098 * @param created the timestamp of the creation of this entity. Must not be <code>null</code>. 099 */ 100 protected void setCreated(Date created) { 101 assertNotNull("created", created); 102 this.created = created; 103 } 104 105 @Override 106 public Date getChanged() { 107 return changed; 108 } 109 @Override 110 public void setChanged(Date changed) { 111 assertNotNull("created", created); 112 this.changed = changed; 113 } 114 115}