001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.bo;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.ojb.broker.PersistenceBroker;
020import org.apache.ojb.broker.PersistenceBrokerAware;
021import org.apache.ojb.broker.PersistenceBrokerException;
022import org.kuali.rice.core.api.mo.common.GloballyUnique;
023import org.kuali.rice.core.api.mo.common.Versioned;
024import org.kuali.rice.kns.service.KNSServiceLocator;
025import org.kuali.rice.krad.service.KRADServiceLocator;
026import org.kuali.rice.krad.service.LegacyAppFrameworkAdapterService;
027import org.kuali.rice.krad.util.LegacyDataFramework;
028
029import javax.persistence.Column;
030import javax.persistence.Embeddable;
031import javax.persistence.MappedSuperclass;
032import javax.persistence.PostLoad;
033import javax.persistence.PostPersist;
034import javax.persistence.PostRemove;
035import javax.persistence.PostUpdate;
036import javax.persistence.PrePersist;
037import javax.persistence.PreRemove;
038import javax.persistence.PreUpdate;
039import javax.persistence.Transient;
040import javax.persistence.Version;
041
042import java.util.ArrayList;
043import java.util.Collection;
044import java.util.List;
045import java.util.UUID;
046
047/**
048 * @author Kuali Rice Team (rice.collab@kuali.org)
049 * @deprecated use new KRAD Data framework {@link org.kuali.rice.krad.data.DataObjectService}.
050 *             In this framework, data objects are not required to have a superclass and can
051 *             be POJO's but they can optionally use {@link org.kuali.rice.krad.bo.DataObjectBase}
052 *             to emulate previous functionality.
053 */
054@Deprecated
055@MappedSuperclass
056public abstract class PersistableBusinessObjectBase extends BusinessObjectBase implements PersistableBusinessObject, PersistenceBrokerAware, Versioned, GloballyUnique {
057
058    /**
059     * EclipseLink static weaving does not weave MappedSuperclass unless an Entity or Embedded is
060     * weaved which uses it, hence this class.
061     */
062    @Embeddable
063    private static final class WeaveMe extends PersistableBusinessObjectBase {}
064
065    private static final long serialVersionUID = 1451642350593233282L;
066        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PersistableBusinessObjectBase.class);
067
068        @Version
069    @Column(name = "VER_NBR", length = 8)
070    protected Long versionNumber;
071
072    @Column(name = "OBJ_ID", length = 36, unique = true)
073    protected String objectId;
074
075    @Transient protected boolean newCollectionRecord;
076    @Transient protected PersistableBusinessObjectExtension extension;
077
078    private static transient LegacyAppFrameworkAdapterService legacyDataAdapter;
079
080    @Override
081    public Long getVersionNumber() {
082        return versionNumber;
083    }
084
085    @Override
086    public void setVersionNumber(Long versionNumber) {
087        this.versionNumber = versionNumber;
088    }
089
090    @Override
091    public String getObjectId() {
092        return objectId;
093    }
094
095    @Override
096    public void setObjectId(String objectId) {
097        this.objectId = objectId;
098    }
099
100    /**
101     * Gets the newCollectionRecord attribute.
102     *
103     * @return Returns the newCollectionRecord.
104     */
105    @Override
106    public boolean isNewCollectionRecord() {
107        return newCollectionRecord;
108    }
109
110    /**
111     * Sets the newCollectionRecord attribute value.
112     *
113     * @param isNewCollectionRecord The newCollectionRecord to set.
114     */
115    @Override
116    public void setNewCollectionRecord(boolean isNewCollectionRecord) {
117        this.newCollectionRecord = isNewCollectionRecord;
118    }
119
120    /**
121     * Implementation of the OJB afterDelete hook which delegates to {@link #postRemove()}.  This method is final
122     * because it is recommended that sub-classes override and implement postRemove if they need to take
123     * advantage of this persistence hook.
124     *
125     * @see org.apache.ojb.broker.PersistenceBrokerAware#afterDelete(org.apache.ojb.broker.PersistenceBroker)
126     */
127    @Override
128    @LegacyDataFramework
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    @Override
152    @LegacyDataFramework
153    public final void afterInsert(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
154        postPersist();
155    }
156
157    /**
158     * Default implementation of the JPA {@link PostPersist} hook.  This implementation currently does nothing,
159     * however sub-classes can override and implement this method if needed.
160     *
161     * <p>This method is currently invoked by the corresponding OJB {@link #afterInsert(PersistenceBroker)} hook.
162     */
163    @PostPersist
164    protected void postPersist() {
165        // do nothing
166    }
167
168    /**
169     * Implementation of the OJB afterLookup hook which delegates to {@link #postLoad()}.  This method is final
170     * because it is recommended that sub-classes override and implement postLoad if they need to take
171     * advantage of this persistence hook.
172     *
173     * @see org.apache.ojb.broker.PersistenceBrokerAware#afterLookup(org.apache.ojb.broker.PersistenceBroker)
174     */
175    @Override
176    public final void afterLookup(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
177        postLoad();
178    }
179
180    /**
181     * Default implementation of the JPA {@link PostLoad} hook.  This implementation currently does nothing,
182     * however sub-classes can override and implement this method if needed.
183     *
184     * <p>This method is currently invoked by the corresponding OJB {@link #afterLookup(PersistenceBroker)} hook.
185     */
186    @PostLoad
187    protected void postLoad() {
188        // do nothing
189    }
190
191    /**
192     * Implementation of the OJB afterUpdate hook which delegates to {@link #postUpdate()}.  This method is final
193     * because it is recommended that sub-classes override and implement postUpdate if they need to take
194     * advantage of this persistence hook.
195     *
196     * @see org.apache.ojb.broker.PersistenceBrokerAware#afterUpdate(org.apache.ojb.broker.PersistenceBroker)
197     */
198    @Override
199    @LegacyDataFramework
200    public final void afterUpdate(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
201        postUpdate();
202    }
203
204    /**
205     * Default implementation of the JPA {@link PostUpdate} hook.  This implementation currently does nothing,
206     * however sub-classes can override and implement this method if needed.
207     *
208     * <p>This method is currently invoked by the corresponding OJB {@link #afterUpdate(PersistenceBroker)} hook.
209     */
210    @PostUpdate
211    protected void postUpdate() {
212        // do nothing
213    }
214
215    /**
216     * Implementation of the OJB beforeDelete hook which delegates to {@link #preRemove()}.  This method is final
217     * because it is recommended that sub-classes override and implement preRemove if they need to take
218     * advantage of this persistence hook.
219     *
220     * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeDelete(org.apache.ojb.broker.PersistenceBroker)
221     */
222    @Override
223    @LegacyDataFramework
224    public final void beforeDelete(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
225        preRemove();
226    }
227
228    /**
229     * Default implementation of the JPA {@link PreRemove} hook.  This implementation currently does nothing,
230     * however sub-classes can implement this method if needed.
231     *
232     * <p>This method is currently invoked by the corresponding OJB {@link #beforeDelete(PersistenceBroker)} hook.
233     */
234    @PreRemove
235    protected void preRemove() {
236        // do nothing
237    }
238
239    /**
240     * Implementation of the OJB beforeInsert hook which delegates to {@link #prePersist()}.  This method is final
241     * because it is recommended that sub-classes override and implement prePersist if they need to take
242     * advantage of this persistence hook.
243     *
244     * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeInsert(org.apache.ojb.broker.PersistenceBroker)
245     */
246    @Override
247    @LegacyDataFramework
248    public final void beforeInsert(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
249        //setObjectId(UUID.randomUUID().toString());
250        setObjectId(null);
251        prePersist();
252    }
253
254    /**
255     * Default implementation of the JPA {@link PrePersist} hook which generates the unique objectId for this
256     * persistable business object if it does not already have one.  Any sub-class which overrides this method
257     * should take care to invoke super.prePersist to ensure that the objectId for this persistable
258     * business object is generated properly.
259     *
260     * <p>This method is currently invoked by the corresponding OJB {@link #beforeInsert(PersistenceBroker)} hook.
261     */
262    @PrePersist
263    protected void prePersist() {
264        generateAndSetObjectIdIfNeeded();
265    }
266
267    /**
268     * Implementation of the OJB beforeUpdate hook which delegates to {@link #preUpdate()}.  This method is final
269     * because it is recommended that sub-classes override and implement preUpdate if they need to take
270     * advantage of this persistence hook.
271     *
272     * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeUpdate(org.apache.ojb.broker.PersistenceBroker)
273     */
274    @Override
275    @LegacyDataFramework
276    public final void beforeUpdate(PersistenceBroker persistenceBroker) throws PersistenceBrokerException {
277        preUpdate();
278    }
279
280    /**
281     * Default implementation of the JPA {@link PreUpdate} hook which generates the unique objectId for this
282     * persistable business object if it does not already have one.  Any sub-class which overrides this method
283     * should take care to invoke super.preUpdate to ensure that the objectId for this persistable
284     * business object is generated properly.
285     *
286     * <p>This method is currently invoked by the corresponding OJB {@link #beforeUpdate(PersistenceBroker)} hook.
287     */
288    @PreUpdate
289    protected void preUpdate() {
290        generateAndSetObjectIdIfNeeded();
291    }
292
293    /**
294     * If this PersistableBusinessObject does not already have a unique objectId, this method will generate
295     * one and set it's value on this object.
296     */
297    private void generateAndSetObjectIdIfNeeded() {
298        if (StringUtils.isEmpty(getObjectId())) {
299            setObjectId(UUID.randomUUID().toString());
300        }
301    }
302
303    /**
304     * getService Refreshes the reference objects from the primitive values.
305     *
306     * @see org.kuali.rice.krad.bo.BusinessObject#refresh()
307     */
308    @Override
309    public void refresh() {
310        getLegacyDataAdapter().refresh(this);
311    }
312
313    @Override
314    public void refreshNonUpdateableReferences() {
315        getLegacyDataAdapter().refreshNonUpdateableReferences(this);
316    }
317
318        @Override
319    public void refreshReferenceObject(String referenceObjectName) {
320        getLegacyDataAdapter().refreshReferenceObject(this, referenceObjectName);
321        }
322
323    @Override
324    public List<Collection<PersistableBusinessObject>> buildListOfDeletionAwareLists() {
325        return new ArrayList<Collection<PersistableBusinessObject>>();
326    }
327
328    @Override
329    public void linkEditableUserFields() {
330        // do nothing
331    }
332
333        @Override
334    public PersistableBusinessObjectExtension getExtension() {
335                if ( extension == null
336                && getLegacyDataAdapter().isPersistable(this.getClass())) {
337                        try {
338                extension = getLegacyDataAdapter().getExtension(this.getClass());
339                        } catch ( Exception ex ) {
340                                LOG.error( "unable to create extension object", ex );
341                        }
342                }
343                return extension;
344        }
345
346        @Override
347    public void setExtension(PersistableBusinessObjectExtension extension) {
348                this.extension = extension;
349        }
350
351    /**
352     * Returns the legacy data adapter for handling legacy KNS and KRAD data and metadata.
353     *
354     * @return the legacy data adapter
355     * @deprecated application code should never use this! Always use KRAD code directly.
356     */
357    @Deprecated
358    protected static LegacyAppFrameworkAdapterService getLegacyDataAdapter() {
359        return KNSServiceLocator.getLegacyAppFrameworkAdapterService();
360    }
361
362}