View Javadoc

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