View Javadoc

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