View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.log4j.Logger;
25  import org.kuali.rice.core.api.config.ConfigurationException;
26  import org.kuali.rice.coreservice.api.CoreServiceApiServiceLocator;
27  import org.kuali.rice.coreservice.api.component.Component;
28  import org.kuali.rice.coreservice.api.component.ComponentService;
29  import org.kuali.rice.coreservice.framework.parameter.ParameterConstants;
30  import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
31  import org.kuali.rice.krad.datadictionary.DataObjectEntry;
32  import org.kuali.rice.krad.datadictionary.DocumentEntry;
33  import org.kuali.rice.krad.datadictionary.TransactionalDocumentEntry;
34  import org.kuali.rice.krad.document.TransactionalDocument;
35  import org.kuali.rice.krad.service.DataDictionaryComponentPublisherService;
36  import org.kuali.rice.krad.service.DataDictionaryService;
37  import org.kuali.rice.krad.service.KualiModuleService;
38  import org.kuali.rice.krad.util.KRADUtils;
39  
40  /**
41   * Reference implementation of the {@code DataDictionaryComponentPublisherService}.
42   *
43   * This implementation derives components from the DataDictionary for all BusinessObjects and Documents.
44   *
45   * @author Kuali Rice Team (rice.collab@kuali.org)
46   */
47  public class DataDictionaryComponentPublisherServiceImpl implements DataDictionaryComponentPublisherService {
48  
49      private static final Logger LOG = Logger.getLogger(DataDictionaryComponentPublisherServiceImpl.class);
50  
51      private static final String DEFAULT_COMPONENT_SET_ID_PREFIX = "DD:";
52  
53      private DataDictionaryService dataDictionaryService;
54      private KualiModuleService kualiModuleService;
55      private ComponentService componentService;
56      private String applicationId;
57  
58      @Override
59      public void publishAllComponents() {
60          List<Component> componentsToPublish = getComponentsToPublish();
61          getComponentService().publishDerivedComponents(generateComponentSetId(), componentsToPublish);
62      }
63  
64      protected String generateComponentSetId() {
65          if (StringUtils.isBlank(getApplicationId())) {
66              throw new ConfigurationException("A valid non-null, non-blank application id was not injected into " + getClass().getName());
67          }
68          return DEFAULT_COMPONENT_SET_ID_PREFIX + getApplicationId();
69      }
70  
71      protected List<Component> getComponentsToPublish() {
72          List<Component> components = new ArrayList<Component>();
73  
74          Map<String, Component> uniqueComponentMap = new HashMap<String, Component>();
75          for (DataObjectEntry dataObjectEntry : getDataDictionaryService().getDataDictionary().getDataObjectEntries().values()) {
76              try {
77                  Component component = deriveComponentFromDataObjectEntry(dataObjectEntry);
78                  uniqueComponentMap.put(component.getCode(), component);
79              }
80              catch (Exception e) {
81                  LOG.error("An exception was encountered when attempting to publish all components for business object class: " + dataObjectEntry.getDataObjectClass(), e);
82              }
83          }
84          for (DocumentEntry documentEntry : getDataDictionaryService().getDataDictionary().getDocumentEntries().values()) {
85              if (documentEntry instanceof TransactionalDocumentEntry) {
86                  try {
87                      Component component = deriveComponentFromDocumentEntry(documentEntry);
88                      uniqueComponentMap.put(component.getCode(), component);
89                  }
90                  catch (Exception e) {
91                      LOG.error("An exception was encountered when attempting to publish all components for transactional document class: " + documentEntry.getDocumentClass(), e);
92                  }
93              }
94          }
95          components.addAll(uniqueComponentMap.values());
96          return components;
97      }
98  
99  	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 }