|  1 |     | 
     | 
  |  2 |     | 
     | 
  |  3 |     | 
     | 
  |  4 |     | 
     | 
  |  5 |     | 
     | 
  |  6 |     | 
     | 
  |  7 |     | 
     | 
  |  8 |     | 
     | 
  |  9 |     | 
     | 
  |  10 |     | 
     | 
  |  11 |     | 
     | 
  |  12 |     | 
     | 
  |  13 |     | 
     | 
  |  14 |     | 
     | 
  |  15 |     | 
     | 
  |  16 |     | 
   package org.kuali.rice.kew.impl.document.search;  | 
  |  17 |     | 
     | 
  |  18 |     | 
   import org.apache.commons.collections.CollectionUtils;  | 
  |  19 |     | 
   import org.apache.commons.lang.StringUtils;  | 
  |  20 |     | 
   import org.joda.time.DateTime;  | 
  |  21 |     | 
   import org.kuali.rice.core.api.CoreApiServiceLocator;  | 
  |  22 |     | 
   import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;  | 
  |  23 |     | 
   import org.kuali.rice.core.api.uif.RemotableAttributeError;  | 
  |  24 |     | 
   import org.kuali.rice.core.api.uif.RemotableAttributeField;  | 
  |  25 |     | 
   import org.kuali.rice.core.api.util.RiceConstants;  | 
  |  26 |     | 
   import org.kuali.rice.core.framework.persistence.jdbc.sql.Criteria;  | 
  |  27 |     | 
   import org.kuali.rice.core.framework.persistence.jdbc.sql.SqlBuilder;  | 
  |  28 |     | 
   import org.kuali.rice.core.framework.persistence.platform.DatabasePlatform;  | 
  |  29 |     | 
   import org.kuali.rice.kew.api.KewApiServiceLocator;  | 
  |  30 |     | 
   import org.kuali.rice.kew.api.document.Document;  | 
  |  31 |     | 
   import org.kuali.rice.kew.api.document.DocumentStatus;  | 
  |  32 |     | 
   import org.kuali.rice.kew.api.document.DocumentStatusCategory;  | 
  |  33 |     | 
   import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;  | 
  |  34 |     | 
   import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;  | 
  |  35 |     | 
   import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;  | 
  |  36 |     | 
   import org.kuali.rice.kew.api.document.search.DocumentSearchResult;  | 
  |  37 |     | 
   import org.kuali.rice.kew.api.document.search.DocumentSearchResults;  | 
  |  38 |     | 
   import org.kuali.rice.kew.api.document.search.RouteNodeLookupLogic;  | 
  |  39 |     | 
   import org.kuali.rice.kew.docsearch.DocumentSearchInternalUtils;  | 
  |  40 |     | 
   import org.kuali.rice.kew.docsearch.QueryComponent;  | 
  |  41 |     | 
   import org.kuali.rice.kew.docsearch.SearchableAttributeValue;  | 
  |  42 |     | 
   import org.kuali.rice.kew.doctype.bo.DocumentType;  | 
  |  43 |     | 
   import org.kuali.rice.kew.doctype.service.DocumentTypeService;  | 
  |  44 |     | 
   import org.kuali.rice.kew.engine.node.RouteNode;  | 
  |  45 |     | 
   import org.kuali.rice.kew.service.KEWServiceLocator;  | 
  |  46 |     | 
   import org.kuali.rice.kew.api.KewApiConstants;  | 
  |  47 |     | 
   import org.kuali.rice.kew.util.PerformanceLogger;  | 
  |  48 |     | 
   import org.kuali.rice.kim.api.identity.Person;  | 
  |  49 |     | 
   import org.kuali.rice.kim.api.services.KimApiServiceLocator;  | 
  |  50 |     | 
   import org.kuali.rice.krad.util.MessageMap;  | 
  |  51 |     | 
     | 
  |  52 |     | 
   import java.sql.ResultSet;  | 
  |  53 |     | 
   import java.sql.SQLException;  | 
  |  54 |     | 
   import java.sql.Statement;  | 
  |  55 |     | 
   import java.sql.Timestamp;  | 
  |  56 |     | 
   import java.util.ArrayList;  | 
  |  57 |     | 
   import java.util.Collection;  | 
  |  58 |     | 
   import java.util.Collections;  | 
  |  59 |     | 
   import java.util.HashMap;  | 
  |  60 |     | 
   import java.util.HashSet;  | 
  |  61 |     | 
   import java.util.List;  | 
  |  62 |     | 
   import java.util.Map;  | 
  |  63 |     | 
   import java.util.Set;  | 
  |  64 |     | 
   import java.util.TreeSet;  | 
  |  65 |     | 
     | 
  |  66 |     | 
     | 
  |  67 |     | 
     | 
  |  68 |     | 
     | 
  |  69 |     | 
     | 
  |  70 |     | 
     | 
  |  71 |     | 
     | 
  |  72 |    0 |    public class DocumentSearchGeneratorImpl implements DocumentSearchGenerator { | 
  |  73 |     | 
     | 
  |  74 |    0 |        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentSearchGeneratorImpl.class);  | 
  |  75 |     | 
     | 
  |  76 |     | 
       private static final String ROUTE_NODE_TABLE = "KREW_RTE_NODE_T";  | 
  |  77 |     | 
       private static final String ROUTE_NODE_INST_TABLE = "KREW_RTE_NODE_INSTN_T";  | 
  |  78 |     | 
       private static final String DATABASE_WILDCARD_CHARACTER_STRING = "%";  | 
  |  79 |    0 |        private static final char DATABASE_WILDCARD_CHARACTER = DATABASE_WILDCARD_CHARACTER_STRING.toCharArray()[0];  | 
  |  80 |     | 
     | 
  |  81 |     | 
       private DatabasePlatform dbPlatform;  | 
  |  82 |     | 
       private MessageMap messageMap;  | 
  |  83 |     | 
     | 
  |  84 |    0 |        private SqlBuilder sqlBuilder = null;  | 
  |  85 |     | 
     | 
  |  86 |     | 
       @Override  | 
  |  87 |     | 
       public DocumentSearchCriteria clearSearch(DocumentSearchCriteria criteria) { | 
  |  88 |    0 |            return DocumentSearchCriteria.Builder.create().build();  | 
  |  89 |     | 
       }  | 
  |  90 |     | 
     | 
  |  91 |     | 
       public DocumentType getValidDocumentType(String documentTypeFullName) { | 
  |  92 |    0 |            if (!org.apache.commons.lang.StringUtils.isEmpty(documentTypeFullName)) { | 
  |  93 |    0 |                DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeFullName);  | 
  |  94 |    0 |                if (documentType == null) { | 
  |  95 |    0 |                    throw new RuntimeException("No Valid Document Type Found for document type name '" + documentTypeFullName + "'"); | 
  |  96 |     | 
               }  | 
  |  97 |    0 |                return documentType;  | 
  |  98 |     | 
           }  | 
  |  99 |    0 |            return null;  | 
  |  100 |     | 
       }  | 
  |  101 |     | 
     | 
  |  102 |     | 
       @Override  | 
  |  103 |     | 
       public List<RemotableAttributeError> validateSearchableAttributes(DocumentSearchCriteria.Builder criteria) { | 
  |  104 |    0 |            List<RemotableAttributeError> errors = new ArrayList<RemotableAttributeError>();  | 
  |  105 |    0 |            DocumentType documentType = getValidDocumentType(criteria.getDocumentTypeName());  | 
  |  106 |    0 |            if (documentType != null) { | 
  |  107 |    0 |                errors = KEWServiceLocator.getDocumentSearchCustomizationMediator().validateLookupFieldParameters(documentType, criteria.build());  | 
  |  108 |     | 
           }  | 
  |  109 |    0 |            return errors == null ? Collections.<RemotableAttributeError>emptyList() : Collections.unmodifiableList(errors);  | 
  |  110 |     | 
       }  | 
  |  111 |     | 
     | 
  |  112 |     | 
       public QueryComponent getSearchableAttributeSql(Map<String, List<String>> documentAttributeValues, List<RemotableAttributeField> searchFields, String whereClausePredicatePrefix) { | 
  |  113 |     | 
     | 
  |  114 |    0 |            StringBuilder fromSql = new StringBuilder();  | 
  |  115 |    0 |            StringBuilder whereSql = new StringBuilder();  | 
  |  116 |     | 
     | 
  |  117 |     | 
             | 
  |  118 |    0 |            Criteria finalCriteria = null;  | 
  |  119 |    0 |            int tableIndex = 1;  | 
  |  120 |    0 |            SqlBuilder sqlBuilder = this.getSqlBuilder();  | 
  |  121 |     | 
     | 
  |  122 |    0 |            for (String documentAttributeName : documentAttributeValues.keySet()) { | 
  |  123 |     | 
     | 
  |  124 |    0 |                List<String> searchValues = documentAttributeValues.get(documentAttributeName);  | 
  |  125 |    0 |                if (CollectionUtils.isEmpty(searchValues)) { | 
  |  126 |    0 |                    continue;  | 
  |  127 |     | 
               }  | 
  |  128 |     | 
     | 
  |  129 |    0 |                String tableAlias = "EXT" + tableIndex;  | 
  |  130 |    0 |                RemotableAttributeField searchField = getSearchFieldByName(documentAttributeName, searchFields);  | 
  |  131 |    0 |                String tableName = DocumentSearchInternalUtils.getAttributeTableName(searchField);  | 
  |  132 |    0 |                boolean caseSensitive = DocumentSearchInternalUtils.isLookupCaseSensitive(searchField);  | 
  |  133 |     | 
     | 
  |  134 |    0 |                Criteria crit = null;  | 
  |  135 |     | 
     | 
  |  136 |    0 |                Class<?> dataTypeClass = DocumentSearchInternalUtils.getDataTypeClass(searchField);  | 
  |  137 |    0 |                if (searchValues.size() > 1) { | 
  |  138 |     | 
                     | 
  |  139 |    0 |                    crit = new Criteria(tableName, tableAlias);  | 
  |  140 |    0 |                    crit.setDbPlatform(sqlBuilder.getDbPlatform());  | 
  |  141 |    0 |                    crit.in("VAL", searchValues, dataTypeClass); | 
  |  142 |     | 
               } else { | 
  |  143 |    0 |                    crit = sqlBuilder.createCriteria("VAL", searchValues.get(0) , tableName, tableAlias, dataTypeClass, !caseSensitive); | 
  |  144 |     | 
               }  | 
  |  145 |    0 |                sqlBuilder.addCriteria("KEY_CD", documentAttributeName, String.class, false, false, crit);  | 
  |  146 |    0 |                sqlBuilder.andCriteria("DOC_HDR_ID", tableAlias + ".DOC_HDR_ID", "KREW_DOC_HDR_T", "DOC_HDR", SqlBuilder.JoinType.class, false, false, crit); | 
  |  147 |     | 
     | 
  |  148 |    0 |                if (finalCriteria == null ){ | 
  |  149 |    0 |                    finalCriteria = crit;  | 
  |  150 |     | 
               } else{ | 
  |  151 |    0 |                    sqlBuilder.andCriteria(finalCriteria, crit);  | 
  |  152 |     | 
               }  | 
  |  153 |     | 
     | 
  |  154 |     | 
                 | 
  |  155 |     | 
                 | 
  |  156 |    0 |                String whereClausePrefix = (whereSql.length() == 0) ? whereClausePredicatePrefix : getGeneratedPredicatePrefix(whereSql.length());  | 
  |  157 |    0 |                QueryComponent qc = generateSearchableAttributeSql(tableName, documentAttributeName, whereClausePrefix, tableIndex);  | 
  |  158 |    0 |                fromSql.append(qc.getFromSql());  | 
  |  159 |    0 |                tableIndex++;  | 
  |  160 |    0 |            }  | 
  |  161 |     | 
     | 
  |  162 |    0 |            if (finalCriteria == null) { | 
  |  163 |    0 |                return new QueryComponent("", "", ""); | 
  |  164 |     | 
           }  | 
  |  165 |     | 
     | 
  |  166 |    0 |            String whereClausePrefix = (whereSql.length() == 0) ? whereClausePredicatePrefix : getGeneratedPredicatePrefix(whereSql.length());  | 
  |  167 |     | 
     | 
  |  168 |    0 |            return new QueryComponent("", fromSql.toString(), whereClausePrefix + " " + finalCriteria.buildWhere()); | 
  |  169 |     | 
       }  | 
  |  170 |     | 
     | 
  |  171 |     | 
       private RemotableAttributeField getSearchFieldByName(String fieldName, List<RemotableAttributeField> searchFields) { | 
  |  172 |    0 |            for (RemotableAttributeField searchField : searchFields) { | 
  |  173 |    0 |                if (searchField.getName().equals(fieldName)) { | 
  |  174 |    0 |                    return searchField;  | 
  |  175 |     | 
               }  | 
  |  176 |     | 
           }  | 
  |  177 |    0 |            throw new IllegalStateException("Failed to locate a RemotableAttributeField for fieldName=" + fieldName); | 
  |  178 |     | 
       }  | 
  |  179 |     | 
     | 
  |  180 |     | 
       public QueryComponent generateSearchableAttributeSql(String tableName, String documentAttributeName, String whereSqlStarter,int tableIndex) { | 
  |  181 |    0 |            String tableIdentifier = "EXT" + tableIndex;  | 
  |  182 |    0 |            QueryComponent joinSqlComponent = getSearchableAttributeJoinSql(tableName, tableIdentifier, whereSqlStarter, documentAttributeName);  | 
  |  183 |    0 |            return new QueryComponent("", joinSqlComponent.getFromSql(), joinSqlComponent.getWhereSql()); | 
  |  184 |     | 
       }  | 
  |  185 |     | 
     | 
  |  186 |     | 
       public QueryComponent getSearchableAttributeJoinSql(String tableName, String tableIdentifier, String whereSqlStarter, String attributeTableKeyColumnName) { | 
  |  187 |    0 |            return new QueryComponent("", generateSearchableAttributeFromSql(tableName, tableIdentifier).toString(), generateSearchableAttributeWhereClauseJoin(whereSqlStarter, tableIdentifier, attributeTableKeyColumnName).toString()); | 
  |  188 |     | 
       }  | 
  |  189 |     | 
     | 
  |  190 |     | 
       public StringBuilder generateSearchableAttributeWhereClauseJoin(String whereSqlStarter,String tableIdentifier,String attributeTableKeyColumnName) { | 
  |  191 |    0 |            StringBuilder whereSql = new StringBuilder(constructWhereClauseElement(whereSqlStarter, "DOC_HDR.DOC_HDR_ID", "=", getDbPlatform().escapeString(tableIdentifier + ".DOC_HDR_ID"), null, null));  | 
  |  192 |    0 |            whereSql.append(constructWhereClauseElement(" and ", tableIdentifier + ".KEY_CD", "=", | 
  |  193 |     | 
                   getDbPlatform().escapeString(attributeTableKeyColumnName), "'", "'"));  | 
  |  194 |    0 |            return whereSql;  | 
  |  195 |     | 
       }  | 
  |  196 |     | 
     | 
  |  197 |     | 
       public StringBuilder generateSearchableAttributeFromSql(String tableName, String tableIdentifier) { | 
  |  198 |    0 |            if (StringUtils.isBlank(tableName)) { | 
  |  199 |    0 |                throw new IllegalArgumentException("tableName was null or blank"); | 
  |  200 |     | 
           }  | 
  |  201 |    0 |            if (StringUtils.isBlank(tableIdentifier)) { | 
  |  202 |    0 |                throw new IllegalArgumentException("tableIdentifier was null or blank"); | 
  |  203 |     | 
           }  | 
  |  204 |    0 |            StringBuilder fromSql = new StringBuilder();  | 
  |  205 |    0 |            fromSql.append(" ,").append(tableName).append(" ").append(getDbPlatform().escapeString(tableIdentifier)).append(" "); | 
  |  206 |    0 |            return fromSql;  | 
  |  207 |     | 
       }  | 
  |  208 |     | 
     | 
  |  209 |     | 
       public StringBuilder constructWhereClauseElement(String clauseStarter,String queryTableColumnName,String operand,String valueToSearch,String valuePrefix,String valueSuffix) { | 
  |  210 |    0 |            StringBuilder whereSql = new StringBuilder();  | 
  |  211 |    0 |            valuePrefix = (valuePrefix != null) ? valuePrefix : "";  | 
  |  212 |    0 |            valueSuffix = (valueSuffix != null) ? valueSuffix : "";  | 
  |  213 |    0 |            whereSql.append(" " + clauseStarter + " ").append(getDbPlatform().escapeString(queryTableColumnName)).append(" " + operand + " ").append(valuePrefix).append(valueToSearch).append(valueSuffix).append(" "); | 
  |  214 |    0 |            return whereSql;  | 
  |  215 |     | 
       }  | 
  |  216 |     | 
     | 
  |  217 |     | 
       @Override  | 
  |  218 |     | 
       public DocumentSearchResults.Builder processResultSet(DocumentSearchCriteria criteria, boolean criteriaModified, Statement searchAttributeStatement, ResultSet resultSet, int maxResultCap, int fetchLimit) throws SQLException { | 
  |  219 |    0 |            DocumentSearchCriteria.Builder criteriaBuilder = DocumentSearchCriteria.Builder.create(criteria);  | 
  |  220 |    0 |            DocumentSearchResults.Builder results = DocumentSearchResults.Builder.create(criteriaBuilder);  | 
  |  221 |    0 |            results.setCriteriaModified(criteriaModified);  | 
  |  222 |    0 |            int size = 0;  | 
  |  223 |    0 |            List<DocumentSearchResult.Builder> resultList = new ArrayList<DocumentSearchResult.Builder>();  | 
  |  224 |    0 |            results.setSearchResults(resultList);  | 
  |  225 |    0 |            Map<String, DocumentSearchResult.Builder> resultMap = new HashMap<String, DocumentSearchResult.Builder>();  | 
  |  226 |    0 |            PerformanceLogger perfLog = new PerformanceLogger();  | 
  |  227 |    0 |            int iteration = 0;  | 
  |  228 |    0 |            boolean resultSetHasNext = resultSet.next();  | 
  |  229 |    0 |            while ( resultSetHasNext && resultMap.size() < maxResultCap && iteration++ < fetchLimit) { | 
  |  230 |    0 |                DocumentSearchResult.Builder resultBuilder = processRow(criteria, searchAttributeStatement, resultSet);  | 
  |  231 |    0 |                String documentId = resultBuilder.getDocument().getDocumentId();  | 
  |  232 |    0 |                if (!resultMap.containsKey(documentId)) { | 
  |  233 |    0 |                    resultList.add(resultBuilder);  | 
  |  234 |    0 |                    resultMap.put(documentId, resultBuilder);  | 
  |  235 |    0 |                    size++;  | 
  |  236 |     | 
               } else { | 
  |  237 |     | 
                     | 
  |  238 |    0 |                    DocumentSearchResult.Builder previousEntry = resultMap.get(documentId);  | 
  |  239 |    0 |                    handleMultipleDocumentRows(previousEntry, resultBuilder);  | 
  |  240 |     | 
               }  | 
  |  241 |    0 |                resultSetHasNext = resultSet.next();  | 
  |  242 |    0 |            }  | 
  |  243 |     | 
             | 
  |  244 |    0 |            perfLog.log("Time to read doc search results.", true); | 
  |  245 |     | 
             | 
  |  246 |    0 |            results.setOverThreshold(resultSetHasNext);  | 
  |  247 |     | 
     | 
  |  248 |    0 |            LOG.debug("Processed "+size+" document search result rows."); | 
  |  249 |    0 |            return results;  | 
  |  250 |     | 
       }  | 
  |  251 |     | 
     | 
  |  252 |     | 
         | 
  |  253 |     | 
     | 
  |  254 |     | 
     | 
  |  255 |     | 
     | 
  |  256 |     | 
     | 
  |  257 |     | 
     | 
  |  258 |     | 
     | 
  |  259 |     | 
       private void handleMultipleDocumentRows(DocumentSearchResult.Builder existingRow, DocumentSearchResult.Builder newRow) { | 
  |  260 |    0 |            for (DocumentAttribute.AbstractBuilder<?> newDocumentAttribute : newRow.getDocumentAttributes()) { | 
  |  261 |    0 |                existingRow.getDocumentAttributes().add(newDocumentAttribute);  | 
  |  262 |     | 
           }  | 
  |  263 |    0 |        }  | 
  |  264 |     | 
     | 
  |  265 |     | 
       protected DocumentSearchResult.Builder processRow(DocumentSearchCriteria criteria, Statement searchAttributeStatement, ResultSet rs) throws SQLException { | 
  |  266 |     | 
     | 
  |  267 |    0 |            String documentId = rs.getString("DOC_HDR_ID"); | 
  |  268 |    0 |            String initiatorPrincipalId = rs.getString("INITR_PRNCPL_ID"); | 
  |  269 |    0 |            String documentTypeName = rs.getString("DOC_TYP_NM"); | 
  |  270 |    0 |            org.kuali.rice.kew.api.doctype.DocumentType documentType =  | 
  |  271 |     | 
                   KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(documentTypeName);  | 
  |  272 |    0 |            if (documentType == null) { | 
  |  273 |    0 |                throw new IllegalStateException("Failed to locate a document type with the given name: " + documentTypeName); | 
  |  274 |     | 
           }  | 
  |  275 |    0 |            String documentTypeId = documentType.getId();  | 
  |  276 |     | 
     | 
  |  277 |    0 |            Document.Builder documentBuilder = Document.Builder.create(documentId, initiatorPrincipalId, documentTypeName, documentTypeId);  | 
  |  278 |    0 |            DocumentSearchResult.Builder resultBuilder = DocumentSearchResult.Builder.create(documentBuilder);  | 
  |  279 |     | 
     | 
  |  280 |    0 |            String statusCode = rs.getString("DOC_HDR_STAT_CD"); | 
  |  281 |    0 |            Timestamp createTimestamp = rs.getTimestamp("CRTE_DT"); | 
  |  282 |    0 |            String title = rs.getString("TTL"); | 
  |  283 |    0 |            String applicationDocumentStatus = rs.getString("APP_DOC_STAT"); | 
  |  284 |     | 
     | 
  |  285 |    0 |            documentBuilder.setStatus(DocumentStatus.fromCode(statusCode));  | 
  |  286 |    0 |            documentBuilder.setDateCreated(new DateTime(createTimestamp.getTime()));  | 
  |  287 |    0 |            documentBuilder.setTitle(title);  | 
  |  288 |    0 |            documentBuilder.setApplicationDocumentStatus(applicationDocumentStatus);  | 
  |  289 |     | 
     | 
  |  290 |     | 
             | 
  |  291 |     | 
     | 
  |  292 |    0 |            if (isUsingAtLeastOneSearchAttribute(criteria)) { | 
  |  293 |    0 |                populateDocumentAttributesValues(resultBuilder, searchAttributeStatement);  | 
  |  294 |     | 
           }  | 
  |  295 |     | 
     | 
  |  296 |    0 |            return resultBuilder;  | 
  |  297 |     | 
       }  | 
  |  298 |     | 
     | 
  |  299 |     | 
         | 
  |  300 |     | 
     | 
  |  301 |     | 
     | 
  |  302 |     | 
     | 
  |  303 |     | 
     | 
  |  304 |     | 
     | 
  |  305 |     | 
     | 
  |  306 |     | 
     | 
  |  307 |     | 
       public void populateDocumentAttributesValues(DocumentSearchResult.Builder resultBuilder, Statement searchAttributeStatement) throws SQLException { | 
  |  308 |    0 |            searchAttributeStatement.setFetchSize(50);  | 
  |  309 |    0 |            String documentId = resultBuilder.getDocument().getDocumentId();  | 
  |  310 |    0 |            List<SearchableAttributeValue> attributeValues = DocumentSearchInternalUtils  | 
  |  311 |     | 
                   .getSearchableAttributeValueObjectTypes();  | 
  |  312 |    0 |            PerformanceLogger perfLog = new PerformanceLogger(documentId);  | 
  |  313 |    0 |            for (SearchableAttributeValue searchAttValue : attributeValues) { | 
  |  314 |    0 |                String attributeSql = "select KEY_CD, VAL from " + searchAttValue.getAttributeTableName() + " where DOC_HDR_ID = '" + documentId + "'";  | 
  |  315 |    0 |                ResultSet attributeResultSet = null;  | 
  |  316 |     | 
               try { | 
  |  317 |    0 |                    attributeResultSet = searchAttributeStatement.executeQuery(attributeSql);  | 
  |  318 |    0 |                    while (attributeResultSet.next()) { | 
  |  319 |    0 |                        searchAttValue.setSearchableAttributeKey(attributeResultSet.getString("KEY_CD")); | 
  |  320 |    0 |                        searchAttValue.setupAttributeValue(attributeResultSet, "VAL");  | 
  |  321 |    0 |                        if ( (!org.apache.commons.lang.StringUtils.isEmpty(searchAttValue.getSearchableAttributeKey())) && (searchAttValue.getSearchableAttributeValue() != null) ) { | 
  |  322 |    0 |                            DocumentAttribute documentAttribute = searchAttValue.toDocumentAttribute();  | 
  |  323 |    0 |                            resultBuilder.getDocumentAttributes().add(DocumentAttributeFactory.loadContractIntoBuilder(  | 
  |  324 |     | 
                                   documentAttribute));  | 
  |  325 |    0 |                        }  | 
  |  326 |     | 
                   }  | 
  |  327 |     | 
               } finally { | 
  |  328 |    0 |                    if (attributeResultSet != null) { | 
  |  329 |     | 
                       try { | 
  |  330 |    0 |                            attributeResultSet.close();  | 
  |  331 |    0 |                        } catch (Exception e) { | 
  |  332 |    0 |                            LOG.warn("Could not close searchable attribute result set for class " + searchAttValue.getClass().getName(),e); | 
  |  333 |    0 |                        }  | 
  |  334 |     | 
                   }  | 
  |  335 |     | 
               }  | 
  |  336 |    0 |            }  | 
  |  337 |    0 |            perfLog.log("Time to execute doc search search attribute queries.", true); | 
  |  338 |    0 |        }  | 
  |  339 |     | 
     | 
  |  340 |     | 
       public String generateSearchSql(DocumentSearchCriteria criteria, List<RemotableAttributeField> searchFields) { | 
  |  341 |     | 
     | 
  |  342 |    0 |            String docTypeTableAlias   = "DOC1";  | 
  |  343 |    0 |            String docHeaderTableAlias = "DOC_HDR";  | 
  |  344 |     | 
     | 
  |  345 |    0 |            String sqlPrefix = "Select * from ("; | 
  |  346 |    0 |            String sqlSuffix = ") FINAL_SEARCH order by FINAL_SEARCH.CRTE_DT desc";  | 
  |  347 |     | 
             | 
  |  348 |    0 |            StringBuilder selectSQL = new StringBuilder("select DISTINCT("+ docHeaderTableAlias +".DOC_HDR_ID), "+ docHeaderTableAlias +".INITR_PRNCPL_ID, " | 
  |  349 |     | 
                   + docHeaderTableAlias +".DOC_HDR_STAT_CD, "+ docHeaderTableAlias +".CRTE_DT, "+ docHeaderTableAlias +".TTL, "+ docHeaderTableAlias +".APP_DOC_STAT, "+ docTypeTableAlias +".DOC_TYP_NM, "  | 
  |  350 |     | 
                   + docTypeTableAlias +".LBL, "+ docTypeTableAlias +".DOC_HDLR_URL, "+ docTypeTableAlias +".ACTV_IND");  | 
  |  351 |    0 |            StringBuilder fromSQL = new StringBuilder(" from KREW_DOC_TYP_T "+ docTypeTableAlias +" "); | 
  |  352 |    0 |            StringBuilder fromSQLForDocHeaderTable = new StringBuilder(", KREW_DOC_HDR_T " + docHeaderTableAlias + " "); | 
  |  353 |     | 
     | 
  |  354 |    0 |            StringBuilder whereSQL = new StringBuilder();  | 
  |  355 |    0 |            whereSQL.append(getDocumentIdSql(criteria.getDocumentId(), getGeneratedPredicatePrefix(whereSQL.length()), docHeaderTableAlias));  | 
  |  356 |    0 |            whereSQL.append(getInitiatorSql(criteria.getInitiatorPrincipalName(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  357 |    0 |            whereSQL.append(getAppDocIdSql(criteria.getApplicationDocumentId(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  358 |    0 |            whereSQL.append(getDateCreatedSql(criteria.getDateCreatedFrom(), criteria.getDateCreatedTo(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  359 |    0 |            whereSQL.append(getDateLastModifiedSql(criteria.getDateLastModifiedFrom(), criteria.getDateLastModifiedTo(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  360 |    0 |            whereSQL.append(getDateApprovedSql(criteria.getDateApprovedFrom(), criteria.getDateApprovedTo(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  361 |    0 |            whereSQL.append(getDateFinalizedSql(criteria.getDateFinalizedFrom(), criteria.getDateFinalizedTo(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  362 |     | 
     | 
  |  363 |     | 
             | 
  |  364 |    0 |            String principalViewerSql = getViewerSql(criteria.getViewerPrincipalName(), getGeneratedPredicatePrefix(whereSQL.length()));  | 
  |  365 |    0 |            String groupViewerSql = getGroupViewerSql(criteria.getViewerGroupId(), getGeneratedPredicatePrefix(whereSQL.length()));  | 
  |  366 |    0 |            if (StringUtils.isNotBlank(principalViewerSql) || StringUtils.isNotBlank(groupViewerSql)) { | 
  |  367 |    0 |                whereSQL.append(principalViewerSql);  | 
  |  368 |    0 |                whereSQL.append(groupViewerSql);  | 
  |  369 |    0 |                fromSQL.append(", KREW_ACTN_RQST_T "); | 
  |  370 |     | 
           }  | 
  |  371 |     | 
     | 
  |  372 |    0 |            if (!("".equals(getApproverSql(criteria.getApproverPrincipalName(), getGeneratedPredicatePrefix(whereSQL.length()))))) { | 
  |  373 |    0 |                whereSQL.append(getApproverSql(criteria.getApproverPrincipalName(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  374 |    0 |                fromSQL.append(", KREW_ACTN_TKN_T "); | 
  |  375 |     | 
           }  | 
  |  376 |     | 
     | 
  |  377 |     | 
     | 
  |  378 |     | 
     | 
  |  379 |    0 |            String docRouteNodeSql = getDocRouteNodeSql(criteria.getDocumentTypeName(), criteria.getRouteNodeName(), criteria.getRouteNodeLookupLogic(), getGeneratedPredicatePrefix(whereSQL.length()));  | 
  |  380 |    0 |            if (StringUtils.isNotBlank(docRouteNodeSql)) { | 
  |  381 |    0 |                whereSQL.append(docRouteNodeSql);  | 
  |  382 |    0 |                fromSQL.append(", KREW_RTE_NODE_INSTN_T "); | 
  |  383 |    0 |                fromSQL.append(", KREW_RTE_NODE_T "); | 
  |  384 |     | 
           }  | 
  |  385 |     | 
     | 
  |  386 |    0 |            if (!criteria.getDocumentAttributeValues().isEmpty()) { | 
  |  387 |    0 |                QueryComponent queryComponent = getSearchableAttributeSql(criteria.getDocumentAttributeValues(), searchFields, getGeneratedPredicatePrefix(  | 
  |  388 |     | 
                       whereSQL.length()));  | 
  |  389 |    0 |                selectSQL.append(queryComponent.getSelectSql());  | 
  |  390 |    0 |                fromSQL.append(queryComponent.getFromSql());  | 
  |  391 |    0 |                whereSQL.append(queryComponent.getWhereSql());  | 
  |  392 |     | 
           }  | 
  |  393 |     | 
     | 
  |  394 |    0 |            whereSQL.append(getDocTypeFullNameWhereSql(criteria, getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  395 |    0 |            whereSQL.append(getDocTitleSql(criteria.getTitle(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  396 |    0 |            whereSQL.append(getDocumentStatusSql(criteria.getDocumentStatuses(), criteria.getDocumentStatusCategories(), getGeneratedPredicatePrefix(whereSQL.length())));  | 
  |  397 |    0 |            whereSQL.append(getGeneratedPredicatePrefix(whereSQL.length())).append(" DOC_HDR.DOC_TYP_ID = DOC1.DOC_TYP_ID "); | 
  |  398 |    0 |            fromSQL.append(fromSQLForDocHeaderTable);  | 
  |  399 |     | 
     | 
  |  400 |     | 
             | 
  |  401 |    0 |            String statusTransitionWhereClause = getStatusTransitionDateSql(criteria.getDateApplicationDocumentStatusChangedFrom(), criteria.getDateApplicationDocumentStatusChangedTo(), getGeneratedPredicatePrefix(whereSQL.length()));  | 
  |  402 |    0 |            whereSQL.append(getAppDocStatusSql(criteria.getApplicationDocumentStatus(), getGeneratedPredicatePrefix(whereSQL.length()), statusTransitionWhereClause.length() ));  | 
  |  403 |    0 |            if (statusTransitionWhereClause.length() > 0){ | 
  |  404 |    0 |                    whereSQL.append(statusTransitionWhereClause);  | 
  |  405 |    0 |                whereSQL.append(getGeneratedPredicatePrefix(whereSQL.length())).append(" DOC_HDR.DOC_HDR_ID = STAT_TRAN.DOC_HDR_ID "); | 
  |  406 |    0 |                    fromSQL.append(", KREW_APP_DOC_STAT_TRAN_T STAT_TRAN "); | 
  |  407 |     | 
           }  | 
  |  408 |     | 
     | 
  |  409 |    0 |            String finalizedSql = sqlPrefix + " " + selectSQL.toString() + " " + fromSQL.toString() + " " + whereSQL.toString() + " " + sqlSuffix;  | 
  |  410 |     | 
     | 
  |  411 |    0 |            LOG.info("*********** SEARCH SQL ***************"); | 
  |  412 |    0 |            LOG.info(finalizedSql);  | 
  |  413 |    0 |            LOG.info("**************************************"); | 
  |  414 |    0 |            return finalizedSql;  | 
  |  415 |     | 
       }  | 
  |  416 |     | 
     | 
  |  417 |     | 
       public String getDocumentIdSql(String documentId, String whereClausePredicatePrefix, String tableAlias) { | 
  |  418 |    0 |            if (StringUtils.isBlank(documentId)) { | 
  |  419 |    0 |                return "";  | 
  |  420 |     | 
           } else { | 
  |  421 |     | 
                     | 
  |  422 |     | 
                     | 
  |  423 |    0 |                Criteria crit = getSqlBuilder().createCriteria("DOC_HDR_ID", documentId, "KREW_DOC_HDR_T", tableAlias, String.class, false, true); | 
  |  424 |    0 |                return new StringBuilder(whereClausePredicatePrefix + crit.buildWhere()).toString();  | 
  |  425 |     | 
           }  | 
  |  426 |     | 
       }  | 
  |  427 |     | 
     | 
  |  428 |     | 
       public String getDocTitleSql(String docTitle, String whereClausePredicatePrefix) { | 
  |  429 |    0 |            if (StringUtils.isBlank(docTitle)) { | 
  |  430 |    0 |                return "";  | 
  |  431 |     | 
           } else { | 
  |  432 |     | 
                 | 
  |  433 |    0 |                docTitle = docTitle.trim().replace("\'", "\'\'"); | 
  |  434 |    0 |                SqlBuilder sqlBuild = new SqlBuilder();  | 
  |  435 |    0 |                Criteria crit = new Criteria("KREW_DOC_HDR_T", "DOC_HDR"); | 
  |  436 |    0 |                sqlBuild.addCriteria("TTL", docTitle, String.class, true, true, crit); | 
  |  437 |    0 |                return new StringBuilder(whereClausePredicatePrefix + crit.buildWhere()).toString();  | 
  |  438 |     | 
           }  | 
  |  439 |     | 
       }  | 
  |  440 |     | 
     | 
  |  441 |     | 
         | 
  |  442 |     | 
         | 
  |  443 |     | 
       public String getAppDocIdSql(String appDocId, String whereClausePredicatePrefix) { | 
  |  444 |    0 |            if (StringUtils.isBlank(appDocId)) { | 
  |  445 |    0 |                return "";  | 
  |  446 |     | 
           } else { | 
  |  447 |    0 |                String tableAlias = "DOC_HDR";  | 
  |  448 |    0 |                Criteria crit = getSqlBuilder().createCriteria("APP_DOC_ID", appDocId, "KREW_DOC_HDR_T", tableAlias,String.class); | 
  |  449 |    0 |                return new StringBuilder(whereClausePredicatePrefix + crit.buildWhere()).toString();  | 
  |  450 |     | 
           }  | 
  |  451 |     | 
       }  | 
  |  452 |     | 
     | 
  |  453 |     | 
       public String getDateCreatedSql(DateTime fromDateCreated, DateTime toDateCreated, String whereClausePredicatePrefix) { | 
  |  454 |    0 |            return establishDateString(fromDateCreated, toDateCreated, "KREW_DOC_HDR_T", "DOC_HDR", "CRTE_DT", whereClausePredicatePrefix);  | 
  |  455 |     | 
       }  | 
  |  456 |     | 
     | 
  |  457 |     | 
       public String getDateApprovedSql(DateTime fromDateApproved, DateTime toDateApproved, String whereClausePredicatePrefix) { | 
  |  458 |    0 |            return establishDateString(fromDateApproved, toDateApproved, "KREW_DOC_HDR_T", "DOC_HDR", "APRV_DT", whereClausePredicatePrefix);  | 
  |  459 |     | 
       }  | 
  |  460 |     | 
     | 
  |  461 |     | 
       public String getDateFinalizedSql(DateTime fromDateFinalized, DateTime toDateFinalized, String whereClausePredicatePrefix) { | 
  |  462 |    0 |            return establishDateString(fromDateFinalized, toDateFinalized, "KREW_DOC_HDR_T", "DOC_HDR", "FNL_DT", whereClausePredicatePrefix);  | 
  |  463 |     | 
       }  | 
  |  464 |     | 
     | 
  |  465 |     | 
       public String getDateLastModifiedSql(DateTime fromDateLastModified, DateTime toDateLastModified, String whereClausePredicatePrefix) { | 
  |  466 |    0 |            return establishDateString(fromDateLastModified, toDateLastModified, "KREW_DOC_HDR_T", "DOC_HDR", "STAT_MDFN_DT", whereClausePredicatePrefix);  | 
  |  467 |     | 
       }  | 
  |  468 |     | 
     | 
  |  469 |     | 
           public String getStatusTransitionDateSql(DateTime fromStatusTransitionDate, DateTime toStatusTransitionDate, String whereClausePredicatePrefix) { | 
  |  470 |    0 |            return establishDateString(fromStatusTransitionDate, toStatusTransitionDate, "KREW_DOC_HDR_T", "DOC_HDR", "APP_DOC_STAT_MDFN_DT", whereClausePredicatePrefix);  | 
  |  471 |     | 
       }  | 
  |  472 |     | 
     | 
  |  473 |     | 
       public String getViewerSql(String viewer, String whereClausePredicatePrefix) { | 
  |  474 |    0 |            StringBuilder returnSql = new StringBuilder();  | 
  |  475 |    0 |            if (StringUtils.isNotBlank(viewer)) { | 
  |  476 |    0 |                Map<String, String> m = new HashMap<String, String>();  | 
  |  477 |    0 |                m.put("principalName", viewer); | 
  |  478 |     | 
     | 
  |  479 |     | 
                 | 
  |  480 |    0 |                List<Person> personList = KimApiServiceLocator.getPersonService().findPeople(m, false);  | 
  |  481 |    0 |                if(CollectionUtils.isEmpty(personList)) { | 
  |  482 |     | 
                     | 
  |  483 |    0 |                    return new StringBuilder(whereClausePredicatePrefix + " 1 = 0 ").toString();  | 
  |  484 |     | 
               }  | 
  |  485 |     | 
     | 
  |  486 |    0 |                List<String> principalList = new ArrayList<String>();  | 
  |  487 |    0 |                for (Person person : personList){ | 
  |  488 |    0 |                    principalList.add(person.getPrincipalId());  | 
  |  489 |     | 
               }  | 
  |  490 |     | 
     | 
  |  491 |    0 |                Criteria crit = new Criteria("KREW_ACTN_RQST_T", "KREW_ACTN_RQST_T"); | 
  |  492 |    0 |                crit.in("PRNCPL_ID", principalList, String.class); | 
  |  493 |    0 |                returnSql.append(whereClausePredicatePrefix + "( (DOC_HDR.DOC_HDR_ID = KREW_ACTN_RQST_T.DOC_HDR_ID and " + crit.buildWhere() + " )");  | 
  |  494 |     | 
     | 
  |  495 |    0 |                Set<String> viewerGroupIds = new TreeSet<String>();  | 
  |  496 |     | 
     | 
  |  497 |    0 |                if(CollectionUtils.isNotEmpty(principalList)) { | 
  |  498 |    0 |                    for(String principalId: principalList){ | 
  |  499 |    0 |                        viewerGroupIds.addAll(KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(principalId));  | 
  |  500 |     | 
                   }  | 
  |  501 |     | 
               }  | 
  |  502 |     | 
     | 
  |  503 |     | 
                 | 
  |  504 |     | 
                 | 
  |  505 |    0 |                if (viewerGroupIds != null && !viewerGroupIds.isEmpty()) { | 
  |  506 |     | 
     | 
  |  507 |    0 |                    returnSql.append(" or ( " + | 
  |  508 |     | 
                       "DOC_HDR.DOC_HDR_ID = KREW_ACTN_RQST_T.DOC_HDR_ID " +  | 
  |  509 |     | 
                       "and KREW_ACTN_RQST_T.GRP_ID in ("); | 
  |  510 |     | 
     | 
  |  511 |    0 |                    boolean first = true;  | 
  |  512 |    0 |                    for (String groupId : viewerGroupIds){ | 
  |  513 |    0 |                        if(!first){ | 
  |  514 |    0 |                            returnSql.append(","); | 
  |  515 |     | 
                       }  | 
  |  516 |    0 |                        returnSql.append("'").append(groupId).append("'"); | 
  |  517 |    0 |                        first = false;  | 
  |  518 |     | 
                   }  | 
  |  519 |    0 |                    returnSql.append("))"); | 
  |  520 |     | 
               }  | 
  |  521 |    0 |                returnSql.append(")"); | 
  |  522 |     | 
           }  | 
  |  523 |    0 |            return returnSql.toString();  | 
  |  524 |     | 
       }  | 
  |  525 |     | 
     | 
  |  526 |     | 
       public String getGroupViewerSql(String groupId, String whereClausePredicatePrefix) { | 
  |  527 |    0 |            String sql = "";  | 
  |  528 |    0 |            if (StringUtils.isNotBlank(groupId)) { | 
  |  529 |    0 |                sql = whereClausePredicatePrefix + " DOC_HDR.DOC_HDR_ID = KREW_ACTN_RQST_T.DOC_HDR_ID and KREW_ACTN_RQST_T.GRP_ID = '" + groupId + "'";  | 
  |  530 |     | 
           }  | 
  |  531 |    0 |            return sql;  | 
  |  532 |     | 
       }  | 
  |  533 |     | 
     | 
  |  534 |     | 
       public String getInitiatorSql(String initiatorPrincipalName, String whereClausePredicatePrefix) { | 
  |  535 |     | 
     | 
  |  536 |    0 |            if (StringUtils.isBlank(initiatorPrincipalName)) { | 
  |  537 |    0 |                return "";  | 
  |  538 |     | 
           }  | 
  |  539 |     | 
     | 
  |  540 |    0 |            String tableAlias = "DOC_HDR";  | 
  |  541 |     | 
     | 
  |  542 |    0 |            Map<String, String> m = new HashMap<String, String>();  | 
  |  543 |    0 |            m.put("principalName", initiatorPrincipalName); | 
  |  544 |     | 
     | 
  |  545 |     | 
             | 
  |  546 |    0 |            List<Person> pList = KimApiServiceLocator.getPersonService().findPeople(m, false);  | 
  |  547 |     | 
     | 
  |  548 |    0 |            if(pList == null || pList.isEmpty() ){ | 
  |  549 |     | 
                 | 
  |  550 |    0 |                 return new StringBuilder(whereClausePredicatePrefix + " 1 = 0 ").toString();  | 
  |  551 |     | 
           }  | 
  |  552 |     | 
     | 
  |  553 |    0 |            List<String> principalList = new ArrayList<String>();  | 
  |  554 |     | 
     | 
  |  555 |    0 |            for(Person p: pList){ | 
  |  556 |    0 |                principalList.add(p.getPrincipalId());  | 
  |  557 |     | 
           }  | 
  |  558 |     | 
     | 
  |  559 |    0 |            Criteria crit = new Criteria("KREW_DOC_HDR_T", tableAlias); | 
  |  560 |    0 |            crit.in("INITR_PRNCPL_ID", principalList, String.class); | 
  |  561 |     | 
     | 
  |  562 |    0 |            return new StringBuilder(whereClausePredicatePrefix + crit.buildWhere()).toString();  | 
  |  563 |     | 
       }  | 
  |  564 |     | 
     | 
  |  565 |     | 
       public String getApproverSql(String approver, String whereClausePredicatePrefix) { | 
  |  566 |    0 |            String returnSql = "";  | 
  |  567 |    0 |            if (StringUtils.isNotBlank(approver)) { | 
  |  568 |    0 |                Map<String, String> m = new HashMap<String, String>();  | 
  |  569 |    0 |                m.put("principalName", approver); | 
  |  570 |     | 
     | 
  |  571 |     | 
                 | 
  |  572 |    0 |                List<Person> pList = KimApiServiceLocator.getPersonService().findPeople(m, false);  | 
  |  573 |     | 
     | 
  |  574 |    0 |                if(pList == null || pList.isEmpty() ){ | 
  |  575 |    0 |                     return "";  | 
  |  576 |     | 
               }  | 
  |  577 |     | 
     | 
  |  578 |    0 |                List<String> principalList = new ArrayList<String>();  | 
  |  579 |     | 
     | 
  |  580 |    0 |                for(Person p: pList){ | 
  |  581 |    0 |                    principalList.add(p.getPrincipalId());  | 
  |  582 |     | 
               }  | 
  |  583 |     | 
     | 
  |  584 |    0 |                Criteria crit = new Criteria("KREW_ACTN_TKN_T", "KREW_ACTN_TKN_T"); | 
  |  585 |    0 |                crit.in("PRNCPL_ID", principalList, String.class); | 
  |  586 |     | 
     | 
  |  587 |    0 |                returnSql = whereClausePredicatePrefix +  | 
  |  588 |     | 
               " DOC_HDR.DOC_HDR_ID = KREW_ACTN_TKN_T.DOC_HDR_ID and upper(KREW_ACTN_TKN_T.ACTN_CD) in ('" + | 
  |  589 |     | 
               KewApiConstants.ACTION_TAKEN_APPROVED_CD + "','" + KewApiConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + "')" +  | 
  |  590 |     | 
               " and " + crit.buildWhere();  | 
  |  591 |     | 
           }  | 
  |  592 |    0 |            return returnSql;  | 
  |  593 |     | 
       }  | 
  |  594 |     | 
     | 
  |  595 |     | 
       public String getDocTypeFullNameWhereSql(DocumentSearchCriteria criteria, String whereClausePredicatePrefix) { | 
  |  596 |    0 |            List<String> documentTypeNamesToSearch = new ArrayList<String>();  | 
  |  597 |    0 |            String primaryDocumentTypeName = criteria.getDocumentTypeName();  | 
  |  598 |    0 |            if (StringUtils.isNotBlank(primaryDocumentTypeName)) { | 
  |  599 |    0 |                documentTypeNamesToSearch.add(primaryDocumentTypeName);  | 
  |  600 |     | 
           }  | 
  |  601 |    0 |            documentTypeNamesToSearch.addAll(criteria.getAdditionalDocumentTypeNames());  | 
  |  602 |    0 |            StringBuilder returnSql = new StringBuilder(""); | 
  |  603 |    0 |            if (CollectionUtils.isNotEmpty(documentTypeNamesToSearch)) { | 
  |  604 |    0 |                int index = 0;  | 
  |  605 |    0 |                for (String documentTypeName : documentTypeNamesToSearch) { | 
  |  606 |    0 |                    if (StringUtils.isNotBlank(documentTypeName)) { | 
  |  607 |    0 |                        String clause = index++ == 0 ? "" : " or ";  | 
  |  608 |    0 |                        DocumentTypeService docSrv = KEWServiceLocator.getDocumentTypeService();  | 
  |  609 |    0 |                        DocumentType docType = docSrv.findByName(documentTypeName.trim());  | 
  |  610 |    0 |                        if (docType != null) { | 
  |  611 |    0 |                            addDocumentTypeNameToSearchOn(returnSql, documentTypeName.trim(), clause);  | 
  |  612 |    0 |                            if (docType.getChildrenDocTypes() != null) { | 
  |  613 |    0 |                                addChildDocumentTypes(returnSql, docType.getChildrenDocTypes());  | 
  |  614 |     | 
                           }  | 
  |  615 |     | 
                       } else{ | 
  |  616 |    0 |                            addDocumentTypeLikeNameToSearchOn(returnSql, documentTypeName.trim(), clause);  | 
  |  617 |     | 
                       }  | 
  |  618 |    0 |                    }  | 
  |  619 |     | 
               }  | 
  |  620 |     | 
           }  | 
  |  621 |    0 |            if (returnSql.length() > 0) { | 
  |  622 |    0 |                returnSql.insert(0, "("); | 
  |  623 |    0 |                returnSql.insert(0, whereClausePredicatePrefix);  | 
  |  624 |    0 |                returnSql.append(")"); | 
  |  625 |     | 
           }  | 
  |  626 |    0 |            return returnSql.toString();  | 
  |  627 |     | 
       }  | 
  |  628 |     | 
     | 
  |  629 |     | 
       public void addChildDocumentTypes(StringBuilder whereSql, Collection<DocumentType> childDocumentTypes) { | 
  |  630 |    0 |            for (DocumentType child : childDocumentTypes) { | 
  |  631 |    0 |                addDocumentTypeNameToSearchOn(whereSql, child.getName());  | 
  |  632 |    0 |                addChildDocumentTypes(whereSql, child.getChildrenDocTypes());  | 
  |  633 |     | 
           }  | 
  |  634 |    0 |        }  | 
  |  635 |     | 
     | 
  |  636 |     | 
       public void addDocumentTypeNameToSearchOn(StringBuilder whereSql, String documentTypeName) { | 
  |  637 |    0 |            this.addDocumentTypeNameToSearchOn(whereSql, documentTypeName, " or ");  | 
  |  638 |    0 |        }  | 
  |  639 |     | 
     | 
  |  640 |     | 
       public void addDocumentTypeNameToSearchOn(StringBuilder whereSql, String documentTypeName, String clause) { | 
  |  641 |    0 |            whereSql.append(clause).append(" DOC1.DOC_TYP_NM = '" + documentTypeName + "'"); | 
  |  642 |    0 |        }  | 
  |  643 |     | 
       public void addDocumentTypeLikeNameToSearchOn(StringBuilder whereSql, String documentTypeName, String clause) { | 
  |  644 |    0 |            documentTypeName = documentTypeName.replace('*', '%'); | 
  |  645 |    0 |            whereSql.append(clause).append(" DOC1.DOC_TYP_NM LIKE '" + documentTypeName + "'"); | 
  |  646 |    0 |        }  | 
  |  647 |     | 
     | 
  |  648 |     | 
       public String getDocRouteNodeSql(String documentTypeFullName, String routeNodeName, RouteNodeLookupLogic docRouteLevelLogic, String whereClausePredicatePrefix) { | 
  |  649 |     | 
             | 
  |  650 |     | 
             | 
  |  651 |    0 |            String returnSql = "";  | 
  |  652 |    0 |            if (StringUtils.isNotBlank(routeNodeName)) { | 
  |  653 |    0 |                if (docRouteLevelLogic == null) { | 
  |  654 |    0 |                    docRouteLevelLogic = RouteNodeLookupLogic.EXACTLY;  | 
  |  655 |     | 
               }  | 
  |  656 |    0 |                StringBuilder routeNodeCriteria = new StringBuilder("and " + ROUTE_NODE_TABLE + ".NM "); | 
  |  657 |    0 |                if (RouteNodeLookupLogic.EXACTLY == docRouteLevelLogic) { | 
  |  658 |    0 |                            routeNodeCriteria.append("= '" + getDbPlatform().escapeString(routeNodeName) + "' "); | 
  |  659 |     | 
               } else { | 
  |  660 |    0 |                    routeNodeCriteria.append("in ("); | 
  |  661 |     | 
                     | 
  |  662 |    0 |                    StringBuilder routeNodeInCriteria = new StringBuilder();  | 
  |  663 |    0 |                    boolean foundSpecifiedNode = false;  | 
  |  664 |    0 |                    List<RouteNode> routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(getValidDocumentType(documentTypeFullName), true);  | 
  |  665 |    0 |                    for (RouteNode routeNode : routeNodes) { | 
  |  666 |    0 |                        if (routeNodeName.equals(routeNode.getRouteNodeName())) { | 
  |  667 |     | 
                             | 
  |  668 |    0 |                            foundSpecifiedNode = true;  | 
  |  669 |    0 |                            continue;  | 
  |  670 |     | 
                       }  | 
  |  671 |     | 
                         | 
  |  672 |     | 
                         | 
  |  673 |     | 
                         | 
  |  674 |    0 |                        if ( (!foundSpecifiedNode && RouteNodeLookupLogic.BEFORE == docRouteLevelLogic) ||  | 
  |  675 |     | 
                            (foundSpecifiedNode && RouteNodeLookupLogic.AFTER == docRouteLevelLogic) ) { | 
  |  676 |    0 |                            if (routeNodeInCriteria.length() > 0) { | 
  |  677 |    0 |                                routeNodeInCriteria.append(", "); | 
  |  678 |     | 
                           }  | 
  |  679 |    0 |                            routeNodeInCriteria.append("'" + routeNode.getRouteNodeName() + "'"); | 
  |  680 |     | 
                       }  | 
  |  681 |     | 
                   }  | 
  |  682 |    0 |                    if (routeNodeInCriteria.length() > 0) { | 
  |  683 |    0 |                        routeNodeCriteria.append(routeNodeInCriteria);  | 
  |  684 |     | 
                   } else { | 
  |  685 |    0 |                        routeNodeCriteria.append("''"); | 
  |  686 |     | 
                   }  | 
  |  687 |    0 |                    routeNodeCriteria.append(") "); | 
  |  688 |     | 
               }  | 
  |  689 |    0 |                returnSql = whereClausePredicatePrefix + "DOC_HDR.DOC_HDR_ID = " + ROUTE_NODE_INST_TABLE + ".DOC_HDR_ID and " + ROUTE_NODE_INST_TABLE + ".RTE_NODE_ID = " + ROUTE_NODE_TABLE + ".RTE_NODE_ID and " + ROUTE_NODE_INST_TABLE + ".ACTV_IND = 1 " + routeNodeCriteria.toString() + " ";  | 
  |  690 |     | 
           }  | 
  |  691 |    0 |            return returnSql;  | 
  |  692 |     | 
       }  | 
  |  693 |     | 
     | 
  |  694 |     | 
       public String getDocumentStatusSql(List<DocumentStatus> documentStatuses, List<DocumentStatusCategory> categories, String whereClausePredicatePrefix) { | 
  |  695 |    0 |            if (CollectionUtils.isEmpty(documentStatuses) && CollectionUtils.isEmpty(categories)) { | 
  |  696 |    0 |                return whereClausePredicatePrefix + "DOC_HDR.DOC_HDR_STAT_CD != '" + DocumentStatus.INITIATED.getCode() + "'";  | 
  |  697 |     | 
           } else { | 
  |  698 |     | 
                 | 
  |  699 |    0 |                Set<DocumentStatus> statusesToInclude = new HashSet<DocumentStatus>(documentStatuses);  | 
  |  700 |     | 
     | 
  |  701 |     | 
                 | 
  |  702 |    0 |                for (DocumentStatusCategory category : categories) { | 
  |  703 |    0 |                    Set<DocumentStatus> categoryStatuses = DocumentStatus.getStatusesForCategory(category);  | 
  |  704 |    0 |                    statusesToInclude.addAll(categoryStatuses);  | 
  |  705 |    0 |                }  | 
  |  706 |     | 
     | 
  |  707 |    0 |                Set<String> statusCodes = new HashSet<String>();  | 
  |  708 |    0 |                for (DocumentStatus statusToInclude : statusesToInclude) { | 
  |  709 |    0 |                    statusCodes.add("'" + getDbPlatform().escapeString(statusToInclude.getCode()) + "'"); | 
  |  710 |     | 
               }  | 
  |  711 |    0 |                return whereClausePredicatePrefix + " DOC_HDR.DOC_HDR_STAT_CD in (" + StringUtils.join(statusCodes, ", ") +")"; | 
  |  712 |     | 
           }  | 
  |  713 |     | 
       }  | 
  |  714 |     | 
     | 
  |  715 |     | 
         | 
  |  716 |     | 
     | 
  |  717 |     | 
     | 
  |  718 |     | 
     | 
  |  719 |     | 
     | 
  |  720 |     | 
       public String getAppDocStatusSql(String appDocStatus, String whereClausePredicatePrefix, int statusTransitionWhereClauseLength) { | 
  |  721 |    0 |            if (StringUtils.isBlank(appDocStatus)) { | 
  |  722 |    0 |                return "";  | 
  |  723 |     | 
           } else { | 
  |  724 |    0 |                    if (statusTransitionWhereClauseLength > 0){ | 
  |  725 |    0 |                            return whereClausePredicatePrefix + " STAT_TRAN.APP_DOC_STAT_TO = '" + getDbPlatform().escapeString(appDocStatus.trim()) + "'";  | 
  |  726 |     | 
                   }else{ | 
  |  727 |    0 |                            return whereClausePredicatePrefix + " DOC_HDR.APP_DOC_STAT = '" + getDbPlatform().escapeString(appDocStatus.trim()) + "'";  | 
  |  728 |     | 
                   }  | 
  |  729 |     | 
           }  | 
  |  730 |     | 
       }  | 
  |  731 |     | 
     | 
  |  732 |     | 
       public String getGeneratedPredicatePrefix(int whereClauseSize) { | 
  |  733 |    0 |            return (whereClauseSize > 0) ? " and " : " where ";  | 
  |  734 |     | 
       }  | 
  |  735 |     | 
     | 
  |  736 |     | 
       public String establishDateString(DateTime fromDate, DateTime toDate, String tableName, String tableAlias, String colName, String whereStatementClause) { | 
  |  737 |     | 
     | 
  |  738 |    0 |            String fromDateValue = null;  | 
  |  739 |    0 |            if (fromDate != null) { | 
  |  740 |    0 |                fromDateValue = CoreApiServiceLocator.getDateTimeService().toDateString(fromDate.toDate());  | 
  |  741 |     | 
           }  | 
  |  742 |     | 
     | 
  |  743 |    0 |            String toDateValue = null;  | 
  |  744 |    0 |            if (toDate != null) { | 
  |  745 |    0 |                toDateValue = CoreApiServiceLocator.getDateTimeService().toDateString(toDate.toDate());  | 
  |  746 |    0 |                toDateValue += " 23:59:59";  | 
  |  747 |     | 
           }  | 
  |  748 |     | 
     | 
  |  749 |    0 |            String searchValue = null;  | 
  |  750 |    0 |            if (fromDateValue != null && toDateValue != null) { | 
  |  751 |    0 |                searchValue = fromDateValue + " .. " + toDateValue;  | 
  |  752 |    0 |            } else if (fromDateValue != null) { | 
  |  753 |    0 |                searchValue = ">= " + fromDateValue;  | 
  |  754 |    0 |            } else if (toDateValue != null) { | 
  |  755 |    0 |                searchValue = "<= " + toDateValue;  | 
  |  756 |     | 
           } else { | 
  |  757 |    0 |                return "";  | 
  |  758 |     | 
           }  | 
  |  759 |     | 
     | 
  |  760 |    0 |            Criteria crit = getSqlBuilder().createCriteria(colName, searchValue, tableName, tableAlias, java.sql.Date.class, true, true);  | 
  |  761 |    0 |            return new StringBuilder(whereStatementClause).append(crit.buildWhere()).toString();  | 
  |  762 |     | 
     | 
  |  763 |     | 
       }  | 
  |  764 |     | 
     | 
  |  765 |     | 
       public DatabasePlatform getDbPlatform() { | 
  |  766 |    0 |            if (dbPlatform == null) { | 
  |  767 |    0 |                dbPlatform = (DatabasePlatform) GlobalResourceLoader.getService(RiceConstants.DB_PLATFORM);  | 
  |  768 |     | 
           }  | 
  |  769 |    0 |            return dbPlatform;  | 
  |  770 |     | 
       }  | 
  |  771 |     | 
     | 
  |  772 |     | 
       public SqlBuilder getSqlBuilder() { | 
  |  773 |    0 |            if(sqlBuilder == null){ | 
  |  774 |    0 |                sqlBuilder = new SqlBuilder();  | 
  |  775 |    0 |                sqlBuilder.setDbPlatform(getDbPlatform());  | 
  |  776 |    0 |                sqlBuilder.setDateTimeService(CoreApiServiceLocator.getDateTimeService());  | 
  |  777 |     | 
           }  | 
  |  778 |    0 |            return this.sqlBuilder;  | 
  |  779 |     | 
       }  | 
  |  780 |     | 
     | 
  |  781 |     | 
       public void setSqlBuilder(SqlBuilder sqlBuilder) { | 
  |  782 |    0 |            this.sqlBuilder = sqlBuilder;  | 
  |  783 |    0 |        }  | 
  |  784 |     | 
     | 
  |  785 |     | 
         | 
  |  786 |     | 
     | 
  |  787 |     | 
     | 
  |  788 |     | 
     | 
  |  789 |     | 
     | 
  |  790 |     | 
     | 
  |  791 |     | 
       protected boolean isUsingAtLeastOneSearchAttribute(DocumentSearchCriteria criteria) { | 
  |  792 |    0 |            return criteria.getDocumentAttributeValues().size() > 0 || StringUtils.isNotBlank(criteria.getDocumentTypeName());  | 
  |  793 |     | 
       }  | 
  |  794 |     | 
     | 
  |  795 |     | 
   }  |