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