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.kew.docsearch;
017
018import org.apache.commons.lang.StringUtils;
019import org.hibernate.annotations.GenericGenerator;
020import org.hibernate.annotations.Parameter;
021import org.joda.time.DateTime;
022import org.kuali.rice.core.api.CoreApiServiceLocator;
023import org.kuali.rice.core.api.util.RiceConstants;
024import org.kuali.rice.core.framework.persistence.jdbc.sql.SqlBuilder;
025import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
026import org.kuali.rice.kew.api.KewApiConstants;
027import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDateTime;
028import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
029import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
030import org.kuali.rice.kew.service.KEWServiceLocator;
031
032import javax.persistence.CascadeType;
033import javax.persistence.Column;
034import javax.persistence.Entity;
035import javax.persistence.FetchType;
036import javax.persistence.GeneratedValue;
037import javax.persistence.Id;
038import javax.persistence.JoinColumn;
039import javax.persistence.ManyToOne;
040import javax.persistence.NamedQueries;
041import javax.persistence.NamedQuery;
042import javax.persistence.Table;
043import javax.persistence.Transient;
044import java.io.Serializable;
045import java.sql.Date;
046import java.sql.ResultSet;
047import java.sql.SQLException;
048import java.sql.Timestamp;
049import java.text.DateFormat;
050import java.text.ParseException;
051import java.text.SimpleDateFormat;
052import java.util.Calendar;
053
054
055/**
056 *
057 * @author Kuali Rice Team (rice.collab@kuali.org)
058 */
059@Entity
060@Table(name="KREW_DOC_HDR_EXT_DT_T")
061//@Sequence(name="KREW_SRCH_ATTR_S",property="searchableAttributeValueId")
062@NamedQueries({
063        @NamedQuery(name="SearchableAttributeDateTimeValue.FindByDocumentId", query="select s from SearchableAttributeDateTimeValue as s where s.documentId = :documentId"),
064        @NamedQuery(name="SearchableAttributeDateTimeValue.FindByKey", query="select s from SearchableAttributeDateTimeValue as s where s.documentId = :documentId and s.searchableAttributeKey = :searchableAttributeKey")
065})
066public class SearchableAttributeDateTimeValue implements SearchableAttributeValue, Serializable {
067    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SearchableAttributeDateTimeValue.class);
068
069    private static final long serialVersionUID = 3045621112943214772L;
070
071    private static final String ATTRIBUTE_DATABASE_TABLE_NAME = "KREW_DOC_HDR_EXT_DT_T";
072    private static final boolean DEFAULT_WILDCARD_ALLOWANCE_POLICY = false;
073    private static final boolean ALLOWS_RANGE_SEARCH = true;
074    private static final boolean ALLOWS_CASE_INSENSITIVE_SEARCH = false;
075    private static final String ATTRIBUTE_XML_REPRESENTATION = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_DATE;
076
077    @Id
078    @GeneratedValue(generator="KREW_SRCH_ATTR_S")
079        @GenericGenerator(name="KREW_SRCH_ATTR_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
080                        @Parameter(name="sequence_name",value="KREW_SRCH_ATTR_S"),
081                        @Parameter(name="value_column",value="id")
082        })
083        @Column(name="DOC_HDR_EXT_DT_ID")
084        private String searchableAttributeValueId;
085    @Column(name="KEY_CD")
086        private String searchableAttributeKey;
087        @Column(name="VAL")
088        private Timestamp searchableAttributeValue;
089    @Transient
090    protected String ojbConcreteClass; // attribute needed for OJB polymorphism - do not alter!
091
092    @Column(name="DOC_HDR_ID")
093        private String documentId;
094    @ManyToOne(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST})
095        @JoinColumn(name="DOC_HDR_ID", insertable=false, updatable=false)
096        private DocumentRouteHeaderValue routeHeader;
097
098    /**
099     * Default constructor.
100     */
101    public SearchableAttributeDateTimeValue() {
102        super();
103        this.ojbConcreteClass = this.getClass().getName();
104    }
105
106    /* (non-Javadoc)
107     * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.lang.String)
108     */
109    public void setupAttributeValue(String value) {
110        this.setSearchableAttributeValue(convertStringToTimestamp(value));
111    }
112
113    private Timestamp convertStringToTimestamp(String value) {
114        if (org.apache.commons.lang.StringUtils.isEmpty(value)) {
115            return null;
116        } else {
117            Timestamp t;
118            try {
119                t = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(value);
120            } catch (ParseException e) {
121                t = null;
122            }
123            if (t == null) {
124                String errorMsg = "Error converting timestamp value '" + value + "' to valid timestamp object.";
125                LOG.error("setupAttributeValue() " + errorMsg);
126                throw new RuntimeException(errorMsg);
127            }
128            return t;
129        }
130    }
131
132        /* (non-Javadoc)
133         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.sql.ResultSet, java.lang.String)
134         */
135        public void setupAttributeValue(ResultSet resultSet, String columnName) throws SQLException {
136                Calendar c = Calendar.getInstance();
137                c.clear(Calendar.HOUR);
138                c.clear(Calendar.MINUTE);
139                c.clear(Calendar.SECOND);
140                c.clear(Calendar.MILLISECOND);
141                this.setSearchableAttributeValue(resultSet.getTimestamp(columnName, c));
142        }
143
144        /* (non-Javadoc)
145         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getSearchableAttributeDisplayValue()
146         */
147    public String getSearchableAttributeDisplayValue() {
148        return formatAttributeValue(null);
149    }
150
151    private String formatAttributeValue(String formatPattern) {
152        DateFormat df = getDateFormatToUse(formatPattern);
153        return df.format(new Date(getSearchableAttributeValue().getTime()));
154    }
155
156    private DateFormat getDateFormatToUse(String parameterFormatPattern) {
157        if (StringUtils.isNotBlank(parameterFormatPattern)) {
158            return new SimpleDateFormat(parameterFormatPattern);
159        }
160        return RiceConstants.getDefaultDateFormat();
161    }
162
163        /* (non-Javadoc)
164         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeDataType()
165         */
166        public String getAttributeDataType() {
167                return ATTRIBUTE_XML_REPRESENTATION;
168        }
169
170        /* (non-Javadoc)
171         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeTableName()
172         */
173        public String getAttributeTableName() {
174                return ATTRIBUTE_DATABASE_TABLE_NAME;
175        }
176
177    /* (non-Javadoc)
178         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsWildcardsByDefault()
179         */
180        public boolean allowsWildcards() {
181                return DEFAULT_WILDCARD_ALLOWANCE_POLICY;
182        }
183
184    /* (non-Javadoc)
185         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsCaseInsensitivity()
186         */
187        public boolean allowsCaseInsensitivity() {
188                return ALLOWS_CASE_INSENSITIVE_SEARCH;
189        }
190
191        /* (non-Javadoc)
192         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsRangeSearches()
193         */
194        public boolean allowsRangeSearches() {
195                return ALLOWS_RANGE_SEARCH;
196        }
197
198        /* (non-Javadoc)
199         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isPassesDefaultValidation()
200         */
201    public boolean isPassesDefaultValidation(String valueEntered) {
202        return new SqlBuilder().isValidDate(valueEntered);
203        //return (DocSearchUtils.getEntryFormattedDate(valueEntered) != null);
204    }
205
206    /* (non-Javadoc)
207     * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isRangeValid(java.lang.String, java.lang.String)
208     */
209    public Boolean isRangeValid(String lowerValue, String upperValue) {
210        if (allowsRangeSearches()) {
211            Timestamp lowerTime = convertStringToTimestamp(lowerValue);
212            Timestamp upperTime = convertStringToTimestamp(upperValue);
213            if ( (lowerTime != null) && (upperTime != null) ) {
214                return (lowerTime.compareTo(upperTime) <= 0);
215            }
216            return true;
217        }
218        return null;
219    }
220
221        public String getOjbConcreteClass() {
222        return ojbConcreteClass;
223    }
224
225    public void setOjbConcreteClass(String ojbConcreteClass) {
226        this.ojbConcreteClass = ojbConcreteClass;
227    }
228
229    public DocumentRouteHeaderValue getRouteHeader() {
230        return routeHeader;
231    }
232
233    public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
234        this.routeHeader = routeHeader;
235    }
236
237    public String getDocumentId() {
238        return documentId;
239    }
240
241    public void setDocumentId(String documentId) {
242        this.documentId = documentId;
243    }
244
245    public String getSearchableAttributeKey() {
246        return searchableAttributeKey;
247    }
248
249    public void setSearchableAttributeKey(String searchableAttributeKey) {
250        this.searchableAttributeKey = searchableAttributeKey;
251    }
252
253    public Timestamp getSearchableAttributeValue() {
254        return searchableAttributeValue;
255    }
256
257    public void setSearchableAttributeValue(Timestamp searchableAttributeValue) {
258        this.searchableAttributeValue = searchableAttributeValue;
259    }
260
261    public String getSearchableAttributeValueId() {
262        return searchableAttributeValueId;
263    }
264
265    public void setSearchableAttributeValueId(String searchableAttributeValueId) {
266        this.searchableAttributeValueId = searchableAttributeValueId;
267    }
268
269        //@PrePersist
270        public void beforeInsert(){
271                OrmUtils.populateAutoIncValue(this, KEWServiceLocator.getEntityManagerFactory().createEntityManager());
272        }
273
274    @Override
275    public DocumentAttributeDateTime toDocumentAttribute() {
276        DateTime dateTime = null;
277        if (getSearchableAttributeValue() != null) {
278            dateTime = new DateTime(getSearchableAttributeValue().getTime());
279        }
280        return DocumentAttributeFactory.createDateTimeAttribute(getSearchableAttributeKey(), dateTime);
281    }
282}
283