View Javadoc

1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 1.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/ecl1.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.student.lum.service.assembler;
17  
18  import org.kuali.student.common.assembly.BaseDTOAssemblyNode;
19  import org.kuali.student.common.assembly.BaseDTOAssemblyNode.NodeOperation;
20  import org.kuali.student.common.assembly.data.AssemblyException;
21  import org.kuali.student.common.dto.DtoConstants;
22  import org.kuali.student.common.dto.RichTextInfo;
23  import org.kuali.student.common.exceptions.DoesNotExistException;
24  import org.kuali.student.common.exceptions.InvalidParameterException;
25  import org.kuali.student.common.exceptions.MissingParameterException;
26  import org.kuali.student.common.exceptions.OperationFailedException;
27  import org.kuali.student.lum.course.dto.LoDisplayInfo;
28  import org.kuali.student.lum.course.service.assembler.LoAssembler;
29  import org.kuali.student.lum.lo.dto.LoInfo;
30  import org.kuali.student.lum.lo.service.LearningObjectiveService;
31  import org.kuali.student.lum.lu.dto.CluLoRelationInfo;
32  import org.kuali.student.lum.lu.dto.CluResultInfo;
33  import org.kuali.student.lum.lu.dto.ResultOptionInfo;
34  import org.kuali.student.lum.lu.service.LuService;
35  
36  import java.util.ArrayList;
37  import java.util.Date;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.Map.Entry;
42  
43  /**
44   * This is a description of what this class does - jimt don't forget to fill this in.
45   *
46   * @author Kuali Rice Team (kuali-rice@googlegroups.com)
47   *
48   */
49  public class CluAssemblerUtils {
50      private LuService luService;
51      private LearningObjectiveService loService;
52      private LoAssembler loAssembler;
53  
54      public List<String> assembleCluResults(List<String> resultTypes, List<CluResultInfo> cluResults) throws AssemblyException{
55  		if(resultTypes==null){
56  			throw new AssemblyException("result types can not be null");
57  		}
58  		List<String> results = new ArrayList<String>();
59  		//Loop through all the CluResults to find those with the matching types
60  		for(CluResultInfo cluResult:cluResults){
61  			if(resultTypes.contains(cluResult.getType())){
62  				//Loop through all options and add to the list of Strings
63  				for(ResultOptionInfo resultOption: cluResult.getResultOptions()){
64  					results.add(resultOption.getResultComponentId());
65  				}
66  			}
67  		}
68  		return results;
69  	}
70  
71      public BaseDTOAssemblyNode<?, ?> disassembleCluResults(String cluId,
72  			String cluState, List<String> options, NodeOperation operation, String resultType,
73  			String resultsDescription, String resultDescription) throws AssemblyException {
74  		BaseDTOAssemblyNode<List<String>, CluResultInfo> cluResultNode = new BaseDTOAssemblyNode<List<String>, CluResultInfo>(null);
75  		if(resultType==null){
76  			throw new AssemblyException("resultType can not be null");
77  		}
78  
79  		// Get the current options and put them in a map of option type id/cluResult
80  		Map<String, ResultOptionInfo> currentResults = new HashMap<String, ResultOptionInfo>();
81  
82  		CluResultInfo cluResult = null;
83  
84          //TODO Check this for proper handling of multiple CluResultInfos?  
85  		//If this is not a create, lookup the results for this clu
86  		if (!NodeOperation.CREATE.equals(operation)) {
87  			try {
88  				List<CluResultInfo> cluResultList = luService.getCluResultByClu(cluId);
89  
90  				for (CluResultInfo currentResult : cluResultList) {
91  					if (resultType.equals(currentResult.getType())) {
92  						cluResult = currentResult;
93  						if(NodeOperation.DELETE.equals(operation)){
94  							//if this is a delete, then we only need the CluResultInfo
95  							cluResultNode.setOperation(NodeOperation.DELETE);
96  						}else{
97  							//Find all the Result options and store in a map for easy access later
98  							cluResultNode.setOperation(NodeOperation.UPDATE);
99  							
100 							for(ResultOptionInfo resultOption:currentResult.getResultOptions()){
101 								// Set the state of the result option so it appears in the KSLU_RSLT_OPT table
102 							    // States include Draft, Approved, Superseded etc.
103 							    resultOption.setState(cluState);
104 							    currentResults.put(resultOption.getResultComponentId(), resultOption);
105 							}
106 						}
107 					}
108 				}
109 			} catch (DoesNotExistException e) {
110 			} catch (InvalidParameterException e) {
111 				throw new AssemblyException("Error getting related " + resultsDescription, e);
112 			} catch (MissingParameterException e) {
113 				throw new AssemblyException("Error getting related " + resultsDescription, e);
114 			} catch (OperationFailedException e) {
115 				throw new AssemblyException("Error getting related " + resultsDescription, e);
116 			}
117 		}
118 
119 		//If this is a delete we don't need the result options, just the CluResultInfo
120 		if(!NodeOperation.DELETE.equals(operation)){
121 			if(cluResult == null){
122 				//Create a new resultInfo of the given type if one does not exist and set operation to Create
123 				cluResult = new CluResultInfo();
124 				cluResult.setCluId(cluId);
125 				cluResult.setState(cluState);
126 				cluResult.setType(resultType);
127 				RichTextInfo desc = new RichTextInfo();
128 				desc.setPlain(resultsDescription);
129 				cluResult.setDesc(desc);
130 				cluResult.setEffectiveDate(new Date());
131 				cluResultNode.setOperation(NodeOperation.CREATE);
132 			}
133 
134 			
135 			cluResult.setResultOptions(new ArrayList<ResultOptionInfo>());
136 
137             // Set the state of the result so it appears in the KSLU_CLU_RSLT table
138             // States include Draft, Approved, Superseded etc.
139 			cluResult.setState(cluState);
140 			
141 			// Loop through all the credit options in this clu
142 			for (String optionType : options) {
143 				if(currentResults.containsKey(optionType)){
144 					//If the option exists already copy it to the new list of result options
145 					ResultOptionInfo resultOptionInfo = currentResults.get(optionType);
146                     
147 					// Set the state of the result option so it appears in the KSLU_RSLT_OPT table
148                     // States include Draft, Approved, Superseded etc.
149 					resultOptionInfo.setState(cluState);
150 					cluResult.getResultOptions().add(resultOptionInfo);
151 				}else{
152 					//Otherwise create a new result option
153 					ResultOptionInfo resultOptionInfo = new ResultOptionInfo();
154 					RichTextInfo desc = new RichTextInfo();
155 					desc.setPlain(resultDescription);
156 					resultOptionInfo.setDesc(desc);
157 					resultOptionInfo.setResultComponentId(optionType);
158                     
159 					// Set the state of the result option so it appears in the KSLU_RSLT_OPT table
160                     // States include Draft, Approved, Superseded etc.
161                     resultOptionInfo.setState(cluState);
162 
163 					cluResult.getResultOptions().add(resultOptionInfo);
164 				}
165 			}
166 		}
167 
168 		cluResultNode.setNodeData(cluResult);
169 		return cluResultNode;
170 	}
171 
172     public List<LoDisplayInfo> assembleLos(String cluId, boolean shallowBuild) throws AssemblyException {
173         List<LoDisplayInfo> loInfos = new ArrayList<LoDisplayInfo>();
174         try {
175             List<CluLoRelationInfo> cluLoRelations = luService.getCluLoRelationsByClu(cluId);
176             for (CluLoRelationInfo cluLoRelation : cluLoRelations) {
177                 String loId = cluLoRelation.getLoId();
178                 LoInfo lo = loService.getLo(loId);
179                 loInfos.add(loAssembler.assemble(lo, null, shallowBuild));
180             }
181         } catch (Exception e) {
182             throw new AssemblyException("Error getting learning objectives", e);
183         }
184 
185         return loInfos;
186     }
187     
188 	public List<BaseDTOAssemblyNode<?, ?>> disassembleLos(String cluId, String cluState, List<LoDisplayInfo> loInfos,
189 			NodeOperation operation) throws AssemblyException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException{
190 		// TODO Auto-generated method stub
191 		List<BaseDTOAssemblyNode<?, ?>> results = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
192 
193 		// Get the current formats and put them in a map of format id/relation
194 		// id
195 		Map<String, CluLoRelationInfo> currentCluLoRelations = new HashMap<String, CluLoRelationInfo>();
196 		try {
197 			List<CluLoRelationInfo> cluLoRelations = luService.getCluLoRelationsByClu(cluId);
198 			for(CluLoRelationInfo cluLoRelation:cluLoRelations){
199 				if(CluAssemblerConstants.CLU_LO_CLU_SPECIFIC_RELATION.equals(cluLoRelation.getType())){
200 					currentCluLoRelations.put(cluLoRelation.getLoId(), cluLoRelation);
201 				}
202 			}
203 		} catch (DoesNotExistException e) {
204 		} catch (Exception e) {
205 			throw new AssemblyException("Error finding related Los", e);
206 		}
207 
208 		// Loop through all the los in this clu
209 		for(LoDisplayInfo loDisplay : loInfos){
210 
211 			// If this is a clu create/new lo update then all los will be created
212 		    if (NodeOperation.CREATE == operation
213 		            || (NodeOperation.UPDATE == operation &&  !currentCluLoRelations.containsKey(loDisplay.getLoInfo().getId()))) {
214 
215                 // the lo does not exist, so create
216                 // Assemble and add the lo
217 		    	loDisplay.getLoInfo().setId(null);
218 		    	loDisplay.getLoInfo().setState(cluState);
219                 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = loAssembler
220                         .disassemble(loDisplay, NodeOperation.CREATE);
221                 results.add(loNode);
222 
223                 // Create the relationship and add it as well
224                 CluLoRelationInfo relation = new CluLoRelationInfo();
225                 relation.setCluId(cluId);
226                 relation.setLoId(loNode.getNodeData().getId());
227                 relation.setType(CluAssemblerConstants.CLU_LO_CLU_SPECIFIC_RELATION);
228                 
229                 // Relations can be either Active or Suspended
230                 // For now, we set them all to Active
231                 // DO NOT use states like draft, superseded, etc for relations
232                 relation.setState(DtoConstants.STATE_ACTIVE);
233 
234                 BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo> relationNode = new BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo>(
235                         null);
236                 relationNode.setNodeData(relation);
237                 relationNode.setOperation(NodeOperation.CREATE);
238 
239                 results.add(relationNode);
240             } else if (NodeOperation.UPDATE == operation
241 					&& currentCluLoRelations.containsKey(loDisplay.getLoInfo().getId())) {
242 				// On update, we need to change the state of the LO to
243                 // match the state of the parent program
244                 loDisplay.getLoInfo().setState(cluState);
245                 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = loAssembler
246                 		.disassemble(loDisplay, NodeOperation.UPDATE);
247 				results.add(loNode);
248 
249 				// remove this entry from the map so we can tell what needs to
250 				// be deleted at the end
251 				currentCluLoRelations.remove(loDisplay.getLoInfo().getId());
252 			} else if (NodeOperation.DELETE == operation
253                     && currentCluLoRelations.containsKey(loDisplay.getLoInfo().getId())) {
254 
255                 // Delete the Format and its relation
256 				CluLoRelationInfo relationToDelete = currentCluLoRelations.get(loDisplay.getLoInfo().getId());
257                 BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo>(
258                         null);
259                 relationToDeleteNode.setNodeData(relationToDelete);
260                 relationToDeleteNode.setOperation(NodeOperation.DELETE);
261                 results.add(relationToDeleteNode);
262 
263                 BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = loAssembler
264         				.disassemble(loDisplay, NodeOperation.DELETE);
265                 results.add(loNode);
266 
267                 // remove this entry from the map so we can tell what needs to
268                 // be deleted at the end
269                 currentCluLoRelations.remove(loDisplay.getLoInfo().getId());
270 			}
271 		}
272 
273         // Now any leftover lo ids are no longer needed, so delete
274         // los and relations
275         for (Entry<String, CluLoRelationInfo> entry : currentCluLoRelations.entrySet()) {
276             // Create a new relation with the id of the relation we want to
277             // delete
278         	CluLoRelationInfo relationToDelete = entry.getValue();
279             BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<LoDisplayInfo, CluLoRelationInfo>(
280                     null);
281             relationToDeleteNode.setNodeData(relationToDelete);
282             relationToDeleteNode.setOperation(NodeOperation.DELETE);
283             results.add(relationToDeleteNode);
284 
285             LoInfo loToDelete = loService.getLo(entry.getKey());
286             LoDisplayInfo loDisplayToDelete = loAssembler.assemble(loToDelete, null, false);
287             BaseDTOAssemblyNode<LoDisplayInfo, LoInfo> loNode = loAssembler
288             		.disassemble(loDisplayToDelete, NodeOperation.DELETE);
289             results.add(loNode);
290         }
291 
292 		return results;
293 	}
294 
295     // Spring setters
296     public void setLuService(LuService luService) {
297         this.luService = luService;
298     }
299 
300     public void setLoService(LearningObjectiveService loService) {
301         this.loService = loService;
302     }
303 
304     public void setLoAssembler(LoAssembler loAssembler) {
305         this.loAssembler = loAssembler;
306     }
307 }