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 @Override 284 public int hashCode() { 285 final int prime = 31; 286 int result = 1; 287 result = prime * result + ((this.documentId == null) ? 0 : this.documentId.hashCode()); 288 result = prime * result + ((this.searchableAttributeKey == null) ? 0 : this.searchableAttributeKey.hashCode()); 289 result = prime * result 290 + ((this.searchableAttributeValue == null) ? 0 : this.searchableAttributeValue.hashCode()); 291 return result; 292 } 293 294 @Override 295 public boolean equals(Object obj) { 296 if (this == obj) 297 return true; 298 if (obj == null) 299 return false; 300 if (getClass() != obj.getClass()) 301 return false; 302 SearchableAttributeDateTimeValue other = (SearchableAttributeDateTimeValue) obj; 303 if (this.documentId == null) { 304 if (other.documentId != null) 305 return false; 306 } else if (!this.documentId.equals(other.documentId)) 307 return false; 308 if (this.searchableAttributeKey == null) { 309 if (other.searchableAttributeKey != null) 310 return false; 311 } else if (!this.searchableAttributeKey.equals(other.searchableAttributeKey)) 312 return false; 313 if (this.searchableAttributeValue == null) { 314 if (other.searchableAttributeValue != null) 315 return false; 316 } else if (!this.searchableAttributeValue.equals(other.searchableAttributeValue)) 317 return false; 318 return true; 319 } 320} 321