1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.coreservice.impl.component;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.commons.lang.builder.CompareToBuilder;
21 import org.apache.log4j.Logger;
22 import org.kuali.rice.coreservice.api.component.Component;
23 import org.kuali.rice.coreservice.api.component.ComponentService;
24 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
25 import org.kuali.rice.core.api.util.ChecksumUtils;
26 import org.kuali.rice.krad.service.BusinessObjectService;
27 import org.springframework.transaction.annotation.Transactional;
28
29 import java.sql.Timestamp;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Comparator;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37
38
39
40
41
42
43 @Transactional
44 public class ComponentServiceImpl implements ComponentService {
45
46 private static final Logger LOG = Logger.getLogger(ComponentServiceImpl.class);
47
48 private BusinessObjectService businessObjectService;
49 private ComponentSetDao componentSetDao;
50
51 @Override
52 public Component getComponentByCode(String namespaceCode, String componentCode) {
53 if (StringUtils.isBlank(namespaceCode)) {
54 throw new RiceIllegalArgumentException("namespaceCode was a null or blank value");
55 }
56 if (StringUtils.isBlank(componentCode)) {
57 throw new RiceIllegalArgumentException("componentCode was a null or blank value");
58 }
59 Map<String, String> primaryKeys = new HashMap<String, String>();
60 primaryKeys.put("namespaceCode", namespaceCode);
61 primaryKeys.put("code", componentCode);
62 ComponentBo componentBo = getBusinessObjectService().findByPrimaryKey(ComponentBo.class, primaryKeys);
63 if (componentBo != null) {
64 return ComponentBo.to(componentBo);
65 }
66 DerivedComponentBo derivedComponentBo = getBusinessObjectService().findByPrimaryKey(DerivedComponentBo.class, primaryKeys);
67 return derivedComponentBo == null ? null : DerivedComponentBo.to(derivedComponentBo);
68 }
69
70 @Override
71 public List<Component> getAllComponentsByNamespaceCode(String namespaceCode) {
72 if (StringUtils.isBlank(namespaceCode)) {
73 throw new RiceIllegalArgumentException("namespaceCode was a null or blank value");
74 }
75 Map<String, String> criteria = new HashMap<String, String>();
76 criteria.put("namespaceCode", namespaceCode);
77
78 List<Component> components = new ArrayList<Component>();
79
80 Collection<ComponentBo> componentBos =
81 getBusinessObjectService().findMatching(ComponentBo.class, criteria);
82 Collection<DerivedComponentBo> derivedComponentBos =
83 getBusinessObjectService().findMatching(DerivedComponentBo.class, criteria);
84 return translateCollections(componentBos, derivedComponentBos);
85 }
86
87 @Override
88 public List<Component> getActiveComponentsByNamespaceCode(String namespaceCode) {
89 if (StringUtils.isBlank(namespaceCode)) {
90 throw new RiceIllegalArgumentException("namespaceCode was a null or blank value");
91 }
92 Map<String, Object> criteria = new HashMap<String, Object>();
93 criteria.put("namespaceCode", namespaceCode);
94 criteria.put("active", Boolean.TRUE);
95 Collection<ComponentBo> componentBos =
96 getBusinessObjectService().findMatching(ComponentBo.class, criteria);
97 criteria.remove("active");
98 Collection<DerivedComponentBo> derivedComponentBos =
99 getBusinessObjectService().findMatching(DerivedComponentBo.class, criteria);
100 return translateCollections(componentBos, derivedComponentBos);
101 }
102
103 @Override
104 public List<Component> getDerivedComponentSet(String componentSetId) {
105 if (StringUtils.isBlank(componentSetId)) {
106 throw new RiceIllegalArgumentException("componentSetId was a null or blank value");
107 }
108 Map<String, Object> criteria = new HashMap<String, Object>();
109 criteria.put("componentSetId", componentSetId);
110 Collection<DerivedComponentBo> derivedComponentBos =
111 getBusinessObjectService().findMatching(DerivedComponentBo.class, criteria);
112 return translateCollections(null, derivedComponentBos);
113 }
114
115 @Override
116 public void publishDerivedComponents(String componentSetId, List<Component> components) {
117 if (StringUtils.isBlank(componentSetId)) {
118 throw new RiceIllegalArgumentException("componentSetId was a null or blank value");
119 }
120 components = validateAndNormalizeComponents(componentSetId, components);
121 LOG.info("Requesting to publish " + components.size() + " derived components for componentSetId=" + componentSetId);
122 ComponentSetBo componentSet = getComponentSetDao().getComponentSet(componentSetId);
123 if (componentSet == null) {
124 componentSet = new ComponentSetBo();
125 componentSet.setComponentSetId(componentSetId);
126 }
127 String checksum = calculateChecksum(components);
128 if (!checksum.equals(componentSet.getChecksum())) {
129 LOG.info("Checksums were different, proceeding with update of derived components for componentSetId=" + componentSetId);
130 componentSet.setChecksum(checksum);
131 componentSet.setLastUpdateTimestamp(new Timestamp(System.currentTimeMillis()));
132 if (getComponentSetDao().saveIgnoreLockingFailure(componentSet)) {
133 updateDerivedComponents(componentSetId, components);
134 }
135 } else {
136 LOG.info("Checksums were the same, no derived component update needed for componentSetId=" + componentSetId);
137 }
138 }
139
140 protected List<Component> validateAndNormalizeComponents(String componentSetId, List<Component> components) {
141 List<Component> processedComponents = new ArrayList<Component>();
142
143
144 if (components == null) {
145 components = new ArrayList<Component>();
146 } else {
147 components = new ArrayList<Component>(components);
148 }
149
150 for (Component component : components) {
151
152 if (component.getComponentSetId() == null) {
153 Component.Builder builder = Component.Builder.create(component);
154 builder.setComponentSetId(componentSetId);
155 component = builder.build();
156 }
157 String currentComponentSetId = component.getComponentSetId();
158 if (!componentSetId.equals(currentComponentSetId)) {
159 throw new RiceIllegalArgumentException("Encountered a component with an invalid componentSetId of '" +
160 currentComponentSetId + "'. Expected null or '" + componentSetId + "'.");
161 }
162 processedComponents.add(component);
163 }
164 return processedComponents;
165 }
166
167
168
169
170
171
172
173 protected String calculateChecksum(List<Component> components) {
174 Collections.sort(components, new Comparator<Component>() {
175 @Override
176 public int compare(Component component1, Component component2) {
177 return CompareToBuilder.reflectionCompare(component1, component2);
178 }
179 });
180 return ChecksumUtils.calculateChecksum(components);
181 }
182
183 protected void updateDerivedComponents(String componentSetId, List<Component> components) {
184 Map<String, Object> deleteCriteria = new HashMap<String, Object>();
185 deleteCriteria.put("componentSetId", componentSetId);
186 businessObjectService.deleteMatching(DerivedComponentBo.class, deleteCriteria);
187 if (CollectionUtils.isNotEmpty(components)) {
188 List<DerivedComponentBo> derivedComponentBos = new ArrayList<DerivedComponentBo>();
189 for (Component component : components) {
190 derivedComponentBos.add(DerivedComponentBo.from(component));
191 }
192 businessObjectService.save(derivedComponentBos);
193 }
194 }
195
196 protected List<Component> translateCollections(Collection<ComponentBo> componentBos, Collection<DerivedComponentBo> derivedComponentBos) {
197 List<Component> components = new ArrayList<Component>();
198 if (CollectionUtils.isNotEmpty(componentBos)) {
199 for (ComponentBo componentBo : componentBos) {
200 components.add(ComponentBo.to(componentBo));
201 }
202 }
203 if (CollectionUtils.isNotEmpty(derivedComponentBos)) {
204 for (DerivedComponentBo derivedComponentBo : derivedComponentBos) {
205 components.add(DerivedComponentBo.to(derivedComponentBo));
206 }
207 }
208 return Collections.unmodifiableList(components);
209 }
210
211 public BusinessObjectService getBusinessObjectService() {
212 return businessObjectService;
213 }
214
215 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
216 this.businessObjectService = businessObjectService;
217 }
218
219 public ComponentSetDao getComponentSetDao() {
220 return componentSetDao;
221 }
222
223 public void setComponentSetDao(ComponentSetDao componentSetDao) {
224 this.componentSetDao = componentSetDao;
225 }
226
227 }