View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  
18  package ch.elca.el4j.services.persistence.generic.dto;
19  
20  import javax.persistence.Column;
21  import javax.persistence.GeneratedValue;
22  import javax.persistence.GenerationType;
23  import javax.persistence.Id;
24  import javax.persistence.MappedSuperclass;
25  import javax.persistence.Transient;
26  
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import ch.elca.el4j.util.codingsupport.Reject;
31  
32  
33  /**
34   * This class is an abstract dto which uses an integer as key value and also
35   * an integer for optimistic locking version controlling.
36   *
37   * @svnLink $Revision: 3873 $;$Date: 2009-08-04 13:59:45 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/core/src/main/java/ch/elca/el4j/services/persistence/generic/dto/AbstractIntKeyIntOptimisticLockingDto.java $
38   *
39   * @author Martin Zeltner (MZE)
40   */
41  @MappedSuperclass
42  public abstract class AbstractIntKeyIntOptimisticLockingDto
43  	extends AbstractIntOptimisticLockingDto
44  	implements PrimaryKeyOptimisticLockingObject {
45  	
46  	/**
47  	 * The logger.
48  	 */
49  	private static Logger s_logger = LoggerFactory.getLogger(AbstractIntKeyIntOptimisticLockingDto.class);
50  
51  	/**
52  	 * Primary key.
53  	 */
54  	private int m_key;
55  	
56  	/**
57  	 * Flag to indicate if the key is new.
58  	 */
59  	private boolean m_keyNew = true;
60  	
61  	/**
62  	 * Has the hashCode value been leaked while being in transient state?
63  	 */
64  	private boolean m_transientHashCodeLeaked = false;
65  
66  	/**
67  	 * @return Returns the key.
68  	 */
69  	@Id @GeneratedValue(strategy = GenerationType.AUTO,
70  		generator = "keyid_generator")
71  	@Column(name = "KEYID")
72  	public int getKey() {
73  		return m_key;
74  	}
75  	
76  	/**
77  	 * {@inheritDoc}
78  	 */
79  	@Transient
80  	public Object getKeyAsObject() {
81  		return isKeyNew() ? null : Integer.valueOf(getKey());
82  	}
83  
84  	/**
85  	 * @param key The key to set.
86  	 */
87  	public void setKey(int key) {
88  		m_key = key;
89  		m_keyNew = false;
90  	}
91  	
92  	/**
93  	 * Convenience method to set the key. The given parameter must be an
94  	 * <code>Number</code> otherwise it will be rejected.
95  	 *
96  	 * @param keyObject Is the key as object to set.
97  	 */
98  	public void setKey(Object keyObject) {
99  		Reject.ifNull(keyObject);
100 		Reject.ifNotAssignableTo(keyObject, Number.class);
101 		int key = ((Number) keyObject).intValue();
102 		setKey(key);
103 	}
104 	
105 	/**
106 	 * @return Returns <code>true</code> if the key has never be set by using
107 	 *         method <code>setKey</code>.
108 	 */
109 	@Transient
110 	public boolean isKeyNew() {
111 		return m_keyNew;
112 	}
113 	
114 	/**
115 	 * {@inheritDoc}
116 	 */
117 	public int hashCode() {
118 		if (m_keyNew) {
119 			m_transientHashCodeLeaked = true;
120 			return super.hashCode();
121 		} else {
122 			if (m_transientHashCodeLeaked) {
123 				s_logger.error("hashCode() has be called once on transient state and once on persistent state  "
124 					+ "of object '" + this.toString() + "' (" + getClass().toString() + "). "
125 					+ "This can happen if you insert a transient object into a collection and persist them afterwards. "
126 					+ "Save the objects before you insert them into a collection!");
127 			}
128 			return m_key;
129 		}
130 	}
131 
132 	/**
133 	 * {@inheritDoc}
134 	 */
135 	public boolean equals(Object obj) {
136 		if (this == obj) {
137 			return true;
138 		}
139 		/* The following is a solution that works for hibernate lazy loading proxies.
140 		if (getClass() != HibernateProxyHelper.getClassWithoutInitializingProxy(obj)) {
141 			return false;
142 		}*/
143 		if (obj instanceof AbstractIntKeyIntOptimisticLockingDto) {
144 			final AbstractIntKeyIntOptimisticLockingDto other = (AbstractIntKeyIntOptimisticLockingDto) obj;
145 			if (!isKeyNew() && !other.isKeyNew()) {
146 				return getKey() == other.getKey() && getClass() == other.getClass();
147 			}
148 		}
149 		return false;
150 	}
151 
152 	/**
153 	 * Reset the key state to "new". This is required in some circumstances (offlining), otherwise
154 	 * it should NOT be used.
155 	 */
156 	public void resetNew() {
157 		m_keyNew = true;
158 	}
159 	
160 	/**
161 	 * {@inheritDoc}
162 	 *
163 	 * Does nothing, because primary key will be generated by database.
164 	 */
165 	public void useGeneratedKey() { }
166 }