001 /** 002 * Copyright 2005-2013 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 */ 016 package org.kuali.rice.kew.docsearch; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.hibernate.annotations.GenericGenerator; 020 import org.hibernate.annotations.Parameter; 021 import org.kuali.rice.core.api.search.SearchOperator; 022 import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils; 023 import org.kuali.rice.core.framework.persistence.jpa.OrmUtils; 024 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDecimal; 025 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory; 026 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 027 import org.kuali.rice.kew.service.KEWServiceLocator; 028 import org.kuali.rice.kew.api.KewApiConstants; 029 030 import javax.persistence.CascadeType; 031 import javax.persistence.Column; 032 import javax.persistence.Entity; 033 import javax.persistence.FetchType; 034 import javax.persistence.GeneratedValue; 035 import javax.persistence.Id; 036 import javax.persistence.JoinColumn; 037 import javax.persistence.ManyToOne; 038 import javax.persistence.NamedQueries; 039 import javax.persistence.NamedQuery; 040 import javax.persistence.Table; 041 import javax.persistence.Transient; 042 import java.io.Serializable; 043 import java.math.BigDecimal; 044 import java.sql.ResultSet; 045 import java.sql.SQLException; 046 import java.text.DecimalFormat; 047 import java.text.NumberFormat; 048 import java.util.Arrays; 049 import java.util.List; 050 import java.util.regex.Matcher; 051 import 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_FLT_T") 059 //@Sequence(name="KREW_SRCH_ATTR_S",property="searchableAttributeValueId") 060 @NamedQueries({ 061 @NamedQuery(name="SearchableAttributeFloatValue.FindByDocumentId", query="select s from SearchableAttributeFloatValue as s where s.documentId = :documentId"), 062 @NamedQuery(name="SearchableAttributeFloatValue.FindByKey", query="select s from SearchableAttributeFloatValue as s where s.documentId = :documentId and s.searchableAttributeKey = :searchableAttributeKey") 063 }) 064 public class SearchableAttributeFloatValue implements SearchableAttributeValue, Serializable { 065 066 private static final long serialVersionUID = -6682101853805320760L; 067 068 private static final String ATTRIBUTE_DATABASE_TABLE_NAME = "KREW_DOC_HDR_EXT_FLT_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]*\\.?[0-9]+"; 073 private static final String ATTRIBUTE_XML_REPRESENTATION = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_FLOAT; 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_FLT_ID") 083 private String searchableAttributeValueId; 084 @Column(name="KEY_CD") 085 private String searchableAttributeKey; 086 @Column(name="VAL") 087 private BigDecimal 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 SearchableAttributeFloatValue() { 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(convertStringToBigDecimal(value)); 110 } 111 112 private BigDecimal convertStringToBigDecimal(String value) { 113 if (org.apache.commons.lang.StringUtils.isEmpty(value)) { 114 return null; 115 } else { 116 return new BigDecimal(value); 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.getBigDecimal(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).toPattern(); 133 ((DecimalFormat)format).applyPattern(DEFAULT_FORMAT_PATTERN); 134 return format.format(getSearchableAttributeValue().doubleValue()); 135 } 136 137 /* (non-Javadoc) 138 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeDataType() 139 */ 140 public String getAttributeDataType() { 141 return ATTRIBUTE_XML_REPRESENTATION; 142 } 143 144 /* (non-Javadoc) 145 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeTableName() 146 */ 147 public String getAttributeTableName() { 148 return ATTRIBUTE_DATABASE_TABLE_NAME; 149 } 150 151 /* (non-Javadoc) 152 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsWildcardsByDefault() 153 */ 154 public boolean allowsWildcards() { 155 return DEFAULT_WILDCARD_ALLOWANCE_POLICY; 156 } 157 158 /* (non-Javadoc) 159 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsCaseInsensitivity() 160 */ 161 public boolean allowsCaseInsensitivity() { 162 return ALLOWS_CASE_INSENSITIVE_SEARCH; 163 } 164 165 /* (non-Javadoc) 166 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsRangeSearches() 167 */ 168 public boolean allowsRangeSearches() { 169 return ALLOWS_RANGE_SEARCH; 170 } 171 172 /* (non-Javadoc) 173 * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isPassesDefaultValidation() 174 */ 175 public boolean isPassesDefaultValidation(String valueEntered) { 176 177 boolean bRet = true; 178 boolean bSplit = false; 179 180 if (StringUtils.contains(valueEntered, SearchOperator.BETWEEN.op())) { 181 List<String> l = Arrays.asList(valueEntered.split("\\.\\.")); 182 for(String value : l){ 183 bSplit = true; 184 if(!isPassesDefaultValidation(value)){ 185 bRet = false; 186 } 187 } 188 } 189 if (StringUtils.contains(valueEntered, SearchOperator.OR.op())) { 190 //splitValueList.addAll(Arrays.asList(StringUtils.split(valueEntered, KRADConstants.OR_LOGICAL_OPERATOR))); 191 List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.OR.op())); 192 for(String value : l){ 193 bSplit = true; 194 if(!isPassesDefaultValidation(value)){ 195 bRet = false; 196 } 197 } 198 } 199 if (StringUtils.contains(valueEntered, SearchOperator.AND.op())) { 200 //splitValueList.addAll(Arrays.asList(StringUtils.split(valueEntered, KRADConstants.AND_LOGICAL_OPERATOR))); 201 List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.AND.op())); 202 for(String value : l){ 203 bSplit = true; 204 if(!isPassesDefaultValidation(value)){ 205 bRet = false; 206 } 207 } 208 } 209 210 if(bSplit){ 211 return bRet; 212 } 213 214 Pattern pattern = Pattern.compile(DEFAULT_VALIDATION_REGEX_EXPRESSION); 215 Matcher matcher = pattern.matcher(SQLUtils.cleanNumericOfValidOperators(valueEntered).trim()); 216 if(!matcher.matches()){ 217 bRet = false; 218 } 219 220 return bRet; 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 BigDecimal lower = null; 230 BigDecimal upper = null; 231 try{ 232 lower = convertStringToBigDecimal(lowerValue); 233 upper = convertStringToBigDecimal(upperValue); 234 }catch(NumberFormatException ex){ 235 return false; 236 } 237 if ( (lower != null) && (upper != null) ) { 238 return (lower.compareTo(upper) <= 0); 239 } 240 return true; 241 } 242 return null; 243 } 244 245 public String getOjbConcreteClass() { 246 return ojbConcreteClass; 247 } 248 249 public void setOjbConcreteClass(String ojbConcreteClass) { 250 this.ojbConcreteClass = ojbConcreteClass; 251 } 252 253 public DocumentRouteHeaderValue getRouteHeader() { 254 return routeHeader; 255 } 256 257 public void setRouteHeader(DocumentRouteHeaderValue routeHeader) { 258 this.routeHeader = routeHeader; 259 } 260 261 public String getDocumentId() { 262 return documentId; 263 } 264 265 public void setDocumentId(String documentId) { 266 this.documentId = documentId; 267 } 268 269 public String getSearchableAttributeKey() { 270 return searchableAttributeKey; 271 } 272 273 public void setSearchableAttributeKey(String searchableAttributeKey) { 274 this.searchableAttributeKey = searchableAttributeKey; 275 } 276 277 public BigDecimal getSearchableAttributeValue() { 278 return searchableAttributeValue; 279 } 280 281 public void setSearchableAttributeValue(BigDecimal searchableAttributeValue) { 282 this.searchableAttributeValue = searchableAttributeValue; 283 } 284 285 /** 286 * @deprecated USE method setSearchableAttributeValue(BigDecimal) instead 287 */ 288 public void setSearchableAttributeValue(Float floatValueToTranslate) { 289 this.searchableAttributeValue = null; 290 if (floatValueToTranslate != null) { 291 this.searchableAttributeValue = new BigDecimal(floatValueToTranslate.toString()); 292 } 293 } 294 295 public String getSearchableAttributeValueId() { 296 return searchableAttributeValueId; 297 } 298 299 public void setSearchableAttributeValueId(String searchableAttributeValueId) { 300 this.searchableAttributeValueId = searchableAttributeValueId; 301 } 302 303 //@PrePersist 304 public void beforeInsert(){ 305 OrmUtils.populateAutoIncValue(this, KEWServiceLocator.getEntityManagerFactory().createEntityManager()); 306 } 307 308 @Override 309 public DocumentAttributeDecimal toDocumentAttribute() { 310 return DocumentAttributeFactory.createDecimalAttribute(getSearchableAttributeKey(), getSearchableAttributeValue()); 311 } 312 313 314 } 315