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.ken.bo;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.apache.commons.lang.StringUtils;
020import org.joda.time.DateTime;
021import org.kuali.rice.ken.api.notification.Notification;
022import org.kuali.rice.ken.api.notification.NotificationContract;
023import org.kuali.rice.ken.api.notification.NotificationRecipient;
024import org.kuali.rice.ken.api.notification.NotificationSender;
025import org.kuali.rice.ken.util.NotificationConstants;
026import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
027import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
028
029import javax.persistence.Basic;
030import javax.persistence.CascadeType;
031import javax.persistence.Column;
032import javax.persistence.Entity;
033import javax.persistence.FetchType;
034import javax.persistence.GeneratedValue;
035import javax.persistence.Id;
036import javax.persistence.JoinColumn;
037import javax.persistence.Lob;
038import javax.persistence.OneToMany;
039import javax.persistence.OneToOne;
040import javax.persistence.OrderBy;
041import javax.persistence.Table;
042import java.sql.Timestamp;
043import java.util.ArrayList;
044import java.util.List;
045
046/**
047 * This class represents an instace of a notification message that is received by the overall 
048 * system.
049 * @author Kuali Rice Team (rice.collab@kuali.org)
050 */
051@Entity
052@Table(name="KREN_NTFCTN_T")
053public class NotificationBo extends PersistableBusinessObjectBase implements NotificationContract, Lockable {
054   
055    @Id
056    @GeneratedValue(generator="KREN_NTFCTN_S")
057    @PortableSequenceGenerator(name="KREN_NTFCTN_S")
058        @Column(name="NTFCTN_ID", nullable = false)
059        private Long id;
060    @Column(name="DELIV_TYP", nullable=false)
061        private String deliveryType;
062        @Column(name="CRTE_DTTM", nullable=false)
063        private Timestamp creationDateTimeValue;
064        @Column(name="SND_DTTM", nullable=true)
065        private Timestamp sendDateTimeValue;
066        @Column(name="AUTO_RMV_DTTM", nullable=true)
067        private Timestamp autoRemoveDateTimeValue;
068    @Column(name="TTL", nullable=true)
069        private String title;
070    @Lob
071        @Basic(fetch=FetchType.LAZY)
072        @Column(name="CNTNT", nullable=false)
073        private String content;
074    @Column(name="PROCESSING_FLAG", nullable=false)
075        private String processingFlag;
076        @Column(name="LOCKD_DTTM", nullable=true)
077        private Timestamp lockedDateValue;
078    @Column(name = "DOC_TYP_NM", nullable = true)
079    private String docTypeName;
080    /**
081     * Lock column for OJB optimistic locking
082     */
083//    @Version
084//      @Column(name="VER_NBR")
085//      private Integer lockVerNbr;
086    
087    // object references
088    @OneToOne(fetch=FetchType.EAGER, cascade={CascadeType.REFRESH, CascadeType.DETACH})
089        @JoinColumn(name="PRIO_ID")
090        private NotificationPriorityBo priority;
091    @OneToOne(fetch=FetchType.EAGER, cascade={CascadeType.REFRESH, CascadeType.DETACH})
092        @JoinColumn(name="CNTNT_TYP_ID", nullable=false)
093        private NotificationContentTypeBo contentType;
094    @OneToOne(fetch=FetchType.EAGER, cascade={CascadeType.REFRESH, CascadeType.DETACH})
095        @JoinColumn(name="CHNL_ID")
096        private NotificationChannelBo channel;
097    @OneToOne(fetch=FetchType.EAGER, cascade={CascadeType.REFRESH, CascadeType.DETACH})
098        @JoinColumn(name="PRODCR_ID")
099        private NotificationProducerBo producer;
100    
101    // lists
102    @OneToMany(cascade={CascadeType.ALL},
103            targetEntity=NotificationRecipientBo.class, mappedBy = "notification")
104    @OrderBy("id ASC")
105        private List<NotificationRecipientBo> recipients;
106
107    @OneToMany(cascade={CascadeType.ALL},
108           targetEntity=NotificationSenderBo.class, mappedBy="notification")
109        @OrderBy("id ASC")
110    private List<NotificationSenderBo> senders;
111    
112    /**
113     * Constructs a Notification instance.
114     */
115    public NotificationBo() {
116        recipients = new ArrayList<NotificationRecipientBo>();
117        senders = new ArrayList<NotificationSenderBo>();
118        processingFlag = NotificationConstants.PROCESSING_FLAGS.UNRESOLVED;
119    }
120
121    /**
122     * Returns when this Notification entry was created 
123     * @return when this Notification entry was created
124     */
125    public Timestamp getCreationDateTimeValue() {
126        return creationDateTimeValue;
127    }
128
129    @Override
130    public DateTime getCreationDateTime() {
131        return this.creationDateTimeValue == null ? null : new DateTime(this.creationDateTimeValue);
132    }
133
134    /**
135     * Sets the creation date of this Notification entry
136     * @param created the creation date of this Notification entry
137     */
138    public void setCreationDateTimeValue(Timestamp created) {
139        this.creationDateTimeValue = created;
140    }
141
142    /**
143     * Return value of lock column for OJB optimistic locking
144     * @return value of lock column for OJB optimistic locking
145     */
146 // should discard this method and call super directly
147    public Integer getLockVerNbr() {
148        return Integer.valueOf(super.getVersionNumber().intValue());
149    }
150
151    /**
152     * Set value of lock column for OJB optimistic locking
153     * @param lockVerNbr value of lock column for OJB optimistic locking
154     */
155 // should discard this method and call super directly
156    public void setLockVerNbr(Integer lockVerNbr) {
157        super.setVersionNumber(lockVerNbr.longValue());
158    }
159
160    /**
161     * Gets the recipients attribute. 
162     * @return Returns the recipients.
163     */
164    public List<NotificationRecipientBo> getRecipients() {
165        return recipients;
166    }
167
168    /**
169     * Sets the recipients attribute value.
170     * @param recipients The recipients to set.
171     */
172    public void setRecipients(List<NotificationRecipientBo> recipients) {
173        this.recipients = recipients;
174    }
175
176    /**
177     * Retrieves a recipient at the specified index
178     * @param index the index in the recipients collection
179     * @return the recipient if found or null
180     */
181    public NotificationRecipientBo getRecipient(int index) {
182        return (NotificationRecipientBo) recipients.get(index);
183    }
184    
185    /**
186     * Adds a recipient
187     * @param recipient The recipient to add
188     */
189    public void addRecipient(NotificationRecipientBo recipient) {
190        recipients.add(recipient);
191    }
192
193    /**
194     * Gets the senders attribute. 
195     * @return Returns the senders.
196     */
197    public List<NotificationSenderBo> getSenders() {
198        return senders;
199    }
200
201    /**
202     * Sets the senders attribute value.
203     * @param senders The senders to set.
204     */
205    public void setSenders(List<NotificationSenderBo> senders) {
206        this.senders = senders;
207    }
208
209    /**
210     * Retrieves a sender at the specified index
211     * @param index the index in the senders collection
212     * @return the sender if found or null
213     */
214    public NotificationSenderBo getSender(int index) {
215        return (NotificationSenderBo) senders.get(index);
216    }
217    /**
218     * Adds a sender
219     * @param sender The sender to add
220     */
221    public void addSender(NotificationSenderBo sender) {
222        senders.add(sender);
223    }
224
225    /**
226     * Gets the autoRemoveDateTime attribute. 
227     * @return Returns the autoRemoveDateTime.
228     */
229    public Timestamp getAutoRemoveDateTimeValue() {
230            return this.autoRemoveDateTimeValue;
231    }
232
233    @Override
234    public DateTime getAutoRemoveDateTime() {
235        return this.autoRemoveDateTimeValue == null ? null : new DateTime(this.autoRemoveDateTimeValue);
236    }
237
238    /**
239     * Sets the autoRemoveDateTime attribute value.
240     * @param autoRemoveDateTimeValue The autoRemoveDateTime to set.
241     */
242    public void setAutoRemoveDateTimeValue(Timestamp autoRemoveDateTimeValue) {
243            this.autoRemoveDateTimeValue = autoRemoveDateTimeValue;
244    }
245
246    /**
247     * Gets the channel attribute. 
248     * @return Returns the channel.
249     */
250    public NotificationChannelBo getChannel() {
251            return channel;
252    }
253
254    /**
255     * Sets the channel attribute value.
256     * @param channel The channel to set.
257     */
258    public void setChannel(NotificationChannelBo channel) {
259            this.channel = channel;
260    }
261
262    /**
263     * Gets the content attribute. 
264     * @return Returns the content.
265     */
266    public String getContent() {
267            return content;
268    }
269
270    /**
271     * Sets the content attribute value.
272     * @param content The content to set.
273     */
274    public void setContent(String content) {
275            this.content = content;
276    }
277
278    /**
279     * Gets the contentType attribute. 
280     * @return Returns the contentType.
281     */
282    public NotificationContentTypeBo getContentType() {
283            return contentType;
284    }
285
286    /**
287     * Sets the contentType attribute value.
288     * @param contentType The contentType to set.
289     */
290    public void setContentType(NotificationContentTypeBo contentType) {
291            this.contentType = contentType;
292    }
293
294    /**
295     * Gets the deliveryType attribute. 
296     * @return Returns the deliveryType.
297     */
298    public String getDeliveryType() {
299            return deliveryType;
300    }
301
302    /**
303     * Sets the deliveryType attribute value.
304     * @param deliveryType The deliveryType to set.
305     */
306    public void setDeliveryType(String deliveryType) {
307            this.deliveryType = deliveryType.toUpperCase();
308    }
309
310    /**
311     * Gets the id attribute. 
312     * @return Returns the id.
313     */
314    public Long getId() {
315            return id;
316    }
317
318    /**
319     * Sets the id attribute value.
320     * @param id The id to set.
321     */
322    public void setId(Long id) {
323            this.id = id;
324    }
325
326    /**
327     * Gets the priority attribute. 
328     * @return Returns the priority.
329     */
330    public NotificationPriorityBo getPriority() {
331            return priority;
332    }
333
334    /**
335     * Sets the priority attribute value.
336     * @param priority The priority to set.
337     */
338    public void setPriority(NotificationPriorityBo priority) {
339            this.priority = priority;
340    }
341
342    /**
343     * Gets the producer attribute. 
344     * @return Returns the producer.
345     */
346    public NotificationProducerBo getProducer() {
347            return producer;
348    }
349
350    /**
351     * Sets the producer attribute value.
352     * @param producer The producer to set.
353     */
354    public void setProducer(NotificationProducerBo producer) {
355            this.producer = producer;
356    }
357
358    /**
359     * Gets the sendDateTime attribute. 
360     * @return Returns the sendDateTime.
361     */
362    public Timestamp getSendDateTimeValue() {
363            return this.sendDateTimeValue;
364    }
365
366    @Override
367    public DateTime getSendDateTime() {
368        return this.sendDateTimeValue == null ? null : new DateTime(this.sendDateTimeValue);
369    }
370
371    /**
372     * Sets the sendDateTime attribute value.
373     * @param sendDateTimeValue The sendDateTime to set.
374     */
375    public void setSendDateTimeValue(Timestamp sendDateTimeValue) {
376            this.sendDateTimeValue = sendDateTimeValue;
377    }
378
379    /**
380     * Gets the processingFlag attribute. 
381     * @return Returns the processingFlag.
382     */
383    public String getProcessingFlag() {
384        return processingFlag;
385    }
386
387    /**
388     * Sets the processingFlag attribute value.
389     * @param processingFlag The processingFlag to set.
390     */
391    public void setProcessingFlag(String processingFlag) {
392        this.processingFlag = processingFlag;
393    }
394    
395    /**
396     * Gets the lockedDate attribute. 
397     * @return Returns the lockedDate.
398     */
399    public Timestamp getLockedDateValue() {
400        return this.lockedDateValue;
401    }
402
403    @Override
404    public DateTime getLockedDate() {
405        return this.lockedDateValue == null ? null : new DateTime(this.lockedDateValue);
406    }
407    
408    /**
409     * Sets the lockedDate attribute value.
410     * @param lockedDateValue The lockedDate to set.
411     */
412    public void setLockedDateValue(Timestamp lockedDateValue) {
413        this.lockedDateValue = lockedDateValue;
414    }
415
416    /**
417     * Gets the title
418     * @return the title of this notification
419     */
420    public String getTitle() {
421        return title;
422    }
423
424    /**
425     * Sets the title
426     * @param title the title of this notification
427     */
428    public void setTitle(String title) {
429        this.title = title;
430    }
431
432    /**
433     * This method just uses StringUtils to get at the content of the <message> tag 
434     * that exists in the notification content.
435     * @return String
436     */
437    public String getContentMessage() {
438            return StringUtils.substringBetween(content, NotificationConstants.XML_MESSAGE_CONSTANTS.MESSAGE_OPEN, NotificationConstants.XML_MESSAGE_CONSTANTS.MESSAGE_CLOSE);  
439    }
440
441    /**
442     * {@inheritDoc}
443     */
444    @Override
445    public String getDocTypeName() {
446        return docTypeName;
447    }
448
449    /**
450     * Sets the custom document type name.
451     *
452     * <p>
453     * If null, the system will use the default {@code KualiNotification} document type when routing the notification.
454     * If the document type does not match any document type name in the system, the system behavior is undefined.
455     * </p>
456     *
457     * @param docTypeName document type name of this notification
458     */
459    public void setDocTypeName(String docTypeName) {
460        this.docTypeName = docTypeName;
461    }
462
463    /**
464     * Converts a mutable bo to its immutable counterpart
465     * @param bo the mutable business object
466     * @return the immutable object
467     */
468    public static Notification to(NotificationBo bo) {
469        if (bo == null) {
470            return null;
471        }
472
473        return Notification.Builder.create(bo).build();
474    }
475
476    /**
477     * Converts a immutable object to its mutable counterpart
478     * @param im immutable object
479     * @return the mutable bo
480     */
481    public static NotificationBo from(Notification im) {
482        if (im == null) {
483            return null;
484        }
485
486        NotificationBo bo = new NotificationBo();
487        bo.setId(im.getId());
488        bo.setVersionNumber(im.getVersionNumber());
489        bo.setObjectId(im.getObjectId());
490        bo.setDeliveryType(im.getDeliveryType());
491        bo.setCreationDateTimeValue(im.getCreationDateTime() == null ? null : new Timestamp(im.getCreationDateTime().getMillis()));
492        bo.setSendDateTimeValue(im.getSendDateTime() == null ? null : new Timestamp(im.getSendDateTime().getMillis()));
493        bo.setAutoRemoveDateTimeValue(im.getAutoRemoveDateTime() == null ? null : new Timestamp(im.getAutoRemoveDateTime().getMillis()));
494        bo.setTitle(im.getTitle());
495        bo.setContent(im.getContent());
496        bo.setLockedDateValue(im.getLockedDate() == null ? null : new Timestamp(im.getLockedDate().getMillis()));
497        bo.setDocTypeName(im.getDocTypeName());
498
499        // object references
500        bo.setPriority(NotificationPriorityBo.from(im.getPriority()));
501        bo.setContentType(NotificationContentTypeBo.from(im.getContentType()));
502        bo.setChannel(NotificationChannelBo.from(im.getChannel()));
503        bo.setProducer(NotificationProducerBo.from(im.getProducer()));
504
505        // lists
506        List<NotificationRecipientBo> tempRecipients = new ArrayList<NotificationRecipientBo>();
507        if (CollectionUtils.isNotEmpty(im.getRecipients())) {
508            for (NotificationRecipient recipient : im.getRecipients()) {
509                tempRecipients.add(NotificationRecipientBo.from(recipient));
510            }
511            bo.setRecipients(tempRecipients);
512        }
513        List<NotificationSenderBo> tempSenders = new ArrayList<NotificationSenderBo>();
514        if (CollectionUtils.isNotEmpty(im.getSenders())) {
515            for (NotificationSender sender : im.getSenders()) {
516                tempSenders.add(NotificationSenderBo.from(sender));
517            }
518            bo.setSenders(tempSenders);
519        }
520
521        return bo;
522    }
523}