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(readOnly=true)
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 @Transactional
124 public void publishDerivedComponents(String componentSetId, List<Component> components) {
125 if (StringUtils.isBlank(componentSetId)) {
126 throw new RiceIllegalArgumentException("componentSetId was a null or blank value");
127 }
128 components = validateAndNormalizeComponents(componentSetId, components);
129 LOG.info("Requesting to publish " + components.size() + " derived components for componentSetId=" + componentSetId);
130 ComponentSetBo componentSet = getDataObjectService().find(ComponentSetBo.class,componentSetId);
131 if (componentSet == null) {
132 componentSet = new ComponentSetBo();
133 componentSet.setComponentSetId(componentSetId);
134 }
135 String checksum = calculateChecksum(components);
136 if (!checksum.equals(componentSet.getChecksum())) {
137 LOG.info("Checksums were different, proceeding with update of derived components for componentSetId=" + componentSetId);
138 componentSet.setChecksum(checksum);
139 componentSet.setLastUpdateTimestamp(new Timestamp(System.currentTimeMillis()));
140 if (getComponentSetDao().saveIgnoreLockingFailure(componentSet)) {
141 updateDerivedComponents(componentSetId, components);
142 }
143 } else {
144 LOG.info("Checksums were the same, no derived component update needed for componentSetId=" + componentSetId);
145 }
146 }
147
148 protected List<Component> validateAndNormalizeComponents(String componentSetId, List<Component> components) {
149 List<Component> processedComponents = new ArrayList<Component>();
150
151
152 if (components == null) {
153 components = new ArrayList<Component>();
154 } else {
155 components = new ArrayList<Component>(components);
156 }
157
158 for (Component component : components) {
159
160 if (component.getComponentSetId() == null) {
161 Component.Builder builder = Component.Builder.create(component);
162 builder.setComponentSetId(componentSetId);
163 component = builder.build();
164 }
165 String currentComponentSetId = component.getComponentSetId();
166 if (!componentSetId.equals(currentComponentSetId)) {
167 throw new RiceIllegalArgumentException("Encountered a component with an invalid componentSetId of '" +
168 currentComponentSetId + "'. Expected null or '" + componentSetId + "'.");
169 }
170 processedComponents.add(component);
171 }
172 return processedComponents;
173 }
174
175
176
177
178
179
180
181 protected String calculateChecksum(List<Component> components) {
182 Collections.sort(components, new Comparator<Component>() {
183 @Override
184 public int compare(Component component1, Component component2) {
185 return CompareToBuilder.reflectionCompare(component1, component2);
186 }
187 });
188 return ChecksumUtils.calculateChecksum(components);
189 }
190
191 protected void updateDerivedComponents(String componentSetId, List<Component> components) {
192 Map<String, Object> deleteCriteria = new HashMap<String, Object>();
193 deleteCriteria.put("componentSetId", componentSetId);
194 dataObjectService.deleteMatching(DerivedComponentBo.class,
195 QueryByCriteria.Builder.andAttributes(deleteCriteria).build());
196 dataObjectService.flush(DerivedComponentBo.class);
197 if (CollectionUtils.isNotEmpty(components)) {
198 List<DerivedComponentBo> derivedComponentBos = new ArrayList<DerivedComponentBo>();
199 for (Component component : components) {
200 derivedComponentBos.add(DerivedComponentBo.from(component));
201 }
202 for(DerivedComponentBo component : derivedComponentBos){
203 dataObjectService.save(component);
204 }
205 }
206 }
207
208 protected List<Component> translateCollections(QueryResults<ComponentBo> componentBos,
209 QueryResults<DerivedComponentBo> derivedComponentBos){
210 List<Component> components = new ArrayList<Component>();
211 if (componentBos != null && CollectionUtils.isNotEmpty(componentBos.getResults())) {
212 for (ComponentBo componentBo : componentBos.getResults()) {
213 components.add(ComponentBo.to(componentBo));
214 }
215 }
216 if (derivedComponentBos != null && CollectionUtils.isNotEmpty(derivedComponentBos.getResults())) {
217 for (DerivedComponentBo derivedComponentBo : derivedComponentBos.getResults()) {
218 components.add(DerivedComponentBo.to(derivedComponentBo));
219 }
220 }
221 return Collections.unmodifiableList(components);
222 }
223
224 public ComponentSetDao getComponentSetDao() {
225 return componentSetDao;
226 }
227
228 public void setComponentSetDao(ComponentSetDao componentSetDao) {
229 this.componentSetDao = componentSetDao;
230 }
231
232 public DataObjectService getDataObjectService() {
233 return dataObjectService;
234 }
235
236 @Required
237 public void setDataObjectService(DataObjectService dataObjectService) {
238 this.dataObjectService = dataObjectService;
239 }
240
241 }