001/** 002 * Copyright 2005-2017 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.util; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.log4j.Logger; 020import org.kuali.rice.kew.doctype.DocumentTypePolicy; 021import org.kuali.rice.kew.doctype.bo.DocumentType; 022import org.kuali.rice.kew.doctype.service.DocumentTypeService; 023 024import java.util.HashMap; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027 028/** 029 * A simple utility class which can parse a target specification for a set of defined Document Types. 030 * 031 * @author Eric Westfall 032 */ 033public class DocumentTypeWindowTargets { 034 035 private static final Logger LOG = Logger.getLogger(DocumentTypeWindowTargets.class); 036 private static final String DEFAULT_KEY = "*"; 037 038 private final Map<String, String> documentTargetMappings; 039 private final Map<String, String> routeLogTargetMappings; 040 private final DocumentTypeService documentTypeService; 041 042 private final String defaultDocumentTarget; 043 private final String defaultRouteLogTarget; 044 045 private final Map<String, String> documentTargetCache = new ConcurrentHashMap<>(); 046 private final Map<String, String> routeLogTargetCache = new ConcurrentHashMap<>(); 047 048 public DocumentTypeWindowTargets(String documentTargetSpec, String routeLogTargetSpec, String defaultDocumentTarget, String defaultRouteLogTarget, DocumentTypeService documentTypeService) { 049 if (StringUtils.isBlank(defaultDocumentTarget)) { 050 throw new IllegalArgumentException("defaultDocumentTarget must not be blank"); 051 } 052 if (StringUtils.isBlank(defaultRouteLogTarget)) { 053 throw new IllegalArgumentException("defaultRouteLogTarget must not be blank"); 054 } 055 if (documentTypeService == null) { 056 throw new IllegalArgumentException("documentTypeService must not be nulll"); 057 } 058 this.documentTargetMappings = new HashMap<>(); 059 this.routeLogTargetMappings = new HashMap<>(); 060 this.documentTypeService = documentTypeService; 061 this.defaultDocumentTarget = defaultDocumentTarget; 062 this.defaultRouteLogTarget = defaultRouteLogTarget; 063 064 parseTargetSpec(documentTargetSpec, this.documentTargetMappings); 065 parseTargetSpec(routeLogTargetSpec, this.routeLogTargetMappings); 066 } 067 068 private void parseTargetSpec(String targetSpec, Map<String, String> targetMappings) { 069 if (!StringUtils.isBlank(targetSpec)) { 070 String[] entries = targetSpec.split(","); 071 for (String entry : entries) { 072 String[] docTypeTarget = entry.split(":"); 073 if (docTypeTarget.length != 2) { 074 LOG.warn("Encountered an invalid entry in target spec, ignoring: " + entry); 075 } else { 076 targetMappings.put(docTypeTarget[0], docTypeTarget[1]); 077 } 078 } 079 } 080 } 081 082 public String getDocumentTarget(String documentTypeName) { 083 return getTargetInternal(documentTypeName, false, 0); 084 } 085 086 public String getRouteLogTarget(String documentTypeName) { 087 return getTargetInternal(documentTypeName, true, 0); 088 } 089 090 private String getTargetInternal(String documentTypeName, boolean isRouteLog, int depth) { 091 if (StringUtils.isBlank(documentTypeName)) { 092 throw new IllegalArgumentException("Document type name must not be blank"); 093 } 094 Map<String, String> targetCache = isRouteLog ? routeLogTargetCache : documentTargetCache; 095 if (!targetCache.containsKey(documentTypeName)) { 096 Map<String, String> targetMappings = isRouteLog ? routeLogTargetMappings : documentTargetMappings; 097 String target = targetMappings.get(documentTypeName); 098 if (target == null) { 099 // first if we are at depth 0, check if the doc type has a policy on it 100 if (depth == 0) { 101 DocumentType documentType = documentTypeService.findByName(documentTypeName); 102 if (documentType != null) { 103 DocumentTypePolicy docSearchTarget = documentType.getDocSearchTarget(); 104 if (docSearchTarget.getPolicyStringValue() != null) { 105 target = docSearchTarget.getPolicyStringValue(); 106 } 107 } 108 } 109 } 110 // if there was no policy, check the parent document type if there is one 111 if (target == null) { 112 String parentDocumentTypeName = documentTypeService.findParentNameByName(documentTypeName); 113 if (parentDocumentTypeName != null) { 114 target = getTargetInternal(parentDocumentTypeName, isRouteLog, depth + 1); 115 } 116 } 117 // fall back to the defaults if no other target can be determined 118 if (target == null) { 119 target = targetMappings.get(DEFAULT_KEY); 120 if (target == null) { 121 target = isRouteLog ? defaultRouteLogTarget : defaultDocumentTarget; 122 } 123 } 124 targetCache.put(documentTypeName, target); 125 } 126 return targetCache.get(documentTypeName); 127 } 128 129}