001 /**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.impl.document.attribute;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.apache.log4j.Logger;
020 import org.apache.log4j.MDC;
021 import org.joda.time.DateTime;
022 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
023 import org.kuali.rice.kew.api.KewApiServiceLocator;
024 import org.kuali.rice.kew.api.WorkflowRuntimeException;
025 import org.kuali.rice.kew.api.document.Document;
026 import org.kuali.rice.kew.api.document.DocumentContent;
027 import org.kuali.rice.kew.api.document.DocumentWithContent;
028 import org.kuali.rice.kew.api.document.WorkflowDocumentService;
029 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
030 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDateTime;
031 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDecimal;
032 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeIndexingQueue;
033 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeInteger;
034 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeString;
035 import org.kuali.rice.kew.docsearch.SearchableAttributeDateTimeValue;
036 import org.kuali.rice.kew.docsearch.SearchableAttributeFloatValue;
037 import org.kuali.rice.kew.docsearch.SearchableAttributeLongValue;
038 import org.kuali.rice.kew.docsearch.SearchableAttributeStringValue;
039 import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
040 import org.kuali.rice.kew.doctype.bo.DocumentType;
041 import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
042 import org.kuali.rice.kew.service.KEWServiceLocator;
043
044 import java.math.BigInteger;
045 import java.sql.Timestamp;
046 import java.util.ArrayList;
047 import java.util.List;
048
049 /**
050 * Reference implementation of the DocumentAttributeIndexingQueue.
051 *
052 * @author Kuali Rice Team (rice.collab@kuali.org)
053 */
054 public class DocumentAttributeIndexingQueueImpl implements DocumentAttributeIndexingQueue {
055
056 private static Logger LOG = Logger.getLogger(DocumentAttributeIndexingQueueImpl.class);
057
058 @Override
059 public void indexDocument(String documentId) {
060 if (StringUtils.isBlank(documentId)) {
061 throw new RiceIllegalArgumentException("documentId was null or blank");
062 }
063 MDC.put("docId", documentId);
064 try {
065 long t1 = System.currentTimeMillis();
066 LOG.info("Indexing document attributes for document " + documentId);
067 Document document = getWorkflowDocumentService().getDocument(documentId);
068 if (document == null) {
069 throw new RiceIllegalArgumentException("Failed to locate document with the given id: " + documentId);
070 }
071 DocumentContent documentContent =
072 KewApiServiceLocator.getWorkflowDocumentService().getDocumentContent(documentId);
073 List<SearchableAttributeValue> attributes = buildSearchableAttributeValues(document, documentContent);
074 KEWServiceLocator.getRouteHeaderService().updateRouteHeaderSearchValues(documentId, attributes);
075 long t2 = System.currentTimeMillis();
076 LOG.info("...finished indexing document " + documentId + " for document search, total time = " + (t2 - t1) +
077 " ms.");
078 } finally {
079 MDC.remove("docId");
080 }
081 }
082
083 /**
084 * Determines the {@link DocumentAttribute}s for the given document and returns a List of SearchableAttributeValue
085 * which will be saved.
086 */
087 private List<SearchableAttributeValue> buildSearchableAttributeValues(Document document, DocumentContent documentContent) {
088 List<SearchableAttributeValue> searchableAttributeValues = new ArrayList<SearchableAttributeValue>();
089 DocumentType documentTypeBo = KEWServiceLocator.getDocumentTypeService().findByName(document.getDocumentTypeName());
090 for (DocumentType.ExtensionHolder<SearchableAttribute> searchableAttributeHolder : documentTypeBo.loadSearchableAttributes()) {
091 DocumentWithContent documentWithContent = DocumentWithContent.create(document, documentContent);
092 SearchableAttribute searchableAttribute = searchableAttributeHolder.getExtension();
093 List<DocumentAttribute> documentAttributes = searchableAttribute.extractDocumentAttributes(
094 searchableAttributeHolder.getExtensionDefinition(), documentWithContent);
095 if (documentAttributes != null) {
096 for (DocumentAttribute documentAttribute : documentAttributes) {
097 if (documentAttribute == null) {
098 LOG.warn("Encountered a 'null' DocumentAttribute from searchable attribute: " + searchableAttribute);
099 continue;
100 }
101 SearchableAttributeValue searchableAttributeValue = null;
102 if (documentAttribute instanceof DocumentAttributeString) {
103 searchableAttributeValue = new SearchableAttributeStringValue();
104 ((SearchableAttributeStringValue)searchableAttributeValue).setSearchableAttributeValue(((DocumentAttributeString)documentAttribute).getValue());
105 } else if (documentAttribute instanceof DocumentAttributeDateTime) {
106 searchableAttributeValue = new SearchableAttributeDateTimeValue();
107 DateTime dateTimeValue = ((DocumentAttributeDateTime)documentAttribute).getValue();
108 Timestamp timestamp = (dateTimeValue == null ? null : new Timestamp(dateTimeValue.getMillis()));
109 ((SearchableAttributeDateTimeValue)searchableAttributeValue).setSearchableAttributeValue(timestamp);
110 } else if (documentAttribute instanceof DocumentAttributeInteger) {
111 searchableAttributeValue = new SearchableAttributeLongValue();
112 BigInteger bigIntegerValue = ((DocumentAttributeInteger)documentAttribute).getValue();
113 Long longValue = (bigIntegerValue == null ? null : bigIntegerValue.longValue());
114 ((SearchableAttributeLongValue)searchableAttributeValue).setSearchableAttributeValue(longValue);
115 } else if (documentAttribute instanceof DocumentAttributeDecimal) {
116 searchableAttributeValue = new SearchableAttributeFloatValue();
117 ((SearchableAttributeFloatValue)searchableAttributeValue).setSearchableAttributeValue(((DocumentAttributeDecimal)documentAttribute).getValue());
118 } else {
119 throw new WorkflowRuntimeException("Encountered an invalid instance of DocumentAttribute, was: " + documentAttribute.getClass());
120 }
121 searchableAttributeValue.setSearchableAttributeKey(documentAttribute.getName());
122 searchableAttributeValue.setDocumentId(document.getDocumentId());
123 searchableAttributeValue.setRouteHeader(null); // let the documentId we set represent this reference
124 searchableAttributeValues.add(searchableAttributeValue);
125 }
126 }
127 }
128 return searchableAttributeValues;
129 }
130
131 protected WorkflowDocumentService getWorkflowDocumentService() {
132 return KewApiServiceLocator.getWorkflowDocumentService();
133 }
134 }