001/** 002 * Copyright 2005-2016 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.krad.service.impl; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.commons.lang.StringUtils; 024import org.apache.log4j.Logger; 025import org.kuali.rice.core.api.config.ConfigurationException; 026import org.kuali.rice.coreservice.api.CoreServiceApiServiceLocator; 027import org.kuali.rice.coreservice.api.component.Component; 028import org.kuali.rice.coreservice.api.component.ComponentService; 029import org.kuali.rice.coreservice.framework.parameter.ParameterConstants; 030import org.kuali.rice.krad.datadictionary.BusinessObjectEntry; 031import org.kuali.rice.krad.datadictionary.DataObjectEntry; 032import org.kuali.rice.krad.datadictionary.DocumentEntry; 033import org.kuali.rice.krad.datadictionary.TransactionalDocumentEntry; 034import org.kuali.rice.krad.document.TransactionalDocument; 035import org.kuali.rice.krad.service.DataDictionaryComponentPublisherService; 036import org.kuali.rice.krad.service.DataDictionaryService; 037import org.kuali.rice.krad.service.KualiModuleService; 038import org.kuali.rice.krad.util.KRADUtils; 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 */ 047public 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 (DataObjectEntry dataObjectEntry : getDataDictionaryService().getDataDictionary().getDataObjectEntries().values()) { 076 try { 077 Component component = deriveComponentFromDataObjectEntry(dataObjectEntry); 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: " + dataObjectEntry.getDataObjectClass(), 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 deriveComponentFromDataObjectEntry(DataObjectEntry dataObjectEntry) { 111 if (dataObjectEntry.getBaseDataObjectClass() != null) { 112 return deriveComponentFromClass(dataObjectEntry.getBaseDataObjectClass()); 113 } 114 115 return deriveComponentFromClass(dataObjectEntry.getDataObjectClass()); 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 annotation. 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 DataObjectEntry doe = getDataDictionaryService().getDataDictionary().getDataObjectEntry(componentSourceClass.getName()); 139 if (doe != null) { 140 return doe.getObjectLabel(); 141 } else { 142 return componentSourceClass.getAnnotation(ParameterConstants.COMPONENT.class).component(); 143 } 144 } 145 146 /* 147 * If block that determines if the class is either a BusinessObject or a TransactionalDocument 148 * return calls try to either get the BusinessObjectEntry's ObjectLable, or grabbing the 149 * data dictionary's BusinessTitleForClass if it is a BusinessObject, or the DocumentLabel if it is a 150 * TransactionalDocument 151 */ 152 if (TransactionalDocument.class.isAssignableFrom(componentSourceClass)) { 153 return getDataDictionaryService().getDocumentLabelByClass(componentSourceClass); 154 } 155 DataObjectEntry doe = getDataDictionaryService().getDataDictionary().getDataObjectEntry(componentSourceClass.getName()); 156 if (doe != null) { 157 return doe.getObjectLabel(); 158 } else { 159 return KRADUtils.getBusinessTitleForClass(componentSourceClass); 160 } 161 } 162 163 public DataDictionaryService getDataDictionaryService() { 164 return dataDictionaryService; 165 } 166 167 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 168 this.dataDictionaryService = dataDictionaryService; 169 } 170 171 public KualiModuleService getKualiModuleService() { 172 return kualiModuleService; 173 } 174 175 public void setKualiModuleService(KualiModuleService kualiModuleService) { 176 this.kualiModuleService = kualiModuleService; 177 } 178 179 public ComponentService getComponentService() { 180 if (componentService == null) { 181 componentService = CoreServiceApiServiceLocator.getComponentService(); 182 } 183 return componentService; 184 } 185 186 public void setComponentService(ComponentService componentService) { 187 this.componentService = componentService; 188 } 189 190 public String getApplicationId() { 191 return applicationId; 192 } 193 194 public void setApplicationId(String applicationId) { 195 this.applicationId = applicationId; 196 } 197 198}