001/**
002 * Copyright 2005-2017 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.joda.time.DateTime;
020import org.kuali.rice.core.api.CoreApiServiceLocator;
021import org.kuali.rice.core.api.util.RiceConstants;
022import org.kuali.rice.core.framework.persistence.jdbc.sql.SqlBuilder;
023import org.kuali.rice.kew.api.KewApiConstants;
024import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDateTime;
025import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
026
027import javax.persistence.AttributeOverride;
028import javax.persistence.AttributeOverrides;
029import javax.persistence.Column;
030import javax.persistence.Entity;
031import javax.persistence.Inheritance;
032import javax.persistence.InheritanceType;
033import javax.persistence.NamedQueries;
034import javax.persistence.NamedQuery;
035import javax.persistence.Table;
036import java.io.Serializable;
037import java.sql.Date;
038import java.sql.ResultSet;
039import java.sql.SQLException;
040import java.sql.Timestamp;
041import java.text.DateFormat;
042import java.text.ParseException;
043import java.text.SimpleDateFormat;
044import java.util.Calendar;
045
046/**
047 *
048 * @author Kuali Rice Team (rice.collab@kuali.org)
049 */
050@Entity
051@Inheritance(strategy= InheritanceType.TABLE_PER_CLASS)
052@Table(name="KREW_DOC_HDR_EXT_DT_T")
053@NamedQueries({
054        @NamedQuery(name="SearchableAttributeDateTimeValue.FindByDocumentId", query="select s from "
055        + "SearchableAttributeDateTimeValue as s where s.documentId = :documentId"),
056@NamedQuery(name="SearchableAttributeDateTimeValue.FindByKey", query="select s from "
057        + "SearchableAttributeDateTimeValue as s where s.documentId = :documentId and "
058        + "s.searchableAttributeKey = :searchableAttributeKey")
059})
060@AttributeOverrides({
061        @AttributeOverride(name="searchableAttributeValueId", column=@Column(name="DOC_HDR_EXT_DT_ID"))
062})
063public class SearchableAttributeDateTimeValue extends SearchableAttributeBase implements SearchableAttributeValue, Serializable {
064    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SearchableAttributeDateTimeValue.class);
065
066    private static final long serialVersionUID = 3045621112943214772L;
067
068    private static final String ATTRIBUTE_DATABASE_TABLE_NAME = "KREW_DOC_HDR_EXT_DT_T";
069    private static final boolean DEFAULT_WILDCARD_ALLOWANCE_POLICY = false;
070    private static final boolean ALLOWS_RANGE_SEARCH = true;
071    private static final boolean ALLOWS_CASE_INSENSITIVE_SEARCH = false;
072    private static final String ATTRIBUTE_XML_REPRESENTATION = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_DATE;
073
074        @Column(name="VAL")
075        private Timestamp searchableAttributeValue;
076
077    /**
078     * Default constructor.
079     */
080    public SearchableAttributeDateTimeValue() {
081        super();
082        this.ojbConcreteClass = this.getClass().getName();
083    }
084
085    public void setupAttributeValue(String value) {
086        this.setSearchableAttributeValue(convertStringToTimestamp(value));
087    }
088
089    private Timestamp convertStringToTimestamp(String value) {
090        if (org.apache.commons.lang.StringUtils.isEmpty(value)) {
091            return null;
092        } else {
093            Timestamp t;
094            try {
095                t = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(value);
096            } catch (ParseException e) {
097                t = null;
098            }
099            if (t == null) {
100                String errorMsg = "Error converting timestamp value '" + value + "' to valid timestamp object.";
101                LOG.error("setupAttributeValue() " + errorMsg);
102                throw new RuntimeException(errorMsg);
103            }
104            return t;
105        }
106    }
107
108    @Override
109        public void setupAttributeValue(ResultSet resultSet, String columnName) throws SQLException {
110                Calendar c = Calendar.getInstance();
111                c.clear(Calendar.HOUR);
112                c.clear(Calendar.MINUTE);
113                c.clear(Calendar.SECOND);
114                c.clear(Calendar.MILLISECOND);
115                this.setSearchableAttributeValue(resultSet.getTimestamp(columnName, c));
116        }
117
118    @Override
119    public String getSearchableAttributeDisplayValue() {
120        return formatAttributeValue(null);
121    }
122
123    private String formatAttributeValue(String formatPattern) {
124        DateFormat df = getDateFormatToUse(formatPattern);
125        return df.format(new Date(getSearchableAttributeValue().getTime()));
126    }
127
128    private DateFormat getDateFormatToUse(String parameterFormatPattern) {
129        if (StringUtils.isNotBlank(parameterFormatPattern)) {
130            return new SimpleDateFormat(parameterFormatPattern);
131        }
132        return RiceConstants.getDefaultDateFormat();
133    }
134
135    @Override
136        public String getAttributeDataType() {
137                return ATTRIBUTE_XML_REPRESENTATION;
138        }
139
140    @Override
141        public String getAttributeTableName() {
142                return ATTRIBUTE_DATABASE_TABLE_NAME;
143        }
144
145    @Override
146        public boolean allowsWildcards() {
147                return DEFAULT_WILDCARD_ALLOWANCE_POLICY;
148        }
149
150    @Override
151        public boolean allowsCaseInsensitivity() {
152                return ALLOWS_CASE_INSENSITIVE_SEARCH;
153        }
154
155    @Override
156        public boolean allowsRangeSearches() {
157                return ALLOWS_RANGE_SEARCH;
158        }
159
160    @Override
161    public boolean isPassesDefaultValidation(String valueEntered) {
162        return new SqlBuilder().isValidDate(valueEntered);
163        //return (DocSearchUtils.getEntryFormattedDate(valueEntered) != null);
164    }
165
166    @Override
167    public Boolean isRangeValid(String lowerValue, String upperValue) {
168        if (allowsRangeSearches()) {
169            Timestamp lowerTime = convertStringToTimestamp(lowerValue);
170            Timestamp upperTime = convertStringToTimestamp(upperValue);
171            if ( (lowerTime != null) && (upperTime != null) ) {
172                return (lowerTime.compareTo(upperTime) <= 0);
173            }
174            return true;
175        }
176        return null;
177    }
178
179    @Override
180    public Timestamp getSearchableAttributeValue() {
181        return searchableAttributeValue;
182    }
183
184    public void setSearchableAttributeValue(Timestamp searchableAttributeValue) {
185        this.searchableAttributeValue = searchableAttributeValue;
186    }
187
188    @Override
189    public DocumentAttributeDateTime toDocumentAttribute() {
190        DateTime dateTime = null;
191        if (getSearchableAttributeValue() != null) {
192            dateTime = new DateTime(getSearchableAttributeValue().getTime());
193        }
194        return DocumentAttributeFactory.createDateTimeAttribute(getSearchableAttributeKey(), dateTime);
195    }
196
197}
198