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.program.service.assembler;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.apache.log4j.Logger;
23  import org.kuali.student.common.assembly.BOAssembler;
24  import org.kuali.student.common.assembly.BaseDTOAssemblyNode;
25  import org.kuali.student.common.assembly.BaseDTOAssemblyNode.NodeOperation;
26  import org.kuali.student.common.assembly.data.AssemblyException;
27  import org.kuali.student.common.dto.AmountInfo;
28  import org.kuali.student.common.dto.DtoConstants;
29  import org.kuali.student.common.exceptions.DataValidationErrorException;
30  import org.kuali.student.common.exceptions.DoesNotExistException;
31  import org.kuali.student.common.exceptions.InvalidParameterException;
32  import org.kuali.student.common.exceptions.MissingParameterException;
33  import org.kuali.student.common.exceptions.OperationFailedException;
34  import org.kuali.student.lum.course.service.assembler.CourseAssembler;
35  import org.kuali.student.lum.lu.dto.CluCluRelationInfo;
36  import org.kuali.student.lum.lu.dto.CluInfo;
37  import org.kuali.student.lum.lu.service.LuService;
38  import org.kuali.student.lum.program.dto.CoreProgramInfo;
39  import org.kuali.student.lum.program.dto.MajorDisciplineInfo;
40  import org.kuali.student.lum.program.dto.ProgramVariationInfo;
41  import org.kuali.student.lum.service.assembler.CluAssemblerUtils;
42  
43  
44  /**
45   * @author KS TODO - Much of this should be shared with ProgramVariationAssembler (and probably other Program Assemblers to
46   *         come). AssemblerUtils?
47   */
48  public class MajorDisciplineAssembler implements BOAssembler<MajorDisciplineInfo, CluInfo> {
49      final static Logger LOG = Logger.getLogger(CourseAssembler.class);
50  
51      private LuService luService;
52  
53      private ProgramVariationAssembler programVariationAssembler;
54      private CoreProgramAssembler coreProgramAssembler;
55      private CluAssemblerUtils cluAssemblerUtils;
56      private ProgramAssemblerUtils programAssemblerUtils;
57  
58      @Override
59      public MajorDisciplineInfo assemble(CluInfo clu, MajorDisciplineInfo majorDiscipline, boolean shallowBuild) throws AssemblyException {
60          MajorDisciplineInfo mdInfo = (null != majorDiscipline) ? majorDiscipline : new MajorDisciplineInfo();
61  
62          // Copy all the data from the clu to the majordiscipline
63          programAssemblerUtils.assembleBasics(clu, mdInfo);
64          programAssemblerUtils.assembleIdentifiers(clu, mdInfo);
65          programAssemblerUtils.assembleBasicAdminOrgs(clu, mdInfo);
66          programAssemblerUtils.assembleFullOrgs(clu, mdInfo);
67          programAssemblerUtils.assembleAtps(clu, mdInfo);
68          programAssemblerUtils.assembleLuCodes(clu, mdInfo);
69  
70          mdInfo.setIntensity((null != clu.getIntensity()) ? clu.getIntensity().getUnitType() : null);
71          mdInfo.setStdDuration(clu.getStdDuration());
72          mdInfo.setPublishedInstructors(clu.getInstructors());
73          mdInfo.setCampusLocations(clu.getCampusLocations());        
74          mdInfo.setAccreditingAgencies(clu.getAccreditations());
75          mdInfo.setEffectiveDate(clu.getEffectiveDate());
76          mdInfo.setDescr(clu.getDescr());
77          mdInfo.setVersionInfo(clu.getVersionInfo());
78          mdInfo.setNextReviewPeriod(clu.getNextReviewPeriod());
79  
80          if (!shallowBuild) {
81          	programAssemblerUtils.assembleRequirements(clu, mdInfo);
82              mdInfo.setCredentialProgramId(programAssemblerUtils.getCredentialProgramID(clu.getId()));
83              mdInfo.setResultOptions(programAssemblerUtils.assembleResultOptions(clu.getId()));
84              mdInfo.setLearningObjectives(cluAssemblerUtils.assembleLos(clu.getId(), shallowBuild));
85              mdInfo.setVariations(assembleVariations(clu.getId(), shallowBuild));
86              mdInfo.setOrgCoreProgram(assembleCoreProgram(clu.getId(), shallowBuild));
87              programAssemblerUtils.assemblePublications(clu, mdInfo);
88          }
89          
90         return mdInfo;
91      }
92  
93      private CoreProgramInfo assembleCoreProgram(String cluId, boolean shallowBuild) throws AssemblyException {
94          CoreProgramInfo coreProgramInfo = null;
95          try {
96              List<CluInfo> corePrograms = luService.getRelatedClusByCluId(cluId, ProgramAssemblerConstants.HAS_CORE_PROGRAM);
97              // TODO - is it an error if there's more than one core program?
98              if (corePrograms.size() == 1) {
99                  coreProgramInfo = coreProgramAssembler.assemble(corePrograms.get(0), null, shallowBuild);
100             } else if (corePrograms.size() > 1) {
101                 throw new AssemblyException(new DataValidationErrorException("MajorDiscipline has more than one associated Core Program"));
102             }
103         } catch (Exception e) {
104             throw new AssemblyException(e);
105         }
106         return coreProgramInfo;
107     }
108 
109     private List<ProgramVariationInfo> assembleVariations(String cluId, boolean shallowBuild) throws AssemblyException {
110         List<ProgramVariationInfo> variations = new ArrayList<ProgramVariationInfo>();
111 
112         try {
113         	Map<String, CluCluRelationInfo> currentRelations = null;
114         	currentRelations = programAssemblerUtils.getCluCluActiveRelations(cluId, ProgramAssemblerConstants.HAS_PROGRAM_VARIATION);
115         	
116         	if(currentRelations != null && !currentRelations.isEmpty()){
117         		for (String variationId : currentRelations.keySet()) {
118         			CluInfo variationClu = luService.getClu(variationId);
119         			variations.add(programVariationAssembler.assemble(variationClu, null, shallowBuild));
120         		}
121         	}
122         } catch (Exception e) {
123             throw new AssemblyException(e);
124         }
125         return variations;
126     }
127 
128     @Override
129     public BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> disassemble(MajorDisciplineInfo major, NodeOperation operation) throws AssemblyException {
130 		if (major == null) {
131 		    LOG.error("Major for  disassemble is null!");
132 			throw new AssemblyException("Major cannot be null");
133 		}
134 
135         //TODO   IDs for objects w/o ids
136 
137 		BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result = new BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo>(
138 				this);
139 		
140 		CluInfo clu;
141 		try {
142 			clu = (NodeOperation.UPDATE == operation) ? luService.getClu(major.getId()) : new CluInfo();
143         } catch (Exception e) {
144 			throw new AssemblyException("Error getting existing learning unit during major update", e);
145         } 
146         
147         boolean stateChanged = NodeOperation.UPDATE == operation && major.getState() != null && !major.getState().equals(clu.getState());
148         
149         programAssemblerUtils.disassembleBasics(clu, major);
150         if (major.getId() == null)
151             major.setId(clu.getId());
152         programAssemblerUtils.disassembleLuCodes(clu, major, operation);
153         programAssemblerUtils.disassembleAdminOrgs(clu, major, operation);
154         programAssemblerUtils.disassembleAtps(clu, major, operation);
155         programAssemblerUtils.disassembleIdentifiers(clu, major, operation);
156         programAssemblerUtils.disassemblePublications(clu, major, operation, result);
157         
158         if(major.getProgramRequirements() != null && !major.getProgramRequirements().isEmpty()) {
159         	programAssemblerUtils.disassembleRequirements(clu, major, operation, result, stateChanged);        	
160         }
161 
162         if (major.getVariations() != null && !major.getVariations().isEmpty()) {
163             try {
164 				disassembleVariations(major, operation, result);
165 			} catch (Exception e) {
166 				throw new AssemblyException("Error diassembling Variations during major update", e);
167 			} 
168         }
169         if (major.getOrgCoreProgram() != null ) {
170             disassembleCoreProgram(major, operation, result);
171         }
172         if (major.getCredentialProgramId() != null) {
173             disassembleCredentialProgram(major, operation, result);
174         }
175         if (major.getResultOptions() != null) {
176             disassembleResultOptions(major, operation, result);
177         }
178         if (major.getLearningObjectives() != null) {
179             disassembleLearningObjectives(major, operation, result);
180         }
181 
182         AmountInfo intensity = new AmountInfo();
183         intensity.setUnitType(major.getIntensity());
184 		clu.setIntensity(intensity);
185         clu.setStdDuration(major.getStdDuration());
186         clu.setInstructors(major.getPublishedInstructors());
187 
188         clu.setNextReviewPeriod(major.getNextReviewPeriod());
189         clu.setEffectiveDate(major.getEffectiveDate());
190 
191         clu.setCampusLocations(major.getCampusLocations());
192         clu.setDescr(major.getDescr());
193 
194         clu.setAccreditations(major.getAccreditingAgencies());
195         clu.setNextReviewPeriod(major.getNextReviewPeriod());
196         clu.setState(major.getState());
197 
198 		// Add the Clu to the result
199 		result.setNodeData(clu);
200 		result.setOperation(operation);
201 		result.setBusinessDTORef(major);
202 
203     	return result;
204     }
205 
206     private void disassembleLearningObjectives(MajorDisciplineInfo major, NodeOperation operation, BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result) throws AssemblyException {
207         try {
208             List<BaseDTOAssemblyNode<?, ?>> loResults = cluAssemblerUtils.disassembleLos(major.getId(), major.getState(),  major.getLearningObjectives(), operation);
209             if (loResults != null) {
210                 result.getChildNodes().addAll(loResults);
211             }
212         } catch (DoesNotExistException e) {
213         } catch (Exception e) {
214             throw new AssemblyException("Error while disassembling los", e);
215         }
216     }
217 
218     private void disassembleResultOptions(MajorDisciplineInfo major, NodeOperation operation, BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result) throws AssemblyException {
219         //TODO Check for ProgramAssemblerConstants.CERTIFICATE_RESULTS too
220         
221         BaseDTOAssemblyNode<?, ?> degreeResults = cluAssemblerUtils.disassembleCluResults(
222                 major.getId(), major.getState(), major.getResultOptions(), operation, ProgramAssemblerConstants.DEGREE_RESULTS, "Result options", "Result option");
223         if (degreeResults != null) {
224             result.getChildNodes().add(degreeResults);
225         }
226     }
227 
228     private void disassembleCredentialProgram(MajorDisciplineInfo major, NodeOperation operation, BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result) throws AssemblyException {
229 
230         List<BaseDTOAssemblyNode<?,?>> credentialResults;
231         try {
232             credentialResults = programAssemblerUtils.disassembleCredentialProgram(major, operation, ProgramAssemblerConstants.HAS_MAJOR_PROGRAM);
233             if (credentialResults != null) {
234                 result.getChildNodes().addAll(credentialResults);
235             }
236         } catch (Exception e) {
237             throw new AssemblyException("Error while disassembling Credential program", e);
238         }
239     }
240 
241     private void disassembleVariations(MajorDisciplineInfo major, NodeOperation operation, BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result) throws AssemblyException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
242     	Map<String, CluCluRelationInfo> currentRelations = null;
243     	List<BaseDTOAssemblyNode<?, ?>> nodes = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
244     	
245     	if (!NodeOperation.CREATE.equals(operation)){
246     		currentRelations = programAssemblerUtils.getCluCluActiveRelations(major.getId(), ProgramAssemblerConstants.HAS_PROGRAM_VARIATION);
247     	}
248     	
249     	// Loop through all the variations in this MD
250         for (ProgramVariationInfo variation : major.getVariations()) {
251             BaseDTOAssemblyNode<?,?> variationNode;
252             variation.setState(major.getState());
253             try {
254 	            if (NodeOperation.UPDATE.equals(operation) && variation.getId() != null
255 						&& (currentRelations != null && currentRelations.containsKey(variation.getId()))) {
256 	                // If the relationship already exists update it
257 	                // remove this entry from the map so we can tell what needs to be deleted at the end
258 	            	variationNode = programVariationAssembler.disassemble(variation, operation);
259 	            	if (variationNode != null) nodes.add(variationNode);
260 	            	currentRelations.remove(variation.getId());  
261 	            } else if (!NodeOperation.DELETE.equals(operation)) {
262 					// the variation does not exist, so create variation & cluclurelation
263 	            	variationNode = programVariationAssembler.disassemble(variation, NodeOperation.CREATE);
264 	            	if (variationNode != null) nodes.add(variationNode);
265 					programAssemblerUtils.addCreateRelationNode(major.getId(), variation.getId(), ProgramAssemblerConstants.HAS_PROGRAM_VARIATION, nodes);
266 				}
267             } catch (Exception e) {
268                 throw new AssemblyException("Error while disassembling Variation", e);
269             } 
270         }
271         
272         // Now any leftover variation ids are no longer needed, so suspend them
273         if(currentRelations != null && currentRelations.size() > 0){
274         	programAssemblerUtils.addSuspendedRelationNodes(currentRelations, nodes);  	
275         	addInactivateVariationNodes(currentRelations, nodes);
276         }
277 
278         result.getChildNodes().addAll(nodes);
279     }
280 
281     private void addInactivateVariationNodes(Map<String, CluCluRelationInfo> currentRelations, List<BaseDTOAssemblyNode<?, ?>> nodes) throws AssemblyException{
282     	for (String variationId : currentRelations.keySet()) {
283 			CluInfo variationClu;
284 			try {
285 				variationClu = luService.getClu(variationId);
286 				ProgramVariationInfo delVariation = programVariationAssembler.assemble(variationClu, null, true);
287 				delVariation.setState(DtoConstants.STATE_SUSPENDED);
288 				BaseDTOAssemblyNode<?,?> variationNode = programVariationAssembler.disassemble(delVariation , NodeOperation.UPDATE);
289 				if (variationNode != null) nodes.add(variationNode);
290 			} catch (Exception e) {
291 				throw new AssemblyException("Error while disassembling variation, deactivateVariations", e);
292 			}
293     	}
294     }
295     
296     private void disassembleCoreProgram(MajorDisciplineInfo major, NodeOperation operation, BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> result) throws AssemblyException {
297 
298         BaseDTOAssemblyNode<?,?> coreResults;
299         try {
300         	major.getOrgCoreProgram().setState(major.getState());
301             coreResults = coreProgramAssembler.disassemble(major.getOrgCoreProgram(), operation);
302             if (coreResults != null) {
303                 result.getChildNodes().add(coreResults);
304             }
305         } catch (Exception e) {
306             throw new AssemblyException("Error while disassembling Core program", e);
307         }
308     }
309 
310     // Setters for Spring
311     public void setLuService(LuService luService) {
312         this.luService = luService;
313     }
314 
315 	public void setProgramVariationAssembler(ProgramVariationAssembler programVariationAssembler) {
316         this.programVariationAssembler = programVariationAssembler;
317     }
318 
319     public ProgramVariationAssembler getProgramVariationAssembler() {
320         return programVariationAssembler;
321     }
322 
323     public void setCoreProgramAssembler(CoreProgramAssembler coreProgramAssembler) {
324         this.coreProgramAssembler = coreProgramAssembler;
325     }
326 
327     public void setCluAssemblerUtils(CluAssemblerUtils cluAssemblerUtils) {
328         this.cluAssemblerUtils = cluAssemblerUtils;
329     }
330 
331     public void setProgramAssemblerUtils(ProgramAssemblerUtils programAssemblerUtils) {
332         this.programAssemblerUtils = programAssemblerUtils;
333     }
334 }