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.ObjectUtils;
019import org.apache.commons.lang.StringUtils;
020import org.hibernate.annotations.GenericGenerator;
021import org.hibernate.annotations.Parameter;
022import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
023import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
024import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
025import org.kuali.rice.kew.api.document.attribute.DocumentAttributeString;
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.*;
031import java.io.Serializable;
032import java.sql.ResultSet;
033import java.sql.SQLException;
034
035
036/**
037 *
038 * @author Kuali Rice Team (rice.collab@kuali.org)
039 */
040@Entity
041@Table(name="KREW_DOC_HDR_EXT_T")
042//@Sequence(name="KREW_SRCH_ATTR_S",property="searchableAttributeValueId")
043@NamedQueries({
044        @NamedQuery(name="SearchableAttributeStringValue.FindByDocumentId", query="select s from SearchableAttributeStringValue as s where s.documentId = :documentId"),
045        @NamedQuery(name="SearchableAttributeStringValue.FindByKey", query="select s from SearchableAttributeStringValue as s where s.documentId = :documentId and s.searchableAttributeKey = :searchableAttributeKey")
046})
047public class SearchableAttributeStringValue implements CaseAwareSearchableAttributeValue, Serializable {
048
049    private static final long serialVersionUID = 8696089933682052078L;
050
051    private static final String ATTRIBUTE_DATABASE_TABLE_NAME = "KREW_DOC_HDR_EXT_T";
052    private static final boolean DEFAULT_WILDCARD_ALLOWANCE_POLICY = true;
053    private static final boolean ALLOWS_RANGE_SEARCH = true;
054    private static final boolean ALLOWS_CASE_INSENSITIVE_SEARCH = true;
055    private static final String ATTRIBUTE_XML_REPRESENTATION = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING;
056    private static final int STRING_MAX_LENGTH = 2000; // should match table creation
057
058    @Id
059    @GeneratedValue(generator="KREW_SRCH_ATTR_S")
060        @GenericGenerator(name="KREW_SRCH_ATTR_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
061                        @Parameter(name="sequence_name",value="KREW_SRCH_ATTR_S"),
062                        @Parameter(name="value_column",value="id")
063        })
064        @Column(name="DOC_HDR_EXT_ID")
065        private String searchableAttributeValueId;
066    @Column(name="KEY_CD")
067        private String searchableAttributeKey;
068    @Column(name="VAL")
069        private String searchableAttributeValue;
070    @Transient
071    protected String ojbConcreteClass; // attribute needed for OJB polymorphism - do not alter!
072
073    @Column(name="DOC_HDR_ID")
074        private String documentId;
075    @ManyToOne(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST})
076        @JoinColumn(name="DOC_HDR_ID", insertable=false, updatable=false)
077        private DocumentRouteHeaderValue routeHeader;
078
079    /**
080     * Default constructor.
081     */
082    public SearchableAttributeStringValue() {
083        super();
084        this.ojbConcreteClass = this.getClass().getName();
085    }
086
087    /* (non-Javadoc)
088     * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.lang.String)
089     */
090    public void setupAttributeValue(String value) {
091        this.setSearchableAttributeValue(value);
092    }
093
094        /* (non-Javadoc)
095         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#setupAttributeValue(java.sql.ResultSet, java.lang.String)
096         */
097        public void setupAttributeValue(ResultSet resultSet, String columnName) throws SQLException {
098                this.setSearchableAttributeValue(resultSet.getString(columnName));
099        }
100
101        /* (non-Javadoc)
102         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getSearchableAttributeDisplayValue()
103         */
104    public String getSearchableAttributeDisplayValue() {
105        return getSearchableAttributeValue();
106    }
107
108        /* (non-Javadoc)
109         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeDataType()
110         */
111        public String getAttributeDataType() {
112                return ATTRIBUTE_XML_REPRESENTATION;
113        }
114
115        /* (non-Javadoc)
116         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#getAttributeTableName()
117         */
118        public String getAttributeTableName() {
119                return ATTRIBUTE_DATABASE_TABLE_NAME;
120        }
121
122    /* (non-Javadoc)
123         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsWildcardsByDefault()
124         */
125        public boolean allowsWildcards() {
126                return DEFAULT_WILDCARD_ALLOWANCE_POLICY;
127        }
128
129    /* (non-Javadoc)
130         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsCaseInsensitivity()
131         */
132        public boolean allowsCaseInsensitivity() {
133                return ALLOWS_CASE_INSENSITIVE_SEARCH;
134        }
135
136    /* (non-Javadoc)
137         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#allowsRangeSearches()
138         */
139        public boolean allowsRangeSearches() {
140                return ALLOWS_RANGE_SEARCH;
141        }
142
143        /**
144         * @return true if the {@code valueEntered} parameter is not null and is equal to or
145         * less than the specified max length defined by {@link #STRING_MAX_LENGTH}
146         *
147         * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isPassesDefaultValidation()
148         */
149        public boolean isPassesDefaultValidation(String valueEntered) {
150            if (valueEntered != null && (valueEntered.length() > STRING_MAX_LENGTH)) {
151                return false;
152            }
153                return true;
154        }
155
156    /* (non-Javadoc)
157     * @see org.kuali.rice.kew.docsearch.SearchableAttributeValue#isRangeValid(java.lang.String, java.lang.String)
158     */
159    public Boolean isRangeValid(String lowerValue, String upperValue) {
160        return isRangeValid(lowerValue, upperValue, true);
161    }
162
163    /* (non-Javadoc)
164     * @see org.kuali.rice.kew.docsearch.CaseAwareSearchableAttributeValue#isRangeValid(java.lang.String, java.lang.String, boolean)
165     */
166    public Boolean isRangeValid(String lowerValue, String upperValue, boolean caseSensitive) {
167        if (allowsRangeSearches()) {
168            return StringUtils.isBlank(lowerValue) ||
169                   StringUtils.isBlank(upperValue) ||
170                   (caseSensitive ?
171                     ObjectUtils.compare(lowerValue, upperValue) <= 0 :
172                     String.CASE_INSENSITIVE_ORDER.compare(lowerValue, upperValue) <= 0);
173        }
174        return null;
175    }
176
177        public String getOjbConcreteClass() {
178                return ojbConcreteClass;
179        }
180
181        public void setOjbConcreteClass(String ojbConcreteClass) {
182                this.ojbConcreteClass = ojbConcreteClass;
183        }
184
185        public DocumentRouteHeaderValue getRouteHeader() {
186                return routeHeader;
187        }
188
189        public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
190                this.routeHeader = routeHeader;
191        }
192
193        public String getDocumentId() {
194                return documentId;
195        }
196
197        public void setDocumentId(String documentId) {
198                this.documentId = documentId;
199        }
200
201        public String getSearchableAttributeKey() {
202                return searchableAttributeKey;
203        }
204
205        public void setSearchableAttributeKey(String searchableAttributeKey) {
206                this.searchableAttributeKey = searchableAttributeKey;
207        }
208
209        public String getSearchableAttributeValue() {
210                return searchableAttributeValue;
211        }
212
213        public void setSearchableAttributeValue(String searchableAttributeValue) {
214                this.searchableAttributeValue = searchableAttributeValue;
215        }
216
217        public String getSearchableAttributeValueId() {
218                return searchableAttributeValueId;
219        }
220
221        public void setSearchableAttributeValueId(String searchableAttributeValueId) {
222                this.searchableAttributeValueId = searchableAttributeValueId;
223        }
224
225        //@PrePersist
226        public void beforeInsert(){
227                OrmUtils.populateAutoIncValue(this, KEWServiceLocator.getEntityManagerFactory().createEntityManager());
228        }
229
230    @Override
231    public DocumentAttributeString toDocumentAttribute() {
232        return DocumentAttributeFactory.createStringAttribute(getSearchableAttributeKey(), getSearchableAttributeValue());
233    }
234
235    @Override
236    public int hashCode() {
237        final int prime = 31;
238        int result = 1;
239        result = prime * result + ((this.documentId == null) ? 0 : this.documentId.hashCode());
240        result = prime * result + ((this.searchableAttributeKey == null) ? 0 : this.searchableAttributeKey.hashCode());
241        result = prime * result
242                + ((this.searchableAttributeValue == null) ? 0 : this.searchableAttributeValue.hashCode());
243        return result;
244    }
245
246    @Override
247    public boolean equals(Object obj) {
248        if (this == obj)
249            return true;
250        if (obj == null)
251            return false;
252        if (getClass() != obj.getClass())
253            return false;
254        SearchableAttributeStringValue other = (SearchableAttributeStringValue) obj;
255        if (this.documentId == null) {
256            if (other.documentId != null)
257                return false;
258        } else if (!this.documentId.equals(other.documentId))
259            return false;
260        if (this.searchableAttributeKey == null) {
261            if (other.searchableAttributeKey != null)
262                return false;
263        } else if (!this.searchableAttributeKey.equals(other.searchableAttributeKey))
264            return false;
265        if (this.searchableAttributeValue == null) {
266            if (other.searchableAttributeValue != null)
267                return false;
268        } else if (!this.searchableAttributeValue.equals(other.searchableAttributeValue))
269            return false;
270        return true;
271    }
272}
273