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 }