1 package org.kuali.student.r2.lum.course.service.assembler;
2
3 import org.kuali.student.common.util.UUIDHelper;
4 import org.kuali.student.r1.common.assembly.BOAssembler;
5 import org.kuali.student.r1.common.assembly.BaseDTOAssemblyNode;
6 import org.kuali.student.r1.common.assembly.BaseDTOAssemblyNode.NodeOperation;
7 import org.kuali.student.r2.common.dto.DtoConstants;
8 import org.kuali.student.r2.lum.course.dto.LoDisplayInfo;
9 import org.kuali.student.r2.lum.lo.dto.LoCategoryInfo;
10 import org.kuali.student.r2.lum.lo.dto.LoInfo;
11 import org.kuali.student.r2.lum.lo.dto.LoLoRelationInfo;
12 import org.kuali.student.r2.common.assembler.AssemblyException;
13 import org.kuali.student.r2.common.dto.AttributeInfo;
14 import org.kuali.student.r2.common.dto.ContextInfo;
15 import org.kuali.student.r2.common.exceptions.*;
16 import org.kuali.student.r2.lum.lo.service.LearningObjectiveService;
17
18 import java.util.*;
19 import java.util.Map.Entry;
20
21
22 public class LoAssembler implements BOAssembler<LoDisplayInfo, LoInfo> {
23
24 private LearningObjectiveService loService;
25
26
27 @Override
28 public LoDisplayInfo assemble(LoInfo lo, LoDisplayInfo loDisplayInfo,
29 boolean shallowBuild, ContextInfo contextInfo) throws AssemblyException {
30
31 LoDisplayInfo loDisplay = (null != loDisplayInfo) ? loDisplayInfo : new LoDisplayInfo();
32
33 loDisplay.setLoInfo(lo);
34
35 if (!shallowBuild) {
36 String loId = lo.getId();
37 try {
38 List<LoCategoryInfo> loCategories = null;
39 loCategories = loService.getLoCategoriesByLo(loId, contextInfo);
40 loDisplay.setLoCategoryInfoList(loCategories);
41 } catch (DoesNotExistException e) {
42 } catch (Exception e) {
43 throw new AssemblyException("Error getting learning objective categories", e);
44 }
45 try {
46 List<LoInfo> childLos = loService.getRelatedLosByLoId(loId, CourseAssemblerConstants.COURSE_LO_RELATION_INCLUDES, contextInfo);
47 for(LoInfo childLo:childLos){
48 LoDisplayInfo childLoDisplay = assemble(childLo, null, shallowBuild,contextInfo);
49 childLoDisplay.setParentLoRelationid(lo.getId());
50
51 childLoDisplay.setParentRelType(CourseAssemblerConstants.COURSE_LO_RELATION_INCLUDES);
52 loDisplay.getLoDisplayInfoList().add(childLoDisplay);
53 }
54 if(loDisplay.getLoDisplayInfoList().size()>1){
55 Collections.sort(loDisplay.getLoDisplayInfoList(), LoDisplayComparator.getInstance());
56 }
57 } catch (DoesNotExistException e) {
58 } catch (Exception e) {
59 throw new AssemblyException("Error getting learning objective", e);
60 }
61
62 }
63 return loDisplay;
64 }
65
66
67
68 public BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> disassemble(
69 LoDisplayInfo loDisplay, NodeOperation operation,ContextInfo contextInfo)
70 throws AssemblyException {
71
72 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> result = new BaseDTOAssemblyNode<LoDisplayInfo, LoInfo>(this);
73
74
75 if (loDisplay == null || loDisplay.getLoInfo() == null) {
76 throw new AssemblyException("Lo can not be null");
77 }
78 if (NodeOperation.CREATE != operation && null == loDisplay.getLoInfo().getId()) {
79 throw new AssemblyException("Lo id can not be null");
80 }
81
82
83 loDisplay.getLoInfo().setId(UUIDHelper.genStringUUID(loDisplay.getLoInfo().getId()));
84
85
86
87 loDisplay.getLoInfo().setTypeKey(CourseAssemblerConstants.COURSE_LO_TYPE);
88
89 loDisplay.getLoInfo().setLoRepositoryKey(CourseAssemblerConstants.COURSE_LO_REPOSITORY_KEY);
90
91
92
93 result.setBusinessDTORef(loDisplay);
94 result.setNodeData(loDisplay.getLoInfo());
95 result.setOperation(operation);
96
97
98 try {
99 List<BaseDTOAssemblyNode<?, ?>> childLoNodes = disassembleChildLos(loDisplay, operation,contextInfo);
100 result.getChildNodes().addAll(childLoNodes);
101 } catch (DoesNotExistException e) {
102 } catch (Exception e) {
103 throw new AssemblyException("Error disassembling child los", e);
104 }
105
106
107 try {
108 List<BaseDTOAssemblyNode<?, ?>> categoryNodes = disassembleCategories(loDisplay, operation,contextInfo);
109 result.getChildNodes().addAll(categoryNodes);
110 } catch (Exception e) {
111 throw new AssemblyException("Error disassembling categories", e);
112 }
113
114 return result;
115 }
116
117 private List<BaseDTOAssemblyNode<?, ?>> disassembleCategories(
118 LoDisplayInfo loDisplay, NodeOperation operation,ContextInfo contextInfo) throws AssemblyException {
119
120 List<BaseDTOAssemblyNode<?, ?>> results = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
121
122
123 Set<String> currentCategoryIds = new HashSet<String>();
124
125 if (!NodeOperation.CREATE.equals(operation)) {
126 try {
127 List<LoCategoryInfo> categories = loService.getLoCategoriesByLo(loDisplay.getLoInfo().getId(), contextInfo);
128 for (LoCategoryInfo category : categories) {
129 currentCategoryIds.add(category.getId());
130 }
131
132 } catch (Exception e) {
133 throw new AssemblyException("Error getting categories", e);
134 }
135 }
136
137 for (LoCategoryInfo category : loDisplay.getLoCategoryInfoList()) {
138
139
140 if (NodeOperation.CREATE == operation
141 || (NodeOperation.UPDATE == operation && !currentCategoryIds.contains(category.getId()))) {
142
143
144 LoCategoryRelationInfo loCategoryRelation = new LoCategoryRelationInfo();
145 loCategoryRelation.setCategoryId(category.getId());
146 loCategoryRelation.setLoId(loDisplay.getLoInfo().getId());
147
148 BaseDTOAssemblyNode<LoDisplayInfo, LoCategoryRelationInfo> relationToAddNode = new BaseDTOAssemblyNode<LoDisplayInfo, LoCategoryRelationInfo>(null);
149 relationToAddNode.setNodeData(loCategoryRelation);
150 relationToAddNode.setOperation(NodeOperation.CREATE);
151 results.add(relationToAddNode);
152
153 currentCategoryIds.remove(category.getId());
154 } else if (NodeOperation.UPDATE == operation
155 && currentCategoryIds.contains(category.getId())) {
156 currentCategoryIds.remove(category.getId());
157 }
158 }
159
160 for(String categoryId:currentCategoryIds){
161
162 LoCategoryRelationInfo loCategoryRelation = new LoCategoryRelationInfo();
163 loCategoryRelation.setCategoryId(categoryId);
164 loCategoryRelation.setLoId(loDisplay.getLoInfo().getId());
165
166 BaseDTOAssemblyNode<LoDisplayInfo, LoCategoryRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<LoDisplayInfo, LoCategoryRelationInfo>(null);
167 relationToDeleteNode.setNodeData(loCategoryRelation);
168 relationToDeleteNode.setOperation(NodeOperation.DELETE);
169 results.add(relationToDeleteNode);
170 }
171
172 return results;
173 }
174
175 private List<BaseDTOAssemblyNode<?, ?>> disassembleChildLos(LoDisplayInfo loDisplay, NodeOperation operation, ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, AssemblyException, PermissionDeniedException{
176 List<BaseDTOAssemblyNode<?, ?>> results = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
177 Map<String,LoLoRelationInfo> currentLoRelations = new HashMap<String,LoLoRelationInfo>();
178
179 if (!NodeOperation.CREATE.equals(operation)) {
180 try {
181 List<LoLoRelationInfo> loRelations = loService.getLoLoRelationsByLoId(loDisplay.getLoInfo().getId(), contextInfo);
182 for (LoLoRelationInfo loRelation : loRelations) {
183
184
185 if(CourseAssemblerConstants.COURSE_LO_RELATION_INCLUDES.equals(loRelation.getTypeKey())&&
186 !loDisplay.getLoInfo().getId().equals(loRelation.getRelatedLoId())){
187 currentLoRelations.put(loRelation.getRelatedLoId(), loRelation);
188 }
189 }
190
191 } catch (Exception e) {
192 throw new AssemblyException("Error getting categories", e);
193 }
194 }
195
196
197 for (LoDisplayInfo childDisplay : loDisplay.getLoDisplayInfoList()) {
198
199
200
201
202
203 childDisplay.getLoInfo().setStateKey(loDisplay.getLoInfo().getStateKey());
204
205
206 if (NodeOperation.CREATE == operation
207 || (NodeOperation.UPDATE == operation && !currentLoRelations.containsKey(childDisplay.getLoInfo().getId()))) {
208
209
210
211 childDisplay.getLoInfo().setId(null);
212 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = this
213 .disassemble(childDisplay, NodeOperation.CREATE,contextInfo);
214 results.add(loNode);
215
216
217 LoLoRelationInfo relation = new LoLoRelationInfo();
218 relation.setLoId(loDisplay.getLoInfo().getId());
219 relation.setRelatedLoId(loNode.getNodeData().getId());
220
221 relation.setTypeKey(CourseAssemblerConstants.COURSE_LO_RELATION_INCLUDES);
222
223
224
225
226
227 relation.setStateKey(DtoConstants.STATE_ACTIVE);
228
229
230 BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo> relationNode = new BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo>(
231 null);
232 relationNode.setNodeData(relation);
233 relationNode.setOperation(NodeOperation.CREATE);
234
235 results.add(relationNode);
236 } else if (NodeOperation.UPDATE == operation
237 && currentLoRelations.containsKey(childDisplay.getLoInfo().getId())) {
238
239
240 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = this
241 .disassemble(childDisplay, NodeOperation.UPDATE,contextInfo);
242 results.add(loNode);
243
244
245
246 currentLoRelations.remove(childDisplay.getLoInfo().getId());
247 } else if (NodeOperation.DELETE == operation
248 && currentLoRelations.containsKey(childDisplay.getLoInfo().getId())) {
249
250
251 LoLoRelationInfo relationToDelete = currentLoRelations.get(childDisplay.getLoInfo().getId());
252 BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo>(
253 null);
254 relationToDeleteNode.setNodeData(relationToDelete);
255 relationToDeleteNode.setOperation(NodeOperation.DELETE);
256 results.add(relationToDeleteNode);
257
258 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = this
259 .disassemble(childDisplay, NodeOperation.DELETE,contextInfo);
260 results.add(loNode);
261
262
263
264 currentLoRelations.remove(childDisplay.getLoInfo().getId());
265 }
266 }
267
268
269
270 for (Entry<String, LoLoRelationInfo> entry : currentLoRelations.entrySet()) {
271
272
273 LoLoRelationInfo relationToDelete = entry.getValue();
274 BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<LoDisplayInfo, LoLoRelationInfo>(
275 null);
276 relationToDeleteNode.setNodeData(relationToDelete);
277 relationToDeleteNode.setOperation(NodeOperation.DELETE);
278 results.add(relationToDeleteNode);
279
280 LoInfo temploTODelete = loService.getLo(entry.getKey(), new ContextInfo());
281 LoDisplayInfo loDisplayToDelete = this.assemble(temploTODelete, null, false,contextInfo);
282 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = this.disassemble(loDisplayToDelete, NodeOperation.DELETE,contextInfo);
283 results.add(loNode);
284 }
285 return results;
286
287 }
288
289 public void setLoService(LearningObjectiveService loService) {
290 this.loService = loService;
291 }
292
293 public static class LoDisplayComparator implements Comparator<LoDisplayInfo>{
294 private static LoDisplayComparator instance = new LoDisplayComparator();
295 @Override
296 public int compare(LoDisplayInfo o1, LoDisplayInfo o2) {
297
298 String o1Sequence = null;
299 for(AttributeInfo attribute : o1.getLoInfo().getAttributes()){
300 if (attribute.getKey().equals(CourseAssemblerConstants.COURSE_LO_SEQUENCE)){
301 o1Sequence = attribute.getValue();
302 }
303 }
304
305 String o2Sequence = null;
306 for(AttributeInfo attribute : o2.getLoInfo().getAttributes()){
307 if (attribute.getKey().equals(CourseAssemblerConstants.COURSE_LO_SEQUENCE)){
308 o2Sequence = attribute.getValue();
309 }
310 }
311
312 if(o1Sequence!=null){
313 return o1Sequence.compareTo(o2Sequence);
314 }else if(o2Sequence!=null){
315 return -1;
316 }
317 return 0;
318 }
319 public static LoDisplayComparator getInstance() {
320 return instance;
321 }
322 }
323
324 }