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