View Javadoc

1   package org.kuali.student.lum.lu.ui.course.server.gwt;
2   
3   import java.util.List;
4   
5   import org.apache.commons.beanutils.PropertyUtils;
6   import org.apache.log4j.Logger;
7   import org.kuali.student.common.assembly.data.Data;
8   import org.kuali.student.common.dto.CurrencyAmountInfo;
9   import org.kuali.student.common.dto.DtoConstants;
10  import org.kuali.student.common.exceptions.AlreadyExistsException;
11  import org.kuali.student.common.exceptions.CircularRelationshipException;
12  import org.kuali.student.common.exceptions.DataValidationErrorException;
13  import org.kuali.student.common.exceptions.DependentObjectsExistException;
14  import org.kuali.student.common.exceptions.DoesNotExistException;
15  import org.kuali.student.common.exceptions.InvalidParameterException;
16  import org.kuali.student.common.exceptions.MissingParameterException;
17  import org.kuali.student.common.exceptions.OperationFailedException;
18  import org.kuali.student.common.exceptions.PermissionDeniedException;
19  import org.kuali.student.common.exceptions.UnsupportedActionException;
20  import org.kuali.student.common.exceptions.VersionMismatchException;
21  import org.kuali.student.common.ui.client.service.DataSaveResult;
22  import org.kuali.student.common.ui.server.gwt.DataService;
23  import org.kuali.student.core.proposal.dto.ProposalInfo;
24  import org.kuali.student.core.proposal.service.ProposalService;
25  import org.kuali.student.core.statement.dto.ReqCompFieldInfo;
26  import org.kuali.student.core.statement.dto.ReqComponentInfo;
27  import org.kuali.student.core.statement.dto.StatementTreeViewInfo;
28  import org.kuali.student.core.statement.service.StatementService;
29  import org.kuali.student.lum.course.dto.ActivityInfo;
30  import org.kuali.student.lum.course.dto.CourseCrossListingInfo;
31  import org.kuali.student.lum.course.dto.CourseFeeInfo;
32  import org.kuali.student.lum.course.dto.CourseInfo;
33  import org.kuali.student.lum.course.dto.CourseJointInfo;
34  import org.kuali.student.lum.course.dto.CourseRevenueInfo;
35  import org.kuali.student.lum.course.dto.CourseVariationInfo;
36  import org.kuali.student.lum.course.dto.FormatInfo;
37  import org.kuali.student.lum.course.dto.LoDisplayInfo;
38  import org.kuali.student.lum.course.service.CourseService;
39  import org.kuali.student.lum.lrc.dto.ResultComponentInfo;
40  import org.kuali.student.lum.lu.LUConstants;
41  import org.kuali.student.lum.lu.dto.AffiliatedOrgInfo;
42  import org.kuali.student.lum.lu.dto.CluSetInfo;
43  import org.kuali.student.lum.lu.service.LuService;
44  import org.kuali.student.lum.statement.typekey.ReqComponentFieldTypes;
45  import org.springframework.transaction.annotation.Transactional;
46  @Transactional(noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
47  public class CopyCourseServiceImpl {
48  	final static Logger LOG = Logger.getLogger(CopyCourseServiceImpl.class);
49  	
50  	private DataService courseDataService;
51  	private DataService courseProposalDataService;
52  	private CourseService courseService;
53  	private LuService luService;
54  	private StatementService statementService;
55  	private ProposalService proposalService;
56  	
57  	private String defaultDocumentType=LUConstants.PROPOSAL_TYPE_COURSE_CREATE;
58  	private String defaultState=DtoConstants.STATE_DRAFT;
59  	
60  	private List<String> ignoreProperties;
61  	
62  	public DataSaveResult createCopyCourse(String originalCluId) throws Exception {
63  		//Copy the course and use the data service to return
64  		CourseInfo copiedCourse = copyCourse(originalCluId);
65  		
66  		DataSaveResult result = new DataSaveResult();
67  		result.setValue(courseDataService.getData(copiedCourse.getId()));
68  		return result;
69  	}
70  
71  	public DataSaveResult createCopyCourseProposal(String originalProposalId) throws Exception {
72  		//Copy the proposal and use the data service to return
73  		ProposalInfo copiedProposal = copyProposal(originalProposalId);
74  		
75  		//Grab the data object so it is transformed
76  		Data data = courseProposalDataService.getData(copiedProposal.getId());
77  		
78  		//Save it so that it goes through the filters and creates workflow
79  		return courseProposalDataService.saveData(data);
80  	}
81  	
82  	private CourseInfo copyCourse(String originalCluId) throws Exception{
83  		//Copy the course
84  		return copyCourse(originalCluId, null, defaultState, ignoreProperties, statementService, luService, courseService);
85  	}
86  	private ProposalInfo copyProposal(String originalProposalId) throws Exception{
87  		try {
88  			//Get the original Proposal
89  			ProposalInfo originalProposal = proposalService.getProposal(originalProposalId);
90  			
91  			//Copy the course from the original Proposal
92  			String originalCluId = originalProposal.getProposalReference().get(0);
93  			CourseInfo copiedCourse = copyCourse(originalCluId);
94  			
95  			//Clear ids and set the reference to the copied course
96  			originalProposal.setId(null);
97  			originalProposal.setWorkflowId(null);
98  			originalProposal.setState(defaultState);
99  			originalProposal.setType(defaultDocumentType);
100 			originalProposal.getProposalReference().set(0, copiedCourse.getId());
101 			originalProposal.getProposerOrg().clear();
102 			originalProposal.getProposerPerson().clear();
103             originalProposal.setName(null);
104 			
105 			//Create the proposal
106 			ProposalInfo copiedProposal = proposalService.createProposal(defaultDocumentType, originalProposal);
107 			
108 			return copiedProposal;
109 			
110 		} catch (Exception e) {
111 			LOG.error("Error copying proposal id:" + originalProposalId, e);
112 			throw e;
113 		}
114 	}
115 
116 	private void resetIds(CourseInfo course) {
117 		//Clear/Reset Joint info ids
118 		for(CourseJointInfo joint:course.getJoints()){
119 			joint.setRelationId(null);
120 		}
121 		//Clear Los
122 		for(LoDisplayInfo lo:course.getCourseSpecificLOs()){
123 			resetLoRecursively(lo);
124 		}
125 		//Clear format/activity ids
126 		for(FormatInfo format:course.getFormats()){
127 			format.setId(null);
128 			for(ActivityInfo activity:format.getActivities()){
129 				activity.setId(null);
130 			}
131 		}
132 		//Clear result component ids
133 		for(ResultComponentInfo result:course.getCreditOptions()){
134 			result.setId(null);
135 		}
136 		//Clear cross listing ids
137 		for(CourseCrossListingInfo crossListing:course.getCrossListings()){
138 			crossListing.setId(null);
139 		}
140 		//Clear Expenditures
141 		for(AffiliatedOrgInfo orgInfo:course.getExpenditure().getAffiliatedOrgs()){
142 			orgInfo.setId(null);
143 		}
144 		//Clear Fees
145 		for(CourseFeeInfo fee:course.getFees()){
146 			fee.setId(null);
147 			for(CurrencyAmountInfo feeAmount:fee.getFeeAmounts()){
148 				feeAmount.setId(null);
149 			}
150 		}
151 		//Clear revenue
152 		for(CourseRevenueInfo revenue:course.getRevenues()){
153 			revenue.setId(null);
154 			for(AffiliatedOrgInfo orgInfo:revenue.getAffiliatedOrgs()){
155 				orgInfo.setId(null);
156 			}
157 		}
158 		//Clear variation ids
159 		for(CourseVariationInfo variation:course.getVariations()){
160 			variation.setId(null);
161 		}
162 	}
163 
164 	private void resetLoRecursively(LoDisplayInfo lo){
165 		//Clear out all the Lo ids recursively
166 		lo.getLoInfo().setId(null);
167 		for(LoDisplayInfo nestedLo:lo.getLoDisplayInfoList()){
168 			resetLoRecursively(nestedLo);
169 		}
170 	}
171 
172 	private void clearStatementTreeViewIds(
173 			List<StatementTreeViewInfo> statementTreeViews, String newState, LuService luService) throws OperationFailedException {
174 		//Clear out all statement ids recursively
175 		for(StatementTreeViewInfo statementTreeView:statementTreeViews){
176 			clearStatementTreeViewIdsRecursively(statementTreeView, newState, luService);
177 		}
178 	}
179 
180 	/**
181 	 * Clears out ids recursively and also copies adhock clusets
182 	 * @param statementTreeView
183 	 * @param luService
184 	 * @throws OperationFailedException
185 	 */
186 	private void clearStatementTreeViewIdsRecursively(StatementTreeViewInfo statementTreeView, String newState,LuService luService) throws OperationFailedException{
187 		statementTreeView.setId(null);
188 		statementTreeView.setState(newState);
189 		
190 		//clear out all the nested requirement components
191 		for(ReqComponentInfo reqComp:statementTreeView.getReqComponents()){
192 			reqComp.setId(null);
193 			reqComp.setState(newState);
194 			for(ReqCompFieldInfo field:reqComp.getReqCompFields()){
195 				field.setId(null);
196 				//copy any clusets that are adhoc'd and set the field value to the new cluset
197 				if(ReqComponentFieldTypes.COURSE_CLUSET_KEY.getId().equals(field.getType())||
198 				   ReqComponentFieldTypes.PROGRAM_CLUSET_KEY.getId().equals(field.getType())||
199 				   ReqComponentFieldTypes.CLUSET_KEY.getId().equals(field.getType())){
200 					try {
201 						CluSetInfo cluSet = luService.getCluSetInfo(field.getValue());
202 						cluSet.setId(null);
203 						cluSet.setState(newState);
204 						//Clear clu ids if membership info exists, they will be re-added based on membership info 
205 						if (cluSet.getMembershipQuery() != null){
206 							cluSet.getCluIds().clear();
207 							cluSet.getCluSetIds().clear();
208 						}
209 						cluSet = luService.createCluSet(cluSet.getType(), cluSet);
210 						field.setValue(cluSet.getId());
211 					} catch (Exception e) {
212 						throw new OperationFailedException("Error copying clusets.", e);
213 					}
214 				}
215 				
216 			}
217 		}
218 		//recurse through nested statements
219 		for(StatementTreeViewInfo child: statementTreeView.getStatements()){
220 			clearStatementTreeViewIdsRecursively(child,newState,luService);
221 		}
222 	}
223 
224     private void copyStatements(String originalCluId, String newCluId, String newState,
225 			StatementService statementService, LuService luService, CourseService courseService) throws OperationFailedException, DoesNotExistException, InvalidParameterException, MissingParameterException, PermissionDeniedException, DataValidationErrorException {
226 		//Get the course statements
227 		List<StatementTreeViewInfo> statementTreeViews = courseService.getCourseStatements(originalCluId,null,null);
228 		
229 		//Clear out the ids and create causing a copy to be made
230 		if(statementTreeViews!=null){
231 			clearStatementTreeViewIds(statementTreeViews,newState,luService);
232 			
233 			for(StatementTreeViewInfo statementTreeView:statementTreeViews){
234 				courseService.createCourseStatement(newCluId, statementTreeView);
235 			}
236 		}
237 	}
238 	
239 	private CourseInfo copyCourse(String originalCluId, String newCluId, String newState, List<String> ignoreProperties, StatementService statementService, LuService luService, CourseService courseService) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, AlreadyExistsException, DataValidationErrorException, VersionMismatchException, CircularRelationshipException, DependentObjectsExistException, UnsupportedActionException{
240 		CourseInfo originalCourse = courseService.getCourse(originalCluId);
241 		resetIds(originalCourse);
242 		originalCourse.setCourseTitle("Copy of "+originalCourse.getCourseTitle());
243 		//Default the newState to the existing course state if no state was set.
244 		//State should never be null
245 		if(newState==null){
246 			newState = originalCourse.getState();
247 		}
248 		
249 		originalCourse.setId(newCluId);
250 		originalCourse.setState(newState);
251         originalCourse.setPilotCourse(false);
252 		
253 		//Loop through the ignore properties and null out the values
254 		if(ignoreProperties!=null){
255 			for(String property:ignoreProperties){
256 				try {
257 					PropertyUtils.setProperty(originalCourse, property, null);
258 				} catch (Exception e) {
259 					throw new InvalidParameterException("Ignore property is invalid and is causing an exception.",e);
260 				}
261 			}
262 		}
263 		
264 		CourseInfo newCourse = courseService.createCourse(originalCourse);
265         copyStatements(originalCluId, newCourse.getId(), newState, statementService, luService, courseService);
266 		return newCourse;
267 	}
268 
269 	public void setCourseService(CourseService courseService) {
270 		this.courseService = courseService;
271 	}
272 
273 	public void setLuService(LuService luService) {
274 		this.luService = luService;
275 	}
276 
277 	public void setStatementService(StatementService statementService) {
278 		this.statementService = statementService;
279 	}
280 
281 	public void setProposalService(ProposalService proposalService) {
282 		this.proposalService = proposalService;
283 	}
284 
285 	public void setCourseDataService(DataService courseDataService) {
286 		this.courseDataService = courseDataService;
287 	}
288 
289 	public void setCourseProposalDataService(DataService courseProposalDataService) {
290 		this.courseProposalDataService = courseProposalDataService;
291 	}
292 
293 	public void setDefaultDocumentType(String defaultDocumentType) {
294 		this.defaultDocumentType = defaultDocumentType;
295 	}
296 
297 	public void setDefaultState(String defaultState) {
298 		this.defaultState = defaultState;
299 	}
300 
301 	public void setIgnoreProperties(List<String> ignoreProperties) {
302 		this.ignoreProperties = ignoreProperties;
303 	}
304 	
305 }