View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.bo;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.ojb.broker.PersistenceBroker;
20  import org.apache.ojb.broker.PersistenceBrokerAware;
21  import org.apache.ojb.broker.PersistenceBrokerException;
22  import org.kuali.rice.core.api.mo.common.GloballyUnique;
23  import org.kuali.rice.core.api.mo.common.Versioned;
24  import org.kuali.rice.krad.service.KRADServiceLocator;
25  import org.kuali.rice.krad.service.PersistenceService;
26  import org.kuali.rice.krad.service.PersistenceStructureService;
27  
28  import javax.persistence.Column;
29  import javax.persistence.MappedSuperclass;
30  import javax.persistence.PostLoad;
31  import javax.persistence.PostPersist;
32  import javax.persistence.PostRemove;
33  import javax.persistence.PostUpdate;
34  import javax.persistence.PrePersist;
35  import javax.persistence.PreRemove;
36  import javax.persistence.PreUpdate;
37  import javax.persistence.Transient;
38  import javax.persistence.Version;
39  import java.util.ArrayList;
40  import java.util.Collection;
41  import java.util.List;
42  import java.util.UUID;
43  
44  /**
45   * Business Object Base Business Object
46   */
47  @MappedSuperclass
48  public abstract class PersistableBusinessObjectBase extends BusinessObjectBase implements PersistableBusinessObject, PersistenceBrokerAware, Versioned, GloballyUnique {
49      
50  	private static final long serialVersionUID = 1451642350593233282L;
51  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PersistableBusinessObjectBase.class);
52      
53  	@Version
54      @Column(name="VER_NBR")
55      protected Long versionNumber;
56      @Column(name="OBJ_ID")
57      private String objectId;
58      @Transient
59      private boolean newCollectionRecord;
60      @Transient
61      protected PersistableBusinessObjectExtension extension;
62  
63      private static transient PersistenceService persistenceService;
64      private static transient PersistenceStructureService persistenceStructureService;
65      
66      /**
67       * @see PersistableBusinessObject#getVersionNumber()
68       */
69      public Long getVersionNumber() {
70          return versionNumber;
71      }
72  
73      /**
74       * @see PersistableBusinessObject#getVersionNumber()
75       */
76      public void setVersionNumber(Long versionNumber) {
77          this.versionNumber = versionNumber;
78      }
79  
80  
81      /**
82       * getter for the guid based object id that is assignable to all objects, in order to support custom attributes a mapping must
83       * also be added to the OJB file and a column must be added to the database for each business object that extension attributes
84       * are supposed to work on.
85       * 
86       * @return
87       */
88      public String getObjectId() {
89          return objectId;
90      }
91  
92      /**
93       * setter for the guid based object id that is assignable to all objects, in order to support custom attributes a mapping must
94       * also be added to the OJB file and column must be added to the database for each business object that extension attributes are
95       * supposed to work on.
96       * 
97       * @param objectId
98       */
99      public void setObjectId(String objectId) {
100         this.objectId = objectId;
101     }
102 
103 
104     /**
105      * Gets the newCollectionRecord attribute.
106      * 
107      * @return Returns the newCollectionRecord.
108      */
109     public boolean isNewCollectionRecord() {
110         return newCollectionRecord;
111     }
112 
113     /**
114      * Sets the newCollectionRecord attribute value.
115      * 
116      * @param isNewCollectionRecord The newCollectionRecord to set.
117      */
118     public void setNewCollectionRecord(boolean isNewCollectionRecord) {
119         this.newCollectionRecord = isNewCollectionRecord;
120     }
121 
122     /**
123      * Implementation of the OJB afterDelete hook which delegates to {@link #postRemove()}.  This method is final
124      * because it is recommended that sub-classes override and implement postRemove if they need to take
125      * advantage of this persistence hook.
126      * 
127      * @see org.apache.ojb.broker.PersistenceBrokerAware#afterDelete(org.apache.ojb.broker.PersistenceBroker)
128      */
129     public final void afterDelete(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
130     	postRemove();
131     }
132     
133     /**
134      * Default implementation of the JPA {@link PostRemove} hook.  This implementation currently does nothing,
135      * however sub-classes can override and implement this method if needed.
136      * 
137      * <p>This method is currently invoked by the corresponding OJB {@link #afterDelete(PersistenceBroker)} hook.
138      */
139     @PostRemove
140     protected void postRemove() {
141     	// do nothing
142     }
143 
144     /**
145      * Implementation of the OJB afterInsert hook which delegates to {@link #postPersist()}.  This method is final
146      * because it is recommended that sub-classes override and implement postPersist if they need to take
147      * advantage of this persistence hook.
148      * 
149      * @see org.apache.ojb.broker.PersistenceBrokerAware#afterInsert(org.apache.ojb.broker.PersistenceBroker)
150      */
151     public final void afterInsert(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
152     	postPersist();
153     }
154 
155     /**
156      * Default implementation of the JPA {@link PostPersist} hook.  This implementation currently does nothing,
157      * however sub-classes can override and implement this method if needed.
158      * 
159      * <p>This method is currently invoked by the corresponding OJB {@link #afterInsert(PersistenceBroker)} hook.
160      */
161     @PostPersist
162     protected void postPersist() {
163     	// do nothing
164     }
165 
166     /**
167      * Implementation of the OJB afterLookup hook which delegates to {@link #postLoad()}.  This method is final
168      * because it is recommended that sub-classes override and implement postLoad if they need to take
169      * advantage of this persistence hook.
170      * 
171      * @see org.apache.ojb.broker.PersistenceBrokerAware#afterLookup(org.apache.ojb.broker.PersistenceBroker)
172      */
173     public final void afterLookup(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
174     	postLoad();
175     }
176     
177     /**
178      * Default implementation of the JPA {@link PostLoad} hook.  This implementation currently does nothing,
179      * however sub-classes can override and implement this method if needed.
180      * 
181      * <p>This method is currently invoked by the corresponding OJB {@link #afterLookup(PersistenceBroker)} hook.
182      */
183     @PostLoad
184     protected void postLoad() {
185     	// do nothing
186     }
187 
188     /**
189      * Implementation of the OJB afterUpdate hook which delegates to {@link #postUpdate()}.  This method is final
190      * because it is recommended that sub-classes override and implement postUpdate if they need to take
191      * advantage of this persistence hook.
192      *  
193      * @see org.apache.ojb.broker.PersistenceBrokerAware#afterUpdate(org.apache.ojb.broker.PersistenceBroker)
194      */
195     public final void afterUpdate(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
196     	postUpdate();
197     }
198     
199     /**
200      * Default implementation of the JPA {@link PostUpdate} hook.  This implementation currently does nothing,
201      * however sub-classes can override and implement this method if needed.
202      * 
203      * <p>This method is currently invoked by the corresponding OJB {@link #afterUpdate(PersistenceBroker)} hook.
204      */
205     @PostUpdate
206     protected void postUpdate() {
207     	// do nothing
208     }
209 
210     /**
211      * Implementation of the OJB beforeDelete hook which delegates to {@link #preRemove()}.  This method is final
212      * because it is recommended that sub-classes override and implement preRemove if they need to take
213      * advantage of this persistence hook.
214      * 
215      * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeDelete(org.apache.ojb.broker.PersistenceBroker)
216      */
217     public final void beforeDelete(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
218     	preRemove();
219     }
220     
221     /**
222      * Default implementation of the JPA {@link PreRemove} hook.  This implementation currently does nothing,
223      * however sub-classes can implement this method if needed.
224      * 
225      * <p>This method is currently invoked by the corresponding OJB {@link #beforeDelete(PersistenceBroker)} hook.
226      */
227     @PreRemove
228     protected void preRemove() {
229     	// do nothing
230     }
231 
232     /**
233      * Implementation of the OJB beforeInsert hook which delegates to {@link #prePersist()}.  This method is final
234      * because it is recommended that sub-classes override and implement prePersist if they need to take
235      * advantage of this persistence hook.
236      * 
237      * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeInsert(org.apache.ojb.broker.PersistenceBroker)
238      */
239     public final void beforeInsert(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
240     	prePersist();
241     }
242     
243     /**
244      * Default implementation of the JPA {@link PrePersist} hook which generates the unique objectId for this 
245      * persistable business object if it does not already have one.  Any sub-class which overrides this method
246      * should take care to invoke super.prePersist to ensure that the objectId for this persistable
247      * business object is generated properly.
248      * 
249      * <p>This method is currently invoked by the corresponding OJB {@link #beforeInsert(PersistenceBroker)} hook.
250      */
251     @PrePersist
252     protected void prePersist() {
253     	generateAndSetObjectIdIfNeeded();
254     }
255 
256     /**
257      * Implementation of the OJB beforeUpdate hook which delegates to {@link #preUpdate()}.  This method is final
258      * because it is recommended that sub-classes override and implement preUpdate if they need to take
259      * advantage of this persistence hook.
260      * 
261      * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeUpdate(org.apache.ojb.broker.PersistenceBroker)
262      */
263     public final void beforeUpdate(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
264     	preUpdate();
265     }
266 
267     /**
268      * Default implementation of the JPA {@link PreUpdate} hook which generates the unique objectId for this 
269      * persistable business object if it does not already have one.  Any sub-class which overrides this method
270      * should take care to invoke super.preUpdate to ensure that the objectId for this persistable
271      * business object is generated properly.
272      * 
273      * <p>This method is currently invoked by the corresponding OJB {@link #beforeUpdate(PersistenceBroker)} hook.
274      */
275     @PreUpdate
276     protected void preUpdate() {
277     	generateAndSetObjectIdIfNeeded();
278     }
279         
280     /**
281      * If this PersistableBusinessObject does not already have a unique objectId, this method will generate
282      * one and set it's value on this object.
283      */
284     private void generateAndSetObjectIdIfNeeded() {
285     	if (StringUtils.isEmpty(getObjectId())) {
286             setObjectId(UUID.randomUUID().toString());
287         }
288     }
289 
290     /**
291      * getService Refreshes the reference objects from the primitive values.
292      * 
293      * @see org.kuali.rice.kns.bo.BusinessObject#refresh()
294      */
295     public void refresh() {
296         getPersistenceService().retrieveNonKeyFields(this);
297     }
298 
299     /**
300      * @see BusinessObject#refresh()
301      */
302     public void refreshNonUpdateableReferences() {
303         getPersistenceService().refreshAllNonUpdatingReferences(this);
304     }
305 
306 	public void refreshReferenceObject(String referenceObjectName) {
307 		if ( StringUtils.isNotBlank(referenceObjectName) && !StringUtils.equals(referenceObjectName, "extension")) {
308 			final PersistenceStructureService pss = getPersistenceStructureService();
309 			if ( pss.hasReference(this.getClass(), referenceObjectName) || pss.hasCollection(this.getClass(), referenceObjectName)) {
310             	getPersistenceService().retrieveReferenceObject( this, referenceObjectName);
311 			} else {
312                 LOG.warn( "refreshReferenceObject() called with non-reference property: " + referenceObjectName );
313 			}
314 		}
315 	}
316 
317     /**
318      * @see PersistableBusinessObject#buildListOfDeletionAwareLists()
319      */
320     public List<Collection<PersistableBusinessObject>> buildListOfDeletionAwareLists() {
321         return new ArrayList<Collection<PersistableBusinessObject>>();
322     }
323 
324     public void linkEditableUserFields() {
325     	// do nothing
326     }
327 
328 	public PersistableBusinessObjectExtension getExtension() {
329 		if ( extension == null ) {
330 			try {
331 				Class<? extends PersistableBusinessObjectExtension> extensionClass = getPersistenceStructureService().getBusinessObjectAttributeClass( getClass(), "extension" );
332 				if ( extensionClass != null ) {
333 					extension = extensionClass.newInstance();
334 				}
335 			} catch ( Exception ex ) {
336 				LOG.error( "unable to create extension object", ex );
337 			}
338 		}
339 		return extension;
340 	}
341 
342 	public void setExtension(PersistableBusinessObjectExtension extension) {
343 		this.extension = extension;
344 	}
345 
346 	/**
347 	 * @return the persistenceService
348 	 */
349 	protected static PersistenceService getPersistenceService() {
350 		if ( persistenceService == null ) {
351 			persistenceService = KRADServiceLocator.getPersistenceService();
352 		}
353 		return persistenceService;
354 	}
355 
356 	protected static PersistenceStructureService getPersistenceStructureService() {
357 		if ( persistenceStructureService == null ) {
358 			persistenceStructureService = KRADServiceLocator.getPersistenceStructureService();
359 		}
360 		return persistenceStructureService;
361 	}
362 
363 }