1   package org.kuali.student.r2.lum.program.service.impl;
2   
3   import org.apache.log4j.Logger;
4   import org.kuali.student.common.conversion.util.R1R2ConverterUtil;
5   import org.kuali.student.r1.common.assembly.BOAssembler;
6   import org.kuali.student.r1.common.assembly.BaseDTOAssemblyNode;
7   import org.kuali.student.r1.common.assembly.BaseDTOAssemblyNode.NodeOperation;
8   import org.kuali.student.r1.common.assembly.BusinessServiceMethodInvoker;
9   import org.kuali.student.r1.common.dictionary.dto.DataType;
10  import org.kuali.student.r1.common.dictionary.dto.ObjectStructureDefinition;
11  import org.kuali.student.r1.common.dictionary.service.DictionaryService;
12  import org.kuali.student.r1.common.validator.ServerDateParser;
13  import org.kuali.student.r1.common.validator.ValidatorUtils;
14  import org.kuali.student.r1.core.statement.dto.ReqCompFieldInfo;
15  import org.kuali.student.r1.core.statement.dto.ReqComponentInfo;
16  import org.kuali.student.r1.core.statement.dto.StatementTreeViewInfo;
17  import org.kuali.student.r1.lum.statement.typekey.ReqComponentFieldTypes;
18  import org.kuali.student.r2.common.assembler.AssemblyException;
19  import org.kuali.student.r2.common.dto.ContextInfo;
20  import org.kuali.student.r2.common.dto.DtoConstants;
21  import org.kuali.student.r2.common.dto.StatusInfo;
22  import org.kuali.student.r2.common.dto.ValidationResultInfo;
23  import org.kuali.student.r2.common.exceptions.*;
24  import org.kuali.student.r2.core.search.dto.SearchRequestInfo;
25  import org.kuali.student.r2.core.search.dto.SearchResultInfo;
26  import org.kuali.student.r2.core.search.service.SearchManager;
27  import org.kuali.student.r2.common.util.constants.ProgramServiceConstants;
28  import org.kuali.student.r2.common.validator.Validator;
29  import org.kuali.student.r2.common.validator.ValidatorFactory;
30  import org.kuali.student.r2.core.atp.dto.AtpInfo;
31  import org.kuali.student.r2.core.atp.service.AtpService;
32  import org.kuali.student.r2.core.class1.type.dto.TypeInfo;
33  import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
34  import org.kuali.student.r2.lum.clu.dto.CluCluRelationInfo;
35  import org.kuali.student.r2.lum.clu.dto.CluInfo;
36  import org.kuali.student.r2.lum.clu.dto.CluSetInfo;
37  import org.kuali.student.r2.lum.clu.service.CluService;
38  import org.kuali.student.r2.lum.course.dto.LoDisplayInfo;
39  import org.kuali.student.r2.lum.course.infc.LoDisplay;
40  import org.kuali.student.r2.lum.course.service.impl.CourseServiceUtils;
41  import org.kuali.student.r2.lum.program.dto.*;
42  import org.kuali.student.r2.lum.program.service.ProgramService;
43  import org.kuali.student.r2.lum.program.service.assembler.CoreProgramAssembler;
44  import org.kuali.student.r2.lum.program.service.assembler.CredentialProgramAssembler;
45  import org.kuali.student.r2.lum.program.service.assembler.MajorDisciplineAssembler;
46  import org.kuali.student.r2.lum.program.service.assembler.ProgramAssemblerConstants;
47  import org.kuali.student.r2.lum.util.constants.CluServiceConstants;
48  import org.springframework.transaction.annotation.Transactional;
49  
50  import javax.jws.WebParam;
51  import java.util.ArrayList;
52  import java.util.Date;
53  import java.util.Iterator;
54  import java.util.List;
55  import org.kuali.student.r2.core.document.dto.RefDocRelationInfo;
56  import org.kuali.student.r2.core.document.service.DocumentService;
57  
58  public class ProgramServiceImpl implements ProgramService{
59  	final static Logger LOG = Logger.getLogger(ProgramServiceImpl.class);
60  
61      private CluService cluService;
62      private ValidatorFactory validatorFactory;
63      private BusinessServiceMethodInvoker programServiceMethodInvoker;
64      private DictionaryService dictionaryService;
65      private SearchManager searchManager;
66      private MajorDisciplineAssembler majorDisciplineAssembler;
67      private ProgramRequirementAssembler programRequirementAssembler;
68      private CredentialProgramAssembler credentialProgramAssembler;
69      private CoreProgramAssembler coreProgramAssembler;
70  
71      private AtpService atpService;
72      private DocumentService documentService;
73      
74  
75      @Override
76      @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
77  	public CredentialProgramInfo createCredentialProgram( String credentialProgramTypeKey,
78                                                            CredentialProgramInfo credentialProgramInfo,
79                                                            ContextInfo contextInfo) throws AlreadyExistsException,
80              DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
81  
82          checkForMissingParameter(credentialProgramInfo, "CredentialProgramInfo");
83  
84          
85          List<ValidationResultInfo> validationResults = validateCredentialProgram("OBJECT", credentialProgramInfo,contextInfo);
86          if (ValidatorUtils.hasErrors(validationResults)) {
87              throw new DataValidationErrorException("Validation error!", validationResults);
88          }
89  
90          try {
91              return processCredentialProgramInfo(credentialProgramInfo, NodeOperation.CREATE,contextInfo);
92          } catch (AssemblyException e) {
93              LOG.error("Error disassembling Credential Program", e);
94              throw new OperationFailedException("Error disassembling Credential Program");
95          }
96      }
97  
98      @Override
99      @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
100     public HonorsProgramInfo createHonorsProgram(String honorsProgramTypeKey,  HonorsProgramInfo honorsProgramInfo,
101                                                  ContextInfo contextInfo) throws AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException,
102             OperationFailedException, PermissionDeniedException {
103         throw new UnsupportedOperationException("createHonorsProgram");
104         
105     }
106 
107     @Override
108     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
109     public ProgramRequirementInfo createProgramRequirement( String programRequirementTypeKey,
110                                                             ProgramRequirementInfo programRequirementInfo,  ContextInfo contextInfo) throws AlreadyExistsException,
111             DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
112         checkForMissingParameter(programRequirementInfo, "programRequirementInfo");
113 
114         
115         List<ValidationResultInfo> validationResults = validateProgramRequirement("OBJECT", programRequirementInfo,contextInfo);
116         if (ValidatorUtils.hasErrors(validationResults)) {
117         	throw new DataValidationErrorException("Validation error!", validationResults);
118         }
119 
120         try {
121             return processProgramRequirement(programRequirementInfo, NodeOperation.CREATE,contextInfo);
122         } catch (AssemblyException e) {
123             LOG.error("Error disassembling Program Requirement", e);
124             throw new OperationFailedException("Error disassembling Program Requirement", e);
125         }
126     }
127 
128     @Override
129     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
130 	public MajorDisciplineInfo createMajorDiscipline( String majorDisciplineTypeKey,
131                                                       MajorDisciplineInfo majorDisciplineInfo,
132                                                       ContextInfo contextInfo) throws AlreadyExistsException,
133             DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
134 
135         checkForMissingParameter(majorDisciplineInfo, "MajorDisciplineInfo");
136 
137         
138         List<ValidationResultInfo> validationResults = validateMajorDiscipline("OBJECT", majorDisciplineInfo,contextInfo);
139         if (ValidatorUtils.hasErrors(validationResults)) {
140             throw new DataValidationErrorException("Validation error!", validationResults);
141         }
142 
143         try {
144             return processMajorDisciplineInfo(majorDisciplineInfo, NodeOperation.CREATE,contextInfo);
145         } catch (AssemblyException e) {
146             LOG.error("Error creating Major Discipline", e);
147             throw new OperationFailedException("Error creating Major Discipline");
148         }
149     }
150     
151     @Override
152 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
153 	public MajorDisciplineInfo createNewMajorDisciplineVersion(String majorDisciplineId,  String versionComment,
154                                                                ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException,
155             PermissionDeniedException, VersionMismatchException, DataValidationErrorException,ReadOnlyException {
156 		
157 		VersionDisplayInfo currentVersion = cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, majorDisciplineId,contextInfo);
158 		MajorDisciplineInfo originalMajorDiscipline = getMajorDiscipline(currentVersion.getId(),contextInfo);
159 
160 		
161 		CluInfo newVersionClu = cluService.createNewCluVersion(majorDisciplineId, versionComment,contextInfo);
162 
163 		try {
164 	        BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> results;
165 
166 	        
167 			majorDisciplineAssembler.assemble(newVersionClu, originalMajorDiscipline, true,contextInfo);
168 
169 			
170 			processCopy(originalMajorDiscipline, currentVersion.getId(),contextInfo);
171            
172             
173 			
174             List<String> programRequirementIds = originalMajorDiscipline.getProgramRequirements();
175             updateRequirementsState(programRequirementIds, DtoConstants.STATE_DRAFT,contextInfo);
176             
177 			
178 			results =  majorDisciplineAssembler.disassemble(originalMajorDiscipline, NodeOperation.UPDATE,contextInfo);
179 			
180 			
181 			programServiceMethodInvoker.invokeServiceCalls(results, contextInfo);
182 
183 			return results.getBusinessDTORef();
184 		} catch(AssemblyException e) {
185 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
186 		} catch (AlreadyExistsException e) {
187 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
188 		} catch (DependentObjectsExistException e) {
189 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
190 		} catch (CircularRelationshipException e) {
191 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
192 		} catch (UnsupportedActionException e) {
193 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
194 		} catch (CircularReferenceException e) {
195 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
196 		}
197 	}
198     
199     
200 
201 
202 
203 
204 
205 
206 
207 
208     private void updateRequirementsState(List<String> programRequirementIds, String newState,ContextInfo contextInfo) throws DoesNotExistException,
209         InvalidParameterException, MissingParameterException,
210         OperationFailedException, PermissionDeniedException,  VersionMismatchException, DataValidationErrorException  {
211 
212         
213 
214 
215 
216 
217 
218 
219         if (programRequirementIds != null) { 
220             for (String programRequirementId : programRequirementIds) {
221     
222                 
223                 ProgramRequirementInfo programRequirementInfo = getProgramRequirement(programRequirementId, contextInfo);
224     
225                 
226                 StatementTreeViewInfo statementTree = R1R2ConverterUtil.convert(programRequirementInfo.getStatement(), new StatementTreeViewInfo()) ;
227     
228                 
229                 updateStatementTreeViewInfoState(newState, statementTree);
230     
231                 
232                 programRequirementInfo.setStateKey(newState);
233     
234                 
235                 updateProgramRequirement(programRequirementInfo.getId(), programRequirementInfo.getTypeKey(), programRequirementInfo, contextInfo);
236     
237             }
238         }
239     }
240     
241     
242 
243 
244 
245 
246 
247 
248 
249 
250 
251     private static void updateStatementTreeViewInfoState(String state, StatementTreeViewInfo statementTreeViewInfo) {
252        
253 
254 
255 
256 
257 
258         
259         
260         statementTreeViewInfo.setState(state);
261          
262         
263         List<ReqComponentInfo> reqComponents = statementTreeViewInfo.getReqComponents();
264         
265         
266         for(Iterator<ReqComponentInfo> it = reqComponents.iterator(); it.hasNext();)
267             it.next().setState(state);
268         
269         
270         for(Iterator<StatementTreeViewInfo> itr = statementTreeViewInfo.getStatements().iterator(); itr.hasNext();)
271             updateStatementTreeViewInfoState(state, (StatementTreeViewInfo)itr.next());
272     }
273     
274 	
275 
276 
277 
278 
279 
280 
281 
282 	private void clearStatementTreeViewIdsRecursively(StatementTreeViewInfo statementTreeView,ContextInfo contextInfo) throws OperationFailedException{
283 		if(statementTreeView!=null){
284 			statementTreeView.setId(null);
285 			for(ReqComponentInfo reqComp:statementTreeView.getReqComponents()){
286 				reqComp.setId(null);
287 				for(ReqCompFieldInfo field:reqComp.getReqCompFields()){
288 					field.setId(null);
289 					
290 					if(ReqComponentFieldTypes.COURSE_CLUSET_KEY.getId().equals(field.getType())||
291 					   ReqComponentFieldTypes.PROGRAM_CLUSET_KEY.getId().equals(field.getType())||
292 					   ReqComponentFieldTypes.CLUSET_KEY.getId().equals(field.getType())){
293 						try {
294 							CluSetInfo cluSet = cluService.getCluSet(field.getValue(),contextInfo);
295 							cluSet.setId(null);
296 							
297 							if (cluSet.getMembershipQuery() != null){
298 								cluSet.getCluIds().clear();
299 								cluSet.getCluSetIds().clear();
300 							}
301 							cluSet = cluService.createCluSet(cluSet.getTypeKey(), cluSet,contextInfo);
302 							field.setValue(cluSet.getId());
303 						} catch (Exception e) {
304 							throw new OperationFailedException("Error copying clusets.", e);
305 						}
306 					}
307 					
308 				}
309 			}
310 			
311 			for(StatementTreeViewInfo child: statementTreeView.getStatements()){
312 				clearStatementTreeViewIdsRecursively(child,contextInfo);
313 			}
314 		}
315 	}
316 
317 	
318 
319 
320 
321 
322 
323 
324 
325 
326 
327 
328 
329 
330 
331 
332     private void processCopy(MajorDisciplineInfo majorDiscipline,String originalId,ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, AlreadyExistsException, DataValidationErrorException, VersionMismatchException, CircularRelationshipException,ReadOnlyException {
333 		
334     	majorDiscipline.setStartTerm(null);
335     	majorDiscipline.setEndTerm(null);
336     	majorDiscipline.setEndProgramEntryTerm(null);
337     	majorDiscipline.getAttributes().remove("endInstAdmitTerm");
338     	
339     	
340 		for(LoDisplayInfo lo:majorDiscipline.getLearningObjectives()){
341 			resetLoRecursively(lo);
342 		}
343 		
344 		if(majorDiscipline.getOrgCoreProgram()!=null){
345 			majorDiscipline.getOrgCoreProgram().setId(null);
346 		
347 			if(majorDiscipline.getOrgCoreProgram().getLearningObjectives()!=null){
348 				for(LoDisplay lo:majorDiscipline.getOrgCoreProgram().getLearningObjectives()){
349 					resetLoRecursively((LoDisplayInfo)lo);
350 				}
351 			}
352 		}
353 		
354 		for(ProgramVariationInfo variation:majorDiscipline.getVariations()){
355 			
356 	    	variation.setStartTerm(null);
357 	    	variation.setEndTerm(null);
358 	    	variation.setEndProgramEntryTerm(null);
359 	    	variation.getAttributes().remove("endInstAdmitTerm");
360 	    	
361 			
362 		   	String variationVersionIndId = variation.getVersion().getVersionIndId();
363 			CluInfo newVariationClu = cluService.createNewCluVersion(variationVersionIndId, "Variation version for MajorDiscipline version " + majorDiscipline.getVersion().getSequenceNumber(),contextInfo);
364 			
365 			
366 			CluCluRelationInfo relation = new CluCluRelationInfo();
367 	        relation.setCluId(majorDiscipline.getId());
368 	        relation.setRelatedCluId(newVariationClu.getId());
369 	        relation.setTypeKey(ProgramAssemblerConstants.HAS_PROGRAM_VARIATION);
370 	        
371 	        
372 	        
373 	        relation.setStateKey(DtoConstants.STATE_ACTIVE);
374 			cluService.createCluCluRelation(relation.getCluId(), relation.getRelatedCluId(), relation.getTypeKey(), relation,contextInfo);
375 	        
376 			
377 			variation.setId(newVariationClu.getId());
378 			variation.setMeta(newVariationClu.getMeta());
379 						
380 			
381 			variation.setStateKey(majorDiscipline.getStateKey());
382 			
383 			for(LoDisplay lo:variation.getLearningObjectives()){
384 				resetLoRecursively((LoDisplayInfo)lo);
385 			}
386 			
387 			copyProgramRequirements(variation.getProgramRequirements(),majorDiscipline.getStateKey(),contextInfo);
388 		}
389 		
390 		
391 		copyProgramRequirements(majorDiscipline.getProgramRequirements(),majorDiscipline.getStateKey(),contextInfo);
392 
393 		
394 		List<RefDocRelationInfo> docRelations = documentService.getRefDocRelationsByRef("kuali.org.RefObjectType.ProposalInfo", originalId, contextInfo);
395 		if(docRelations!=null){
396 			for(RefDocRelationInfo docRelation:docRelations){
397 				docRelation.setId(null);
398 				docRelation.setRefObjectId(majorDiscipline.getId());
399 				documentService.createRefDocRelation("kuali.org.RefObjectType.ProposalInfo", 
400                                         majorDiscipline.getId(), 
401                                         docRelation.getDocumentId(), 
402                                         docRelation.getTypeKey(), 
403                                         docRelation, contextInfo);
404 			}
405 		}
406 	}
407 
408 	private void processCopy(CredentialProgramInfo originaCredentialProgram,
409 			String originalId,ContextInfo contextInfo) throws OperationFailedException, AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException, PermissionDeniedException, DoesNotExistException,ReadOnlyException {
410 		
411 		originaCredentialProgram.setStartTerm(null);
412 		originaCredentialProgram.setEndTerm(null);
413 		originaCredentialProgram.setEndProgramEntryTerm(null);
414 		
415 		
416 		if (originaCredentialProgram.getLearningObjectives() != null){
417 			for(LoDisplay lo:originaCredentialProgram.getLearningObjectives()){
418 				resetLoRecursively((LoDisplayInfo)lo);
419 			}
420 		}
421 
422 		
423 		copyProgramRequirements(originaCredentialProgram.getProgramRequirements(),originaCredentialProgram.getStateKey(),contextInfo);
424 
425 		
426 		List<RefDocRelationInfo> docRelations = documentService.getRefDocRelationsByRef("kuali.org.RefObjectType.ProposalInfo", originalId, contextInfo);
427 		if(docRelations!=null){
428 			for(RefDocRelationInfo docRelation:docRelations){
429 				docRelation.setId(null);
430 				docRelation.setRefObjectId(originaCredentialProgram.getId());
431 				documentService.createRefDocRelation("kuali.org.RefObjectType.ProposalInfo", 
432                                         originaCredentialProgram.getId(), 
433                                         docRelation.getDocumentId(), 
434                                         docRelation.getTypeKey(), 
435                                         docRelation,
436                                         contextInfo);
437 			}
438 		}
439 	}
440     
441     private void processCopy(CoreProgramInfo originalCoreProgram, String originalId,ContextInfo contextInfo) throws OperationFailedException, AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException, PermissionDeniedException, DoesNotExistException, ReadOnlyException {
442 		
443     	originalCoreProgram.setStartTerm(null);
444     	originalCoreProgram.setEndTerm(null);
445     	originalCoreProgram.setEndProgramEntryTerm(null);
446 		
447     	
448 		for(LoDisplay lo:originalCoreProgram.getLearningObjectives()){
449 			resetLoRecursively((LoDisplayInfo)lo);
450 		}
451 		
452 		copyProgramRequirements(originalCoreProgram.getProgramRequirements(),originalCoreProgram.getStateKey(),contextInfo);
453 
454 		
455 		List<RefDocRelationInfo> docRelations = documentService.getRefDocRelationsByRef("kuali.org.RefObjectType.ProposalInfo", originalId, contextInfo);
456 		if(docRelations!=null){
457 			for(RefDocRelationInfo docRelation:docRelations){
458 				docRelation.setId(null);
459 				docRelation.setRefObjectId(originalCoreProgram.getId());
460 				documentService.createRefDocRelation("kuali.org.RefObjectType.ProposalInfo", 
461                                         originalCoreProgram.getId(), 
462                                         docRelation.getDocumentId(), 
463                                         docRelation.getTypeKey(), 
464                                         docRelation,
465                                         contextInfo);
466 			}
467 		}
468 	}
469     
470     
471 
472 
473 
474 
475 
476 
477 
478 
479 
480 
481 
482     private void copyProgramRequirements(List<String> originalProgramRequirementIds,String state,ContextInfo contextInfo) throws OperationFailedException, AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException, PermissionDeniedException, DoesNotExistException{
483 		if (originalProgramRequirementIds == null) {
484 		    return;
485 		}
486         
487         
488 		List<String> programRequirementIds = new ArrayList<String>(originalProgramRequirementIds);
489 		originalProgramRequirementIds.clear();
490 		
491 		for(String programRequirementId:programRequirementIds){
492 			
493 			ProgramRequirementInfo programRequirementInfo = getProgramRequirement(programRequirementId, contextInfo);
494 			
495 			programRequirementInfo.setId(null);
496 			
497 			programRequirementInfo.setStateKey(state);
498 			
499 			clearStatementTreeViewIdsRecursively(R1R2ConverterUtil.convert(programRequirementInfo.getStatement(), new StatementTreeViewInfo()),contextInfo);
500 			
501 			for(LoDisplayInfo lo:programRequirementInfo.getLearningObjectives()){
502 				resetLoRecursively(lo);
503 			}
504 			
505 			ProgramRequirementInfo createdProgramRequirement = createProgramRequirement(programRequirementInfo.getTypeKey(),programRequirementInfo,contextInfo);
506 			
507 			originalProgramRequirementIds.add(createdProgramRequirement.getId());
508 		}
509     }
510     
511 	
512 
513 
514 
515 	private void resetLoRecursively(LoDisplayInfo lo){
516 		lo.getLoInfo().setId(null);
517 		for(LoDisplayInfo nestedLo:lo.getLoDisplayInfoList()){
518 			resetLoRecursively(nestedLo);
519 		}
520 	}
521 
522 	@Override
523 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
524 	public StatusInfo setCurrentMajorDisciplineVersion(
525 			String majorDisciplineId, Date currentVersionStart,ContextInfo contextInfo)
526 			throws DoesNotExistException, InvalidParameterException,
527 			MissingParameterException, IllegalVersionSequencingException,
528 			OperationFailedException, PermissionDeniedException, DataValidationErrorException {
529 		StatusInfo status = cluService.setCurrentCluVersion(majorDisciplineId, currentVersionStart,contextInfo);
530 		
531 		
532 		List<ProgramVariationInfo> variationList = getVariationsByMajorDisciplineId(majorDisciplineId,contextInfo);
533 		for (ProgramVariationInfo variationInfo:variationList){
534 			String variationId = variationInfo.getId();
535 			
536 			
537 			if (variationInfo.getVersion().getCurrentVersionStart() == null){
538 				cluService.setCurrentCluVersion(variationId, currentVersionStart,contextInfo);
539 			}
540 		}
541 		
542 		return status;
543 	}
544 
545 	@Override
546     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
547 	public MinorDisciplineInfo createMinorDiscipline( String minorDisciplineTypeKey,
548                                                       MinorDisciplineInfo minorDisciplineInfo,  ContextInfo contextInfo) throws AlreadyExistsException,
549             DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
550         throw new UnsupportedOperationException("createMinorDiscipline");
551         
552     }
553 
554     @Override
555     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
556 	public StatusInfo deleteCredentialProgram(String credentialProgramId,  ContextInfo contextInfo)
557             throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
558 
559 
560 
561 
562 
563 
564 
565 
566 
567 
568 
569 
570     	throw new OperationFailedException("Deletion of CredentialProgram is not supported."); 
571     }
572 
573     @Override
574     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
575 	public StatusInfo deleteHonorsProgram( String honorsProgramId, ContextInfo contextInfo) throws DoesNotExistException,
576             InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
577         throw new UnsupportedOperationException("deleteHonorsProgram");
578         
579     }
580 
581     @Override
582     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
583 	public StatusInfo deleteMajorDiscipline(String majorDisciplineId,ContextInfo contextInfo)
584             throws DoesNotExistException, InvalidParameterException,
585             MissingParameterException, OperationFailedException,
586             PermissionDeniedException {
587 
588         try {
589             MajorDisciplineInfo majorDiscipline = getMajorDiscipline(majorDisciplineId,contextInfo);
590 
591             processMajorDisciplineInfo(majorDiscipline, NodeOperation.DELETE,contextInfo);
592 
593             return getStatus();
594 
595         } catch (AssemblyException e) {
596             LOG.error("Error disassembling MajorDiscipline", e);
597             throw new OperationFailedException("Error disassembling MajorDiscipline");
598         }
599     }
600 
601     @Override
602     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
603 	public StatusInfo deleteMinorDiscipline(String minorDisciplineId,ContextInfo contextInfo)
604             throws DoesNotExistException, InvalidParameterException,
605             MissingParameterException, OperationFailedException,
606             PermissionDeniedException {
607         throw new UnsupportedOperationException("deleteMinorDiscipline");
608         
609     }
610 
611     @Override
612     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
613 	public StatusInfo deleteProgramRequirement(String programRequirementId,ContextInfo contextInfo)
614             throws DoesNotExistException, InvalidParameterException,
615             MissingParameterException, OperationFailedException,
616             PermissionDeniedException {
617     	checkForMissingParameter(programRequirementId, "programRequirementId");
618         try {
619         	ProgramRequirementInfo programRequirement = getProgramRequirement(programRequirementId, contextInfo);
620 
621         	processProgramRequirement(programRequirement, NodeOperation.DELETE, contextInfo);
622 
623             return getStatus();
624 
625         } catch (AssemblyException e) {
626             LOG.error("Error disassembling MajorDiscipline", e);
627             throw new OperationFailedException("Error disassembling ProgramRequirement", e);
628         }
629 
630     }
631 
632     @Override
633     @Transactional(readOnly=true)
634     public CredentialProgramInfo getCredentialProgram(String credentialProgramId,ContextInfo contextInfo)
635             throws DoesNotExistException, InvalidParameterException,
636             MissingParameterException, OperationFailedException,
637             PermissionDeniedException {
638 
639     	CredentialProgramInfo credentialProgramInfo = null;
640 
641         try {
642             CluInfo clu = cluService.getClu(credentialProgramId,contextInfo);
643 
644             if ( ! ProgramAssemblerConstants.CREDENTIAL_PROGRAM_TYPES.contains(clu.getTypeKey()) ) {
645                 throw new DoesNotExistException("Specified CLU is not a Credential Program");
646             }
647 
648             credentialProgramInfo = credentialProgramAssembler.assemble(clu, null, false,contextInfo);
649         } catch (AssemblyException e) {
650             LOG.error("Error assembling CredentialProgram", e);
651             throw new OperationFailedException("Error assembling CredentialProgram");
652         }
653         return credentialProgramInfo;
654 
655 		
656         
657 
658 
659 
660 
661 
662     }
663 
664 
665 
666 
667 
668 
669 
670 
671 
672 
673 
674 
675 
676 
677 
678 
679 
680 
681 
682 
683 
684 
685 
686 
687     @Override
688     public HonorsProgramInfo getHonorsProgram(String honorsProgramId, ContextInfo contextInfo) throws DoesNotExistException,
689             InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
690         throw new UnsupportedOperationException("getHonorsProgram");
691         
692     }
693 
694     @Override
695     @Transactional(readOnly=true)
696     public MajorDisciplineInfo getMajorDiscipline(String majorDisciplineId,ContextInfo contextInfo)
697             throws DoesNotExistException, InvalidParameterException,
698             MissingParameterException, OperationFailedException,
699             PermissionDeniedException {
700 
701 
702         MajorDisciplineInfo majorDiscipline = null;
703 
704         try {
705             CluInfo clu = cluService.getClu(majorDisciplineId,contextInfo);
706             if ( ! ProgramAssemblerConstants.MAJOR_DISCIPLINE.equals(clu.getTypeKey()) ) {
707                 throw new DoesNotExistException("Specified CLU is not a Major Discipline");
708             }
709             majorDiscipline = majorDisciplineAssembler.assemble(clu, null, false,contextInfo);
710         } catch (AssemblyException e) {
711             LOG.error("Error assembling MajorDiscipline", e);
712             throw new OperationFailedException("Error assembling MajorDiscipline");
713         }
714         return majorDiscipline;
715 		
716         
717 
718 
719 
720 
721 
722 	}
723 
724 
725 
726 
727 
728 
729 
730 
731 
732 	@Override
733 	public MinorDisciplineInfo getMinorDiscipline(String minorDisciplineId,ContextInfo contextInfo)
734 			throws DoesNotExistException, InvalidParameterException,
735 			MissingParameterException, OperationFailedException,
736 			PermissionDeniedException {
737 	    throw new UnsupportedOperationException("getMinorDiscipline");
738 		
739 	}
740 
741 	@Override
742 	public List<String> getMinorsByCredentialProgramType(String programType,ContextInfo contextInfo)
743 			throws DoesNotExistException, InvalidParameterException,
744 			MissingParameterException, OperationFailedException {
745 	    throw new UnsupportedOperationException("getMinorsByCredentialProgramType");
746 		
747 	}
748 
749 	@Override
750     @Transactional(readOnly=true)
751 	public ProgramRequirementInfo getProgramRequirement(String programRequirementId, ContextInfo contextInfo) throws DoesNotExistException,
752 			InvalidParameterException, MissingParameterException,
753 			OperationFailedException, PermissionDeniedException
754 
755     {
756 
757 		checkForMissingParameter(programRequirementId, "programRequirementId");
758 
759 		CluInfo clu = cluService.getClu(programRequirementId,contextInfo);
760 		if (!ProgramAssemblerConstants.PROGRAM_REQUIREMENT.equals(clu.getTypeKey())) {
761 			throw new DoesNotExistException("Specified CLU is not a Program Requirement");
762 		}
763 		try {
764 			ProgramRequirementInfo progReqInfo = programRequirementAssembler.assemble(clu, null, false, contextInfo);
765 			return progReqInfo;
766 		} catch (AssemblyException e) {
767             LOG.error("Error assembling program requirement", e);
768             throw new OperationFailedException("Error assembling program requirement: " + e.getMessage(), e);
769 		}
770 	}
771 
772 	@Override
773     @Transactional(readOnly=true)
774 	public List<ProgramVariationInfo> getVariationsByMajorDisciplineId(
775             String majorDisciplineId, ContextInfo contextInfo) throws DoesNotExistException,
776 			InvalidParameterException, MissingParameterException,
777 			OperationFailedException {
778     	List<ProgramVariationInfo> pvInfos = new ArrayList<ProgramVariationInfo>();
779 
780     	try {
781     			List<CluInfo> clus = cluService.getRelatedClusByCluAndRelationType(majorDisciplineId, ProgramAssemblerConstants.HAS_PROGRAM_VARIATION,contextInfo);
782 
783 		        if(clus != null && clus.size() > 0){
784 		        	for(CluInfo clu : clus){
785 		        		ProgramVariationInfo pvInfo = majorDisciplineAssembler.getProgramVariationAssembler().assemble(clu, null, false,contextInfo);
786 		        		if(pvInfo != null){
787 		        			pvInfos.add(pvInfo);
788 		        		}
789 		        	}
790 		        }
791 		    } catch (AssemblyException e) {
792 		        LOG.error("Error assembling ProgramVariation", e);
793 		        throw new OperationFailedException("Error assembling ProgramVariation");
794 		    } catch (PermissionDeniedException e) {
795 				
796 				e.printStackTrace();
797 			}
798 
799         return pvInfos;
800     }
801 
802     @Override
803     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
804 	public CredentialProgramInfo updateCredentialProgram(
805 	        String credentialProgramId, CredentialProgramInfo credentialProgramInfo, ContextInfo contextInfo)
806             throws DataValidationErrorException, DoesNotExistException,
807             InvalidParameterException, MissingParameterException,
808             VersionMismatchException, OperationFailedException,
809             PermissionDeniedException {
810 
811         checkForMissingParameter(credentialProgramInfo, "CredentialProgramInfo");
812 
813         
814         List<ValidationResultInfo> validationResults = validateCredentialProgram("OBJECT", credentialProgramInfo,contextInfo);
815         if (ValidatorUtils.hasErrors(validationResults)) {
816             throw new DataValidationErrorException("Validation error!", validationResults);
817         }
818 
819         try {
820 
821             return processCredentialProgramInfo(credentialProgramInfo, NodeOperation.UPDATE,contextInfo);
822 
823         } catch (AssemblyException e) {
824             LOG.error("Error disassembling Credential Program", e);
825             throw new OperationFailedException("Error disassembling Credential Program");
826         }
827     }
828 
829 
830 
831 
832 
833 
834 
835 
836 
837 
838 
839 
840 
841     @Override
842     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
843 	public MajorDisciplineInfo updateMajorDiscipline(String majorDisciplineId,
844             MajorDisciplineInfo majorDisciplineInfo, ContextInfo contextInfo)
845             throws DataValidationErrorException, DoesNotExistException,
846             InvalidParameterException, MissingParameterException,
847             VersionMismatchException, OperationFailedException,
848             PermissionDeniedException {
849 
850         checkForMissingParameter(majorDisciplineInfo, "MajorDisciplineInfo");
851 
852         
853         List<ValidationResultInfo> validationResults = validateMajorDiscipline("OBJECT", majorDisciplineInfo,contextInfo);
854         if (ValidatorUtils.hasErrors(validationResults)) {
855             throw new DataValidationErrorException("Validation error!", validationResults);
856         }
857 
858         try {
859 
860             return processMajorDisciplineInfo(majorDisciplineInfo, NodeOperation.UPDATE,contextInfo);
861 
862         } catch (AssemblyException e) {
863             LOG.error("Error disassembling majorDiscipline", e);
864             throw new OperationFailedException("Error disassembling majorDiscipline");
865         }
866     }
867 
868     @Override
869     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
870 	public MinorDisciplineInfo updateMinorDiscipline(String minorDisciplineId, String minorDisciplineTypeKey, MinorDisciplineInfo minorDisciplineInfo, ContextInfo contextInfo)
871             throws DataValidationErrorException, DoesNotExistException,
872             InvalidParameterException, MissingParameterException,
873             VersionMismatchException, OperationFailedException,
874             PermissionDeniedException {
875         throw new UnsupportedOperationException("updateMinorDiscipline");
876         
877     }
878 
879     @Override
880     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
881 	public ProgramRequirementInfo updateProgramRequirement(String programRequirementId, String programRequirementTypeKey, 
882             ProgramRequirementInfo programRequirementInfo, ContextInfo contextInfo)
883             throws DataValidationErrorException, DoesNotExistException,
884             InvalidParameterException, MissingParameterException,
885             VersionMismatchException, OperationFailedException,
886             PermissionDeniedException {
887     	checkForMissingParameter(programRequirementInfo, "programRequirementInfo");
888         
889         List<ValidationResultInfo> validationResults = validateProgramRequirement("OBJECT", programRequirementInfo,contextInfo);
890         if (ValidatorUtils.hasErrors(validationResults)) {
891         	throw new DataValidationErrorException("Validation error!", validationResults);
892         }
893 
894         try {
895 			return processProgramRequirement(programRequirementInfo, NodeOperation.UPDATE,contextInfo);
896 		} catch (AssemblyException e) {
897 			throw new OperationFailedException("Unable to update ProgramRequirement", e);
898 		}
899     }
900 
901     @Override
902     public List<ValidationResultInfo> validateCredentialProgram(
903             String validationType, CredentialProgramInfo credentialProgramInfo,ContextInfo contextInfo)
904             throws InvalidParameterException,
905             MissingParameterException, OperationFailedException {
906 
907         List<ValidationResultInfo> validationResults = new ArrayList<ValidationResultInfo>();
908 
909             ObjectStructureDefinition objStructure = this.getObjectStructure(CredentialProgramInfo.class.getName());
910             Validator validator = validatorFactory.getValidator();
911             validationResults.addAll(validator.validateObject(credentialProgramInfo, objStructure,contextInfo));
912 
913 
914         return validationResults;
915     }
916 
917     @Override
918     public List<ValidationResultInfo> validateHonorsProgram(
919             String validationType, HonorsProgramInfo honorsProgramInfo,ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException {
920         throw new UnsupportedOperationException("validateHonorsProgram");
921         
922     }
923 
924     @Override
925     public List<ValidationResultInfo> validateMajorDiscipline(
926             String validationType, MajorDisciplineInfo majorDisciplineInfo,ContextInfo contextInfo)
927             throws InvalidParameterException,
928             MissingParameterException, OperationFailedException,PermissionDeniedException {
929 
930         List<ValidationResultInfo> validationResults = new ArrayList<ValidationResultInfo>();
931 
932             ObjectStructureDefinition objStructure = this.getObjectStructure(MajorDisciplineInfo.class.getName());
933             Validator validator = validatorFactory.getValidator();
934             validationResults.addAll(validator.validateObject(majorDisciplineInfo, objStructure,contextInfo));
935 
936         validateMajorDisciplineAtps(majorDisciplineInfo,validationResults,contextInfo);
937         return validationResults;
938     }
939 
940     @Override
941     public List<ValidationResultInfo> validateMinorDiscipline(
942             String validationType, MinorDisciplineInfo minorDisciplineInfo,ContextInfo contextInfo   )
943             throws InvalidParameterException,
944             MissingParameterException, OperationFailedException {
945         throw new UnsupportedOperationException("validateMinorDiscipline");
946         
947     }
948 
949     @Override
950     public List<ValidationResultInfo> validateProgramRequirement(
951             String validationType, ProgramRequirementInfo programRequirementInfo,ContextInfo contextInfo)
952             throws InvalidParameterException,
953             MissingParameterException, OperationFailedException {
954 
955         ObjectStructureDefinition objStructure = this.getObjectStructure(ProgramRequirementInfo.class.getName());
956         Validator validator = validatorFactory.getValidator();
957         List<ValidationResultInfo> validationResults = validator.validateObject(programRequirementInfo, objStructure,contextInfo);
958 
959         return validationResults;
960     }
961 
962 
963     @Override
964     public ObjectStructureDefinition getObjectStructure(String objectTypeKey) {
965         return dictionaryService.getObjectStructure(objectTypeKey);
966     }
967 
968 
969    @Override
970     public List<String> getObjectTypes() {
971         return dictionaryService.getObjectTypes();
972     }
973 
974     @Override
975     public List<TypeInfo> getSearchTypes( ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException {
976         throw new UnsupportedOperationException("getSearchTypes");
977     }
978 
979     @Override
980     public TypeInfo getSearchType(String searchTypeKey,  ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
981         throw new UnsupportedOperationException("getSearchType");
982     }
983 
984     @Override
985     public SearchResultInfo search(SearchRequestInfo searchRequestInfo,  ContextInfo contextInfo) throws MissingParameterException, OperationFailedException, PermissionDeniedException {
986         throw new UnsupportedOperationException("ProgramService.search");
987     }
988 
989     
990 
991 
992 
993 
994 
995 
996     private void checkForMissingParameter(Object param, String paramName)
997             throws MissingParameterException {
998         if (param == null) {
999             throw new MissingParameterException(paramName + " can not be null");
1000         }
1001     }
1002 
1003     
1004 
1005     private MajorDisciplineInfo processMajorDisciplineInfo(MajorDisciplineInfo majorDisciplineInfo, NodeOperation operation, ContextInfo contextInfo) throws AssemblyException {
1006 
1007         BaseDTOAssemblyNode<MajorDisciplineInfo, CluInfo> results = majorDisciplineAssembler.disassemble(majorDisciplineInfo, operation, contextInfo);
1008         invokeServiceCalls(results, contextInfo);
1009         return results.getBusinessDTORef();
1010     }
1011 
1012     private CredentialProgramInfo processCredentialProgramInfo(CredentialProgramInfo credentialProgramInfo, NodeOperation operation, ContextInfo contextInfo) throws AssemblyException {
1013 
1014         BaseDTOAssemblyNode<CredentialProgramInfo, CluInfo> results = credentialProgramAssembler.disassemble(credentialProgramInfo, operation, contextInfo);
1015         invokeServiceCalls(results, contextInfo);
1016         return results.getBusinessDTORef();
1017     }
1018 
1019     private ProgramRequirementInfo processProgramRequirement(ProgramRequirementInfo programRequirementInfo, NodeOperation operation, ContextInfo contextInfo) throws AssemblyException {
1020     	BOAssembler<ProgramRequirementInfo, CluInfo> passAlong;
1021         BaseDTOAssemblyNode<ProgramRequirementInfo, CluInfo> results = programRequirementAssembler.disassemble(programRequirementInfo, operation, contextInfo);
1022         invokeServiceCalls(results, contextInfo);
1023         return results.getBusinessDTORef();
1024     }
1025 
1026 	private void invokeServiceCalls(BaseDTOAssemblyNode<?, CluInfo> results, ContextInfo contextInfo) throws AssemblyException{
1027         
1028         try {
1029             programServiceMethodInvoker.invokeServiceCalls(results, contextInfo);
1030         } catch (AssemblyException e) {
1031         	throw e;
1032         } catch (Exception e) {
1033             throw new AssemblyException(e);
1034         }
1035     }
1036 
1037     
1038 
1039     public void setCluService(CluService cluService) {
1040         this.cluService = cluService;
1041     }
1042 
1043     public CluService getCluService() {
1044 		return cluService;
1045 	}
1046 
1047 	public void setDictionaryService(DictionaryService dictionaryService) {
1048         this.dictionaryService = dictionaryService;
1049     }
1050 
1051     public DictionaryService getDictionaryService() {
1052 		return dictionaryService;
1053 	}
1054 
1055     public void setSearchManager(SearchManager searchManager) {
1056         this.searchManager = searchManager;
1057     }
1058     
1059 	public SearchManager getSearchManager() {
1060 		return searchManager;
1061 	}
1062 
1063 	public void setMajorDisciplineAssembler(MajorDisciplineAssembler majorDisciplineAssembler) {
1064         this.majorDisciplineAssembler = majorDisciplineAssembler;
1065     }
1066 
1067 	public MajorDisciplineAssembler getMajorDisciplineAssembler() {
1068 		return majorDisciplineAssembler;
1069 	}
1070 
1071 	public void setCredentialProgramAssembler(
1072 			CredentialProgramAssembler credentialProgramAssembler) {
1073 		this.credentialProgramAssembler = credentialProgramAssembler;
1074 	}
1075 
1076 	public CredentialProgramAssembler getCredentialProgramAssembler() {
1077 		return credentialProgramAssembler;
1078 	}
1079 
1080 	public void setProgramRequirementAssembler(ProgramRequirementAssembler programRequirementAssembler) {
1081         this.programRequirementAssembler = programRequirementAssembler;
1082     }
1083 
1084     public ProgramRequirementAssembler getProgramRequirementAssembler() {
1085 		return programRequirementAssembler;
1086 	}
1087 
1088 	public void setProgramServiceMethodInvoker(BusinessServiceMethodInvoker serviceMethodInvoker) {
1089         this.programServiceMethodInvoker = serviceMethodInvoker;
1090     }
1091 
1092     public BusinessServiceMethodInvoker getProgramServiceMethodInvoker() {
1093 		return programServiceMethodInvoker;
1094 	}
1095 
1096 	public void setValidatorFactory(ValidatorFactory validatorFactory) {
1097         this.validatorFactory = validatorFactory;
1098     }
1099 
1100 	public ValidatorFactory getValidatorFactory() {
1101 		return validatorFactory;
1102 	}
1103 	
1104 	public void setCoreProgramAssembler(CoreProgramAssembler coreProgramAssembler) {
1105 		this.coreProgramAssembler = coreProgramAssembler;
1106 	}
1107 
1108 	public CoreProgramAssembler getCoreProgramAssembler() {
1109 		return coreProgramAssembler;
1110 	}
1111 
1112 	private StatusInfo getStatus(){
1113         StatusInfo status = new StatusInfo();
1114         status.setSuccess(true);
1115         return status;
1116 	}
1117 
1118     private CoreProgramInfo processCoreProgramInfo(CoreProgramInfo coreProgramInfo, NodeOperation operation,ContextInfo contextInfo) throws AssemblyException, InvalidParameterException, MissingParameterException, DoesNotExistException, OperationFailedException, PermissionDeniedException {
1119         BaseDTOAssemblyNode<CoreProgramInfo, CluInfo> results = coreProgramAssembler.disassemble(coreProgramInfo, operation, contextInfo);
1120         invokeServiceCalls(results, contextInfo);
1121         return results.getBusinessDTORef();
1122     }
1123 
1124     @Override
1125     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1126 	public CoreProgramInfo createCoreProgram(String coreProgramTypeKey, CoreProgramInfo coreProgramInfo,ContextInfo contextInfo) throws AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, DoesNotExistException {
1127         checkForMissingParameter(coreProgramInfo, "CoreProgramInfo");
1128         
1129         
1130         List<ValidationResultInfo> validationResults = validateCoreProgram("OBJECT", coreProgramInfo, contextInfo );
1131         if (ValidatorUtils.hasErrors(validationResults)) {
1132             throw new DataValidationErrorException("Validation error!", validationResults);
1133         }
1134 
1135         try {
1136             return processCoreProgramInfo(coreProgramInfo, NodeOperation.CREATE,contextInfo);
1137         } catch (AssemblyException e) {
1138             LOG.error("Error disassembling CoreProgram", e);
1139             throw new OperationFailedException("Error disassembling CoreProgram");
1140         }
1141     }
1142 
1143 	@Override
1144 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1145 	public CoreProgramInfo createNewCoreProgramVersion(
1146 			String coreProgramId, String versionComment,ContextInfo contextInfo)
1147 			throws DoesNotExistException, InvalidParameterException,
1148 			MissingParameterException, OperationFailedException,
1149 			PermissionDeniedException, VersionMismatchException,
1150 			DataValidationErrorException, ReadOnlyException {
1151 		
1152 		VersionDisplayInfo currentVersion = cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, coreProgramId,contextInfo);
1153 		CoreProgramInfo originalCoreProgram = getCoreProgram(currentVersion.getId(),contextInfo);
1154 
1155 		
1156 		CluInfo newVersionClu = cluService.createNewCluVersion(coreProgramId, versionComment,contextInfo);
1157 
1158 		try {
1159 	        BaseDTOAssemblyNode<CoreProgramInfo, CluInfo> results;
1160 
1161 	        
1162 			coreProgramAssembler.assemble(newVersionClu, originalCoreProgram, true, contextInfo);
1163 			
1164 			
1165 			processCopy(originalCoreProgram, currentVersion.getId(),contextInfo);
1166 
1167 			
1168 			results = coreProgramAssembler.disassemble(originalCoreProgram, NodeOperation.UPDATE, contextInfo);
1169 
1170 			
1171 			programServiceMethodInvoker.invokeServiceCalls(results, contextInfo);
1172 
1173 			return results.getBusinessDTORef();
1174 		} catch(AssemblyException e) {
1175 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1176 		} catch (AlreadyExistsException e) {
1177 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1178 		} catch (DependentObjectsExistException e) {
1179 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1180 		} catch (CircularRelationshipException e) {
1181 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1182 		} catch (UnsupportedActionException e) {
1183 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1184 		} catch (CircularReferenceException e) {
1185 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1186 		}
1187 	}
1188     
1189 
1190 
1191 	@Override
1192     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1193 	public StatusInfo deleteCoreProgram(String coreProgramId, ContextInfo contextInfo) throws DoesNotExistException,
1194             InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException{
1195 
1196 
1197 
1198 
1199 
1200 
1201 
1202 
1203 
1204 
1205 
1206     	throw new OperationFailedException("Deletion of CoreProgram is not supported."); 
1207     }
1208 
1209     @Override
1210     @Transactional(readOnly=true)
1211     public CoreProgramInfo getCoreProgram(String coreProgramId,ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
1212     	CoreProgramInfo coreProgramInfo = null;
1213 
1214         try {
1215             CluInfo clu = cluService.getClu(coreProgramId,contextInfo);
1216             if ( ! ProgramAssemblerConstants.CORE_PROGRAM.equals(clu.getTypeKey()) ) {
1217                 throw new DoesNotExistException("Specified CLU is not a CoreProgram");
1218             }
1219             coreProgramInfo = coreProgramAssembler.assemble(clu, null, false, contextInfo);
1220         } catch (AssemblyException e) {
1221             LOG.error("Error assembling CoreProgram", e);
1222             throw new OperationFailedException("Error assembling CoreProgram");
1223         }
1224         return coreProgramInfo;
1225 		
1226         
1227 
1228 
1229 
1230 
1231 
1232     }
1233 
1234     @Override
1235     @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1236 	public CoreProgramInfo updateCoreProgram( String coreProgramId,  String coreProgramTypeKey,
1237                                               CoreProgramInfo coreProgramInfo,  ContextInfo contextInfo) throws DataValidationErrorException, DoesNotExistException,
1238             InvalidParameterException, MissingParameterException, VersionMismatchException, OperationFailedException, PermissionDeniedException{
1239         checkForMissingParameter(coreProgramInfo, "CoreProgramInfo");
1240         
1241         
1242         List<ValidationResultInfo> validationResults = validateCoreProgram("OBJECT", coreProgramInfo,contextInfo);
1243         if (ValidatorUtils.hasErrors(validationResults)) {
1244             throw new DataValidationErrorException("Validation error!", validationResults);
1245         }
1246 
1247         try {
1248 
1249             return processCoreProgramInfo(coreProgramInfo, NodeOperation.UPDATE,contextInfo);
1250 
1251         } catch (AssemblyException e) {
1252             LOG.error("Error disassembling CoreProgram", e);
1253             throw new OperationFailedException("Error disassembling CoreProgram");
1254         }
1255     }
1256 
1257     @Override
1258     public List<ValidationResultInfo> validateCoreProgram( String validationType,  CoreProgramInfo coreProgramInfo,
1259                                                            ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException{
1260         List<ValidationResultInfo> validationResults = new ArrayList<ValidationResultInfo>();
1261 
1262 	        ObjectStructureDefinition objStructure = this.getObjectStructure(CoreProgramInfo.class.getName());
1263 	        Validator validator = validatorFactory.getValidator();
1264             validationResults.addAll(validator.validateObject(coreProgramInfo, objStructure,contextInfo));
1265 
1266         return validationResults;
1267     }
1268         
1269         
1270 	@Override
1271 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1272 	public CredentialProgramInfo createNewCredentialProgramVersion( String credentialProgramId,
1273                                                                     String versionComment,
1274                                                                     ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException,
1275             PermissionDeniedException, VersionMismatchException, DataValidationErrorException, ReadOnlyException {
1276 		
1277 		VersionDisplayInfo currentVersion = cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, credentialProgramId,contextInfo);
1278 		CredentialProgramInfo originaCredentialProgram = getCredentialProgram(currentVersion.getId(),contextInfo);
1279 
1280 		
1281 		CluInfo newVersionClu = cluService.createNewCluVersion(credentialProgramId, versionComment,contextInfo);
1282 
1283 		try {
1284 
1285 	        BaseDTOAssemblyNode<CredentialProgramInfo, CluInfo> results;
1286 
1287 	        
1288 	        
1289 			credentialProgramAssembler.assemble(newVersionClu, originaCredentialProgram, true, contextInfo);
1290 
1291 			
1292 
1293 			processCopy(originaCredentialProgram, currentVersion.getId(),contextInfo);
1294 
1295 			
1296 			results = credentialProgramAssembler.disassemble(originaCredentialProgram, NodeOperation.UPDATE, contextInfo);
1297 
1298 			
1299 			programServiceMethodInvoker.invokeServiceCalls(results, contextInfo);
1300 			
1301 			
1302 			return results.getBusinessDTORef();
1303 		} catch(AssemblyException e) {
1304 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1305 		} catch (AlreadyExistsException e) {
1306 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1307 		} catch (DependentObjectsExistException e) {
1308 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1309 		} catch (CircularRelationshipException e) {
1310 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1311 		} catch (UnsupportedActionException e) {
1312 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1313 		} catch (CircularReferenceException e) {
1314 			throw new OperationFailedException("Error creating new MajorDiscipline version",e);
1315 		}
1316 	}
1317 
1318 
1319 	@Override
1320 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1321 	public StatusInfo setCurrentCoreProgramVersion( String coreProgramId,  Date currentVersionStart,
1322                                                     ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, IllegalVersionSequencingException,
1323             OperationFailedException, PermissionDeniedException, DataValidationErrorException{
1324 		StatusInfo status = cluService.setCurrentCluVersion(coreProgramId, currentVersionStart,contextInfo);
1325 		
1326 		return status;
1327 	}
1328 
1329 	@Override
1330 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
1331 	public StatusInfo setCurrentCredentialProgramVersion( String credentialProgramId,  Date currentVersionStart,
1332                                                           ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, IllegalVersionSequencingException,
1333             OperationFailedException, PermissionDeniedException, DataValidationErrorException {
1334 		StatusInfo status = cluService.setCurrentCluVersion(credentialProgramId, currentVersionStart,contextInfo);
1335 		
1336 		return status;
1337 	}
1338 
1339 	@Override
1340     @Transactional(readOnly=true)
1341 	public VersionDisplayInfo getCurrentVersion(String refObjectTypeURI,
1342 			String refObjectId,ContextInfo contextInfo) throws DoesNotExistException,
1343 			InvalidParameterException, MissingParameterException,
1344 			OperationFailedException, PermissionDeniedException {
1345 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1346 			return cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId,contextInfo);
1347 		}
1348 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1349 	}
1350 
1351 	@Override
1352     @Transactional(readOnly=true)
1353 	public VersionDisplayInfo getCurrentVersionOnDate(String refObjectTypeURI,
1354                                                       String refObjectId, Date date, ContextInfo contextInfo) throws DoesNotExistException,
1355 			InvalidParameterException, MissingParameterException,
1356 			OperationFailedException, PermissionDeniedException {
1357 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1358 			return cluService.getCurrentVersionOnDate(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId, date,contextInfo);
1359 		}
1360 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1361 	}
1362 
1363 	@Override
1364     @Transactional(readOnly=true)
1365 	public VersionDisplayInfo getFirstVersion(String refObjectTypeURI,
1366                                               String refObjectId, ContextInfo contextInfo) throws DoesNotExistException,
1367 			InvalidParameterException, MissingParameterException,
1368 			OperationFailedException, PermissionDeniedException {
1369 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1370 			return cluService.getFirstVersion(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId,contextInfo);
1371 		}
1372 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1373 
1374 	}
1375 
1376 	@Override
1377     @Transactional(readOnly=true)
1378 	public VersionDisplayInfo getLatestVersion(String refObjectTypeURI,
1379                                                String refObjectId, ContextInfo contextInfo) throws DoesNotExistException,
1380 			InvalidParameterException, MissingParameterException,
1381 			OperationFailedException, PermissionDeniedException {
1382 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1383 			return cluService.getLatestVersion(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId,contextInfo);
1384 		}
1385 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1386 
1387 	}
1388 
1389 	@Override
1390     @Transactional(readOnly=true)
1391 	public VersionDisplayInfo getVersionBySequenceNumber(
1392             String refObjectTypeURI, String refObjectId, Long sequence, ContextInfo contextInfo)
1393 			throws DoesNotExistException, InvalidParameterException,
1394 			MissingParameterException, OperationFailedException,
1395 			PermissionDeniedException {
1396 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1397 			return cluService.getVersionBySequenceNumber(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId, sequence,contextInfo);
1398 		}
1399 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1400 	}
1401 
1402 	@Override
1403     @Transactional(readOnly=true)
1404 	public List<VersionDisplayInfo> getVersions(String refObjectTypeURI,
1405 			String refObjectId,ContextInfo contextInfo) throws DoesNotExistException,
1406 			InvalidParameterException, MissingParameterException,
1407 			OperationFailedException, PermissionDeniedException {
1408 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1409 			return cluService.getVersions(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId,contextInfo);
1410 		}
1411 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1412 	}
1413 
1414 	@Override
1415     @Transactional(readOnly=true)
1416 	public List<VersionDisplayInfo> getVersionsInDateRange(
1417             String refObjectTypeURI, String refObjectId, Date from, Date to, ContextInfo contextInfo)
1418 			throws DoesNotExistException, InvalidParameterException,
1419 			MissingParameterException, OperationFailedException,
1420 			PermissionDeniedException {
1421 		if(ProgramServiceConstants.PROGRAM_NAMESPACE_MAJOR_DISCIPLINE_URI.equals(refObjectTypeURI)){
1422 			return cluService.getVersionsInDateRange(CluServiceConstants.CLU_NAMESPACE_URI, refObjectId, from, to,contextInfo);
1423 		}
1424 		throw new InvalidParameterException("Object type: " + refObjectTypeURI + " is not known to this implementation");
1425 	}
1426 
1427 	public void setAtpService(AtpService atpService) {
1428 		this.atpService = atpService;
1429 	}
1430 
1431 	public AtpService getAtpService() {
1432 		return atpService;
1433 	}
1434 
1435 	private void validateMajorDisciplineAtps(MajorDisciplineInfo majorDisciplineInfo, List<ValidationResultInfo> validationResults,ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
1436 		String startTerm = majorDisciplineInfo.getStartTerm();
1437 
1438         String endInstAdmitTerm = majorDisciplineInfo.getAttributeValue("endInstAdmitTerm");
1439 		if(endInstAdmitTerm != null) {
1440             compareAtps(startTerm, endInstAdmitTerm, validationResults, "End Inst Admin Term", "endInstAdmitTerm",contextInfo);
1441 		}
1442 		if(!isEmpty(majorDisciplineInfo.getEndProgramEntryTerm())){
1443 			compareAtps(startTerm, majorDisciplineInfo.getEndTerm(), validationResults, "End Program Entry Term", "endProgramEntryTerm",contextInfo);
1444 		}
1445 		
1446 		if(!isEmpty(majorDisciplineInfo.getEndTerm())){
1447 			compareAtps(startTerm, majorDisciplineInfo.getEndTerm(), validationResults, "End Program Enroll Term", "endTerm",contextInfo);
1448 		}		
1449 		
1450 		List<ProgramVariationInfo> variations = majorDisciplineInfo.getVariations();
1451 		if(variations != null && !variations.isEmpty()){
1452 			int idx = 0;
1453 			for(ProgramVariationInfo variation : variations){
1454 				validateVariationAtps(variation, validationResults, idx,contextInfo);
1455 				idx ++;
1456 			}
1457 		}
1458 	}
1459 	
1460 	
1461 	private void validateVariationAtps(ProgramVariationInfo programVariationInfo, List<ValidationResultInfo> validationResults, int idx,ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException,PermissionDeniedException{
1462 		
1463 		String startTerm = programVariationInfo.getStartTerm();
1464         String endInstAdmitTerm = programVariationInfo.getAttributeValue("endInstAdmitTerm");
1465 		if(endInstAdmitTerm != null) {
1466             compareAtps(startTerm, endInstAdmitTerm, validationResults, "End Inst Admin Term",  "variations/" + idx + "/endInstAdmitTerm",contextInfo);
1467 		}
1468 	
1469 		if(!isEmpty(programVariationInfo.getEndProgramEntryTerm())){
1470 			compareAtps(startTerm, programVariationInfo.getEndProgramEntryTerm(), validationResults, "End Program Entry Term", "variations/" + idx + "/endProgramEntryTerm",contextInfo);
1471 		}
1472 		
1473 		if(!isEmpty(programVariationInfo.getEndTerm())){
1474 			compareAtps(startTerm, programVariationInfo.getEndTerm(), validationResults, "End Program Enroll Term", "variations/" + idx + "/endTerm",contextInfo);
1475 		}
1476 	}
1477 	
1478 	private AtpInfo getAtpInfo(String atpKey,ContextInfo contextInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException,PermissionDeniedException{
1479 		if(atpKey==null){
1480 			return null;
1481 		}
1482 		return atpService.getAtp(atpKey, contextInfo);
1483 	}
1484 	
1485 	private void compareAtps(String aptKey1, String aptKey2, List<ValidationResultInfo> validationResults, String field, String path,ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException{
1486 		AtpInfo atpInfo1 = null;
1487 		AtpInfo atpInfo2 = null;
1488 		
1489 		try{
1490 			atpInfo1 = getAtpInfo(aptKey1,contextInfo);
1491 			atpInfo2 = getAtpInfo(aptKey2,contextInfo);
1492 		}catch(DoesNotExistException e){}
1493 		
1494 		if(atpInfo1 != null && atpInfo1 != null){
1495 			if(atpInfo1.getStartDate()!= null && atpInfo2.getStartDate() != null){			
1496 				boolean compareResult = ValidatorUtils.compareValues(atpInfo2.getStartDate(), atpInfo1.getStartDate(), DataType.DATE, "greater_than_equal", true, new ServerDateParser());
1497 				if(!compareResult){
1498 					ValidationResultInfo vri = new ValidationResultInfo();
1499 					vri.setElement(path);
1500 					vri.setError(field + " should be greater than Start Term");
1501 					validationResults.add(vri);
1502 				}
1503 			}
1504 		}
1505 			
1506 	}
1507 	
1508 	private boolean isEmpty(String value){
1509 		return value == null || (value != null && "".equals(value));
1510 	}
1511 
1512 	public void setDocumentService(DocumentService documentService) {
1513 		this.documentService = documentService;
1514 	}
1515 
1516 	public DocumentService getDocumentService() {
1517 		return documentService;
1518 	}
1519 
1520 	@Override
1521 	public List<CredentialProgramInfo> getCredentialProgramsByIds(
1522 			List<String> credentialProgramIds, ContextInfo contextInfo)
1523 			throws DoesNotExistException, InvalidParameterException,
1524 			MissingParameterException, OperationFailedException,
1525 			PermissionDeniedException {
1526 	    throw new UnsupportedOperationException("getCredentialProgramsByIds");
1527 		
1528 	}
1529 
1530 	@Override
1531 	public List<MajorDisciplineInfo> getMajorDisciplinesByIds(
1532 			List<String> majorDisciplineIds, ContextInfo contextInfo)
1533 			throws DoesNotExistException, InvalidParameterException,
1534 			MissingParameterException, OperationFailedException,
1535 			PermissionDeniedException {
1536 	    throw new UnsupportedOperationException("getMajorDisciplinesByIds");
1537 		
1538 	}
1539 
1540 	@Override
1541 	public List<String> getMajorDisciplineIdsByCredentialProgramType(
1542 			String programType, ContextInfo contextInfo)
1543 			throws DoesNotExistException, InvalidParameterException,
1544 			MissingParameterException, OperationFailedException {
1545 	    throw new UnsupportedOperationException("getMajorDisciplineIdsByCredentialProgramType");
1546 		
1547 	}
1548 
1549 	@Override
1550 	public List<HonorsProgramInfo> getHonorsProgramsByIds(
1551 			List<String> honorsProgramIds, ContextInfo contextInfo)
1552 			throws DoesNotExistException, InvalidParameterException,
1553 			MissingParameterException, OperationFailedException,
1554 			PermissionDeniedException {
1555 	    throw new UnsupportedOperationException("getHonorsProgramsByIds");
1556 		
1557 	}
1558 
1559 	@Override
1560 	public List<String> getHonorProgramIdsByCredentialProgramType(
1561 			String programType, ContextInfo contextInfo)
1562 			throws DoesNotExistException, InvalidParameterException,
1563 			MissingParameterException, OperationFailedException {
1564 	    throw new UnsupportedOperationException("getHonorProgramIdsByCredentialProgramType");
1565 		
1566 	}
1567 
1568 	@Override
1569 	public HonorsProgramInfo updateHonorsProgram(String honorsProgramId,
1570 			String honorsProgramTypeKey, HonorsProgramInfo honorsProgramInfo,
1571 			ContextInfo contextInfo) throws DataValidationErrorException,
1572 			DoesNotExistException, InvalidParameterException,
1573 			MissingParameterException, VersionMismatchException,
1574 			OperationFailedException, PermissionDeniedException {
1575 	    throw new UnsupportedOperationException("updateHonorsProgram");
1576 		
1577 	}
1578 
1579 	@Override
1580 	public List<CoreProgramInfo> getCoreProgramsByIds(
1581 			List<String> coreProgramIds, ContextInfo contextInfo)
1582 			throws DoesNotExistException, InvalidParameterException,
1583 			MissingParameterException, OperationFailedException,
1584 			PermissionDeniedException {
1585 	    throw new UnsupportedOperationException("getCoreProgramsByIds");
1586 		
1587 	}
1588 
1589 	@Override
1590 	public List<ProgramRequirementInfo> getProgramRequirementsByIds(
1591 			List<String> programRequirementIds, ContextInfo contextInfo)
1592 			throws DoesNotExistException, InvalidParameterException,
1593 			MissingParameterException, OperationFailedException,
1594 			PermissionDeniedException {
1595 	    throw new UnsupportedOperationException("getProgramRequirementsByIds");
1596 		
1597 	}
1598 
1599 	@Override
1600 	public List<ProgramVariationInfo> getProgramVariationsByMajorDiscipline(
1601 			String majorDisciplineId, ContextInfo contextInfo)
1602 			throws DoesNotExistException, InvalidParameterException,
1603 			MissingParameterException, OperationFailedException {
1604 	    throw new UnsupportedOperationException("getProgramVariationsByMajorDiscipline");
1605 		
1606 	}
1607 
1608 }