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.krad.service.impl; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.apache.log4j.Logger; 020 import org.kuali.rice.core.api.config.ConfigurationException; 021 import org.kuali.rice.coreservice.api.CoreServiceApiServiceLocator; 022 import org.kuali.rice.coreservice.api.component.Component; 023 import org.kuali.rice.coreservice.api.component.ComponentService; 024 import org.kuali.rice.coreservice.framework.parameter.ParameterConstants; 025 import org.kuali.rice.krad.bo.BusinessObject; 026 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry; 027 import org.kuali.rice.krad.datadictionary.DocumentEntry; 028 import org.kuali.rice.krad.datadictionary.TransactionalDocumentEntry; 029 import org.kuali.rice.krad.document.TransactionalDocument; 030 import org.kuali.rice.krad.service.DataDictionaryComponentPublisherService; 031 import org.kuali.rice.krad.service.DataDictionaryService; 032 import org.kuali.rice.krad.service.KualiModuleService; 033 import org.kuali.rice.krad.util.KRADUtils; 034 035 import java.util.ArrayList; 036 import java.util.HashMap; 037 import java.util.List; 038 import java.util.Map; 039 040 /** 041 * Reference implementation of the {@code DataDictionaryComponentPublisherService}. 042 * 043 * This implementation derives components from the DataDictionary for all BusinessObjects and Documents. 044 * 045 * @author Kuali Rice Team (rice.collab@kuali.org) 046 */ 047 public class DataDictionaryComponentPublisherServiceImpl implements DataDictionaryComponentPublisherService { 048 049 private static final Logger LOG = Logger.getLogger(DataDictionaryComponentPublisherServiceImpl.class); 050 051 private static final String DEFAULT_COMPONENT_SET_ID_PREFIX = "DD:"; 052 053 private DataDictionaryService dataDictionaryService; 054 private KualiModuleService kualiModuleService; 055 private ComponentService componentService; 056 private String applicationId; 057 058 @Override 059 public void publishAllComponents() { 060 List<Component> componentsToPublish = getComponentsToPublish(); 061 getComponentService().publishDerivedComponents(generateComponentSetId(), componentsToPublish); 062 } 063 064 protected String generateComponentSetId() { 065 if (StringUtils.isBlank(getApplicationId())) { 066 throw new ConfigurationException("A valid non-null, non-blank application id was not injected into " + getClass().getName()); 067 } 068 return DEFAULT_COMPONENT_SET_ID_PREFIX + getApplicationId(); 069 } 070 071 protected List<Component> getComponentsToPublish() { 072 List<Component> components = new ArrayList<Component>(); 073 074 Map<String, Component> uniqueComponentMap = new HashMap<String, Component>(); 075 for (BusinessObjectEntry businessObjectEntry : getDataDictionaryService().getDataDictionary().getBusinessObjectEntries().values()) { 076 try { 077 Component component = deriveComponentFromBusinessObjectEntry(businessObjectEntry); 078 uniqueComponentMap.put(component.getCode(), component); 079 } 080 catch (Exception e) { 081 LOG.error("An exception was encountered when attempting to publish all components for business object class: " + businessObjectEntry.getBusinessObjectClass(), e); 082 } 083 } 084 for (DocumentEntry documentEntry : getDataDictionaryService().getDataDictionary().getDocumentEntries().values()) { 085 if (documentEntry instanceof TransactionalDocumentEntry) { 086 try { 087 Component component = deriveComponentFromDocumentEntry(documentEntry); 088 uniqueComponentMap.put(component.getCode(), component); 089 } 090 catch (Exception e) { 091 LOG.error("An exception was encountered when attempting to publish all components for transactional document class: " + documentEntry.getDocumentClass(), e); 092 } 093 } 094 } 095 components.addAll(uniqueComponentMap.values()); 096 return components; 097 } 098 099 protected Component deriveComponentFromClass(Class<?> componentSourceClass) { 100 String componentCode = getKualiModuleService().getComponentCode(componentSourceClass); 101 String componentName = deriveComponentName(componentSourceClass); 102 String namespace = getKualiModuleService().getNamespaceCode(componentSourceClass); 103 if (StringUtils.isBlank(componentName)) { 104 componentName = componentCode; 105 } 106 Component.Builder detailType = Component.Builder.create(namespace, componentCode, componentName); 107 return detailType.build(); 108 } 109 110 protected Component deriveComponentFromBusinessObjectEntry(BusinessObjectEntry businessObjectEntry) { 111 Class<?> businessObjectClass = businessObjectEntry.getBaseBusinessObjectClass(); 112 if (businessObjectClass == null) { 113 businessObjectClass = businessObjectEntry.getBusinessObjectClass(); 114 } 115 return deriveComponentFromClass(businessObjectClass); 116 } 117 118 protected Component deriveComponentFromDocumentEntry(DocumentEntry documentEntry) { 119 Class<?> documentClass = documentEntry.getBaseDocumentClass(); 120 if (documentClass == null) { 121 documentClass = documentEntry.getDocumentClass(); 122 } 123 return deriveComponentFromClass(documentClass); 124 } 125 126 protected String deriveComponentName(Class<?> componentSourceClass) { 127 if (componentSourceClass == null) { 128 throw new IllegalArgumentException("The deriveComponentName method requires non-null componentSourceClass"); 129 } 130 131 /* 132 * Some business objects have a Component annotation that sets the value 133 * of the classes annotaion. This if block will test to see if it is there, try to get the 134 * component value from the Data Dictionary if the BusinessObjectEntry exists, if it doesn't 135 * exist, it will fall back to the annotation's value. 136 */ 137 if (componentSourceClass.isAnnotationPresent(ParameterConstants.COMPONENT.class)) { 138 BusinessObjectEntry boe = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(componentSourceClass.getName()); 139 if (boe != null) { 140 return boe.getObjectLabel(); 141 } 142 else { 143 return ((ParameterConstants.COMPONENT) componentSourceClass.getAnnotation(ParameterConstants.COMPONENT.class)).component(); 144 } 145 } 146 147 /* 148 * If block that determines if the class is either a BusinessObject or a TransactionalDocument 149 * return calls try to either get the BusinessObjectEntry's ObjectLable, or grabbing the 150 * data dictionary's BusinessTitleForClass if it is a BusinessObject, or the DocumentLabel if it is a 151 * TransactionalDocument 152 */ 153 if (TransactionalDocument.class.isAssignableFrom(componentSourceClass)) { 154 return getDataDictionaryService().getDocumentLabelByClass(componentSourceClass); 155 } 156 else if (BusinessObject.class.isAssignableFrom(componentSourceClass) ) { 157 BusinessObjectEntry boe = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(componentSourceClass.getName()); 158 if (boe != null) { 159 return boe.getObjectLabel(); 160 } 161 else { 162 return KRADUtils.getBusinessTitleForClass(componentSourceClass); 163 } 164 } 165 throw new IllegalArgumentException("The deriveComponentName method of requires TransactionalDocument or BusinessObject class. Was: " + componentSourceClass.getName() ); 166 } 167 168 public DataDictionaryService getDataDictionaryService() { 169 return dataDictionaryService; 170 } 171 172 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 173 this.dataDictionaryService = dataDictionaryService; 174 } 175 176 public KualiModuleService getKualiModuleService() { 177 return kualiModuleService; 178 } 179 180 public void setKualiModuleService(KualiModuleService kualiModuleService) { 181 this.kualiModuleService = kualiModuleService; 182 } 183 184 public ComponentService getComponentService() { 185 if (componentService == null) { 186 componentService = CoreServiceApiServiceLocator.getComponentService(); 187 } 188 return componentService; 189 } 190 191 public void setComponentService(ComponentService componentService) { 192 this.componentService = componentService; 193 } 194 195 public String getApplicationId() { 196 return applicationId; 197 } 198 199 public void setApplicationId(String applicationId) { 200 this.applicationId = applicationId; 201 } 202 203 }