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.kuali.rice.core.api.search.SearchOperator; 022import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils; 023import org.kuali.rice.core.framework.persistence.jpa.OrmUtils; 024import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory; 025import org.kuali.rice.kew.api.document.attribute.DocumentAttributeInteger; 026import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 027import org.kuali.rice.kew.service.KEWServiceLocator; 028import org.kuali.rice.kew.api.KewApiConstants; 029 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.ManyToOne; 038import javax.persistence.NamedQueries; 039import javax.persistence.NamedQuery; 040import javax.persistence.Table; 041import javax.persistence.Transient; 042import java.io.Serializable; 043import java.math.BigInteger; 044import java.sql.ResultSet; 045import java.sql.SQLException; 046import java.text.DecimalFormat; 047import java.text.NumberFormat; 048import java.util.Arrays; 049import java.util.List; 050import java.util.regex.Matcher; 051import java.util.regex.Pattern; 052 053/** 054 * 055 * @author Kuali Rice Team (rice.collab@kuali.org) 056 */ 057@Entity 058@Table(name="KREW_DOC_HDR_EXT_LONG_T") 059//@Sequence(name="KREW_SRCH_ATTR_S",property="searchableAttributeValueId") 060@NamedQueries({ 061 @NamedQuery(name="SearchableAttributeLongValue.FindByDocumentId", query="select s from SearchableAttributeLongValue as s where s.documentId = :documentId"), 062 @NamedQuery(name="SearchableAttributeLongValue.FindByKey", query="select s from SearchableAttributeLongValue as s where s.documentId = :documentId and s.searchableAttributeKey = :searchableAttributeKey") 063}) 064public class SearchableAttributeLongValue implements SearchableAttributeValue, Serializable { 065 066 private static final long serialVersionUID = 5786144436732198346L; 067 068 private static final String ATTRIBUTE_DATABASE_TABLE_NAME = "KREW_DOC_HDR_EXT_LONG_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 DEFAULT_VALIDATION_REGEX_EXPRESSION = "^-?[0-9]+$"; 073 private static final String ATTRIBUTE_XML_REPRESENTATION = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_LONG; 074 private static final String DEFAULT_FORMAT_PATTERN = "#"; 075 076 @Id 077 @GeneratedValue(generator="KREW_SRCH_ATTR_S") 078 @GenericGenerator(name="KREW_SRCH_ATTR_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={ 079 @Parameter(name="sequence_name",value="KREW_SRCH_ATTR_S"), 080 @Parameter(name="value_column",value="id") 081 }) 082 @Column(name="DOC_HDR_EXT_LONG_ID") 083 private String searchableAttributeValueId; 084 @Column(name="KEY_CD") 085 private String searchableAttributeKey; 086 @Column(name="VAL") 087 private Long searchableAttributeValue; 088 @Transient 089 protected String ojbConcreteClass; // attribute needed for OJB polymorphism - do not alter! 090 091 @Column(name="DOC_HDR_ID") 092 private String documentId; 093 @ManyToOne(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST}) 094 @JoinColumn(name="DOC_HDR_ID", insertable=false, updatable=false) 095 private DocumentRouteHeaderValue routeHeader; 096 097 /** 098 * Default constructor. 099 */ 100 public SearchableAttributeLongValue() { 101 super(); 102 this.ojbConcreteClass = this.getClass().getName(); 103 } 104 105 /* (non-Javadoc) 106 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.lang.String) 107 */ 108 public void setupAttributeValue(String value) { 109 this.setSearchableAttributeValue(convertStringToLong(value)); 110 } 111 112 private Long convertStringToLong(String value) { 113 if (org.apache.commons.lang.StringUtils.isEmpty(value)) { 114 return null; 115 } else { 116 return Long.valueOf(value.trim()); 117 } 118 } 119 120 /* (non-Javadoc) 121 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.sql.ResultSet, java.lang.String) 122 */ 123 public void setupAttributeValue(ResultSet resultSet, String columnName) throws SQLException { 124 this.setSearchableAttributeValue(resultSet.getLong(columnName)); 125 } 126 127 /* (non-Javadoc) 128 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getSearchableAttributeDisplayValue(java.util.Map) 129 */ 130 public String getSearchableAttributeDisplayValue() { 131 NumberFormat format = DecimalFormat.getInstance(); 132 ((DecimalFormat)format).applyPattern(DEFAULT_FORMAT_PATTERN); 133 return format.format(getSearchableAttributeValue().longValue()); 134 } 135 136 /* (non-Javadoc) 137 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeDataType() 138 */ 139 public String getAttributeDataType() { 140 return ATTRIBUTE_XML_REPRESENTATION; 141 } 142 143 /* (non-Javadoc) 144 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeTableName() 145 */ 146 public String getAttributeTableName() { 147 return ATTRIBUTE_DATABASE_TABLE_NAME; 148 } 149 150 /* (non-Javadoc) 151 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsWildcardsByDefault() 152 */ 153 public boolean allowsWildcards() { 154 return DEFAULT_WILDCARD_ALLOWANCE_POLICY; 155 } 156 157 /* (non-Javadoc) 158 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsCaseInsensitivity() 159 */ 160 public boolean allowsCaseInsensitivity() { 161 return ALLOWS_CASE_INSENSITIVE_SEARCH; 162 } 163 164 /* (non-Javadoc) 165 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsRangeSearches() 166 */ 167 public boolean allowsRangeSearches() { 168 return ALLOWS_RANGE_SEARCH; 169 } 170 171 /* (non-Javadoc) 172 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isPassesDefaultValidation() 173 */ 174 public boolean isPassesDefaultValidation(String valueEntered) { 175 176 boolean bRet = true; 177 boolean bSplit = false; 178 179 if (StringUtils.contains(valueEntered, SearchOperator.BETWEEN.op())) { 180 List<String> l = Arrays.asList(valueEntered.split("\\.\\.")); 181 for(String value : l){ 182 bSplit = true; 183 if(!isPassesDefaultValidation(value)){ 184 bRet = false; 185 } 186 } 187 } 188 if (StringUtils.contains(valueEntered, SearchOperator.OR.op())) { 189 //splitValueList.addAll(Arrays.asList(StringUtils.split(valueEntered, KRADConstants.OR_LOGICAL_OPERATOR))); 190 List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.OR.op())); 191 for(String value : l){ 192 bSplit = true; 193 if(!isPassesDefaultValidation(value)){ 194 bRet = false; 195 } 196 } 197 } 198 if (StringUtils.contains(valueEntered, SearchOperator.AND.op())) { 199 //splitValueList.addAll(Arrays.asList(StringUtils.split(valueEntered, KRADConstants.AND_LOGICAL_OPERATOR))); 200 List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.AND.op())); 201 for(String value : l){ 202 bSplit = true; 203 if(!isPassesDefaultValidation(value)){ 204 bRet = false; 205 } 206 } 207 } 208 209 if(bSplit){ 210 return bRet; 211 } 212 213 Pattern pattern = Pattern.compile(DEFAULT_VALIDATION_REGEX_EXPRESSION); 214 Matcher matcher = pattern.matcher(SQLUtils.cleanNumericOfValidOperators(valueEntered).trim()); 215 if(!matcher.matches()){ 216 bRet = false; 217 } 218 219 return bRet; 220 221 } 222 223 224 /* (non-Javadoc) 225 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isRangeValid(java.lang.String, java.lang.String) 226 */ 227 public Boolean isRangeValid(String lowerValue, String upperValue) { 228 if (allowsRangeSearches()) { 229 Long lower = convertStringToLong(lowerValue); 230 Long upper = convertStringToLong(upperValue); 231 if ( (lower != null) && (upper != null) ) { 232 return (lower.compareTo(upper) <= 0); 233 } 234 return true; 235 } 236 return null; 237 } 238 239 public String getOjbConcreteClass() { 240 return ojbConcreteClass; 241 } 242 243 public void setOjbConcreteClass(String ojbConcreteClass) { 244 this.ojbConcreteClass = ojbConcreteClass; 245 } 246 247 public DocumentRouteHeaderValue getRouteHeader() { 248 return routeHeader; 249 } 250 251 public void setRouteHeader(DocumentRouteHeaderValue routeHeader) { 252 this.routeHeader = routeHeader; 253 } 254 255 public String getDocumentId() { 256 return documentId; 257 } 258 259 public void setDocumentId(String documentId) { 260 this.documentId = documentId; 261 } 262 263 public String getSearchableAttributeKey() { 264 return searchableAttributeKey; 265 } 266 267 public void setSearchableAttributeKey(String searchableAttributeKey) { 268 this.searchableAttributeKey = searchableAttributeKey; 269 } 270 271 public Long getSearchableAttributeValue() { 272 return searchableAttributeValue; 273 } 274 275 public void setSearchableAttributeValue(Long searchableAttributeValue) { 276 this.searchableAttributeValue = searchableAttributeValue; 277 } 278 279 public String getSearchableAttributeValueId() { 280 return searchableAttributeValueId; 281 } 282 283 public void setSearchableAttributeValueId(String searchableAttributeValueId) { 284 this.searchableAttributeValueId = searchableAttributeValueId; 285 } 286 287 //@PrePersist 288 public void beforeInsert(){ 289 OrmUtils.populateAutoIncValue(this, KEWServiceLocator.getEntityManagerFactory().createEntityManager()); 290 } 291 292 @Override 293 public DocumentAttributeInteger toDocumentAttribute() { 294 BigInteger integer = null; 295 if (getSearchableAttributeValue() != null) { 296 integer = BigInteger.valueOf(getSearchableAttributeValue().longValue()); 297 } 298 return DocumentAttributeFactory.createIntegerAttribute(getSearchableAttributeKey(), integer); 299 } 300 301 @Override 302 public int hashCode() { 303 final int prime = 31; 304 int result = 1; 305 result = prime * result + ((this.documentId == null) ? 0 : this.documentId.hashCode()); 306 result = prime * result + ((this.searchableAttributeKey == null) ? 0 : this.searchableAttributeKey.hashCode()); 307 result = prime * result 308 + ((this.searchableAttributeValue == null) ? 0 : this.searchableAttributeValue.hashCode()); 309 return result; 310 } 311 312 @Override 313 public boolean equals(Object obj) { 314 if (this == obj) 315 return true; 316 if (obj == null) 317 return false; 318 if (getClass() != obj.getClass()) 319 return false; 320 SearchableAttributeLongValue other = (SearchableAttributeLongValue) obj; 321 if (this.documentId == null) { 322 if (other.documentId != null) 323 return false; 324 } else if (!this.documentId.equals(other.documentId)) 325 return false; 326 if (this.searchableAttributeKey == null) { 327 if (other.searchableAttributeKey != null) 328 return false; 329 } else if (!this.searchableAttributeKey.equals(other.searchableAttributeKey)) 330 return false; 331 if (this.searchableAttributeValue == null) { 332 if (other.searchableAttributeValue != null) 333 return false; 334 } else if (!this.searchableAttributeValue.equals(other.searchableAttributeValue)) 335 return false; 336 return true; 337 } 338 339} 340