View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.lum.lo.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import javax.jws.WebService;
22  
23  import org.kuali.student.common.validator.Validator;
24  import org.kuali.student.common.validator.ValidatorFactory;
25  import org.kuali.student.core.dictionary.dto.ObjectStructureDefinition;
26  import org.kuali.student.core.dictionary.service.DictionaryService;
27  import org.kuali.student.core.dto.StatusInfo;
28  import org.kuali.student.core.exceptions.AlreadyExistsException;
29  import org.kuali.student.core.exceptions.DataValidationErrorException;
30  import org.kuali.student.core.exceptions.DependentObjectsExistException;
31  import org.kuali.student.core.exceptions.DoesNotExistException;
32  import org.kuali.student.core.exceptions.InvalidParameterException;
33  import org.kuali.student.core.exceptions.MissingParameterException;
34  import org.kuali.student.core.exceptions.OperationFailedException;
35  import org.kuali.student.core.exceptions.PermissionDeniedException;
36  import org.kuali.student.core.exceptions.UnsupportedActionException;
37  import org.kuali.student.core.exceptions.VersionMismatchException;
38  import org.kuali.student.core.search.dto.SearchCriteriaTypeInfo;
39  import org.kuali.student.core.search.dto.SearchParam;
40  import org.kuali.student.core.search.dto.SearchRequest;
41  import org.kuali.student.core.search.dto.SearchResult;
42  import org.kuali.student.core.search.dto.SearchResultCell;
43  import org.kuali.student.core.search.dto.SearchResultRow;
44  import org.kuali.student.core.search.dto.SearchResultTypeInfo;
45  import org.kuali.student.core.search.dto.SearchTypeInfo;
46  import org.kuali.student.core.search.service.SearchManager;
47  import org.kuali.student.core.validation.dto.ValidationResultInfo;
48  import org.kuali.student.lum.lo.dao.LoDao;
49  import org.kuali.student.lum.lo.dto.LoCategoryInfo;
50  import org.kuali.student.lum.lo.dto.LoCategoryTypeInfo;
51  import org.kuali.student.lum.lo.dto.LoInfo;
52  import org.kuali.student.lum.lo.dto.LoLoRelationInfo;
53  import org.kuali.student.lum.lo.dto.LoLoRelationTypeInfo;
54  import org.kuali.student.lum.lo.dto.LoRepositoryInfo;
55  import org.kuali.student.lum.lo.dto.LoTypeInfo;
56  import org.kuali.student.lum.lo.entity.Lo;
57  import org.kuali.student.lum.lo.entity.LoCategory;
58  import org.kuali.student.lum.lo.entity.LoCategoryType;
59  import org.kuali.student.lum.lo.entity.LoLoRelation;
60  import org.kuali.student.lum.lo.entity.LoLoRelationType;
61  import org.kuali.student.lum.lo.entity.LoRepository;
62  import org.kuali.student.lum.lo.entity.LoType;
63  import org.kuali.student.lum.lo.service.LearningObjectiveService;
64  import org.springframework.transaction.annotation.Transactional;
65  
66  /*n
67   * @author Kuali Student team
68   *
69   */
70  @WebService(endpointInterface = "org.kuali.student.lum.lo.service.LearningObjectiveService", serviceName = "LearningObjectiveService", portName = "LearningObjectiveService", targetNamespace = "http://student.kuali.org/wsdl/lo")
71  @Transactional(readOnly=true,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
72  public class LearningObjectiveServiceImpl implements LearningObjectiveService {
73      private LoDao loDao;
74  	private SearchManager searchManager;
75      private DictionaryService dictionaryServiceDelegate;
76  	private ValidatorFactory validatorFactory;
77  
78  	public LoDao getLoDao() {
79          return loDao;
80      }
81  
82      public void setLoDao(LoDao dao) {
83          this.loDao = dao;
84      }
85  
86  	public void setSearchManager(SearchManager searchManager) {
87  		this.searchManager = searchManager;
88  	}
89  
90      public void setDictionaryServiceDelegate(DictionaryService dictionaryServiceDelegate) {
91          this.dictionaryServiceDelegate = dictionaryServiceDelegate;
92      }
93  
94  	public ValidatorFactory getValidatorFactory() {
95          return validatorFactory;
96      }
97  
98      public void setValidatorFactory(ValidatorFactory validatorFactory) {
99          this.validatorFactory = validatorFactory;
100     }
101 
102     /*
103      * (non-Javadoc)
104      * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoRepositories()
105      */
106 	@Override
107 	public List<LoRepositoryInfo> getLoRepositories()
108 			throws OperationFailedException {
109 	    List<LoRepository> repositories = loDao.find(LoRepository.class);
110 		return LearningObjectiveServiceAssembler.toLoRepositoryInfos(repositories);
111 	}
112 	
113 	/*
114 	 * (non-Javadoc)
115 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoRepository(java.lang.String)
116 	 */
117 	@Override
118 	public LoRepositoryInfo getLoRepository(String loRepositoryKey)
119 			throws DoesNotExistException, InvalidParameterException,
120 			MissingParameterException, OperationFailedException {
121 	    checkForMissingParameter(loRepositoryKey, "loRepositoryKey");
122 		return LearningObjectiveServiceAssembler.toLoRepositoryInfo(loDao.fetch(LoRepository.class, loRepositoryKey));
123 	}
124 
125 	/*
126 	 * (non-Javadoc)
127 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoTypes()
128 	 */
129 	@Override
130 	public List<LoTypeInfo> getLoTypes() throws OperationFailedException {
131 	    List<LoType> find = loDao.find(LoType.class);
132 		return LearningObjectiveServiceAssembler.toLoTypeInfos(find);
133 	}
134 
135 	/*
136 	 * (non-Javadoc)
137 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoType(java.lang.String)
138 	 */
139 	@Override
140 	public LoTypeInfo getLoType(String loTypeKey) throws DoesNotExistException,
141 			InvalidParameterException, MissingParameterException,
142 			OperationFailedException {
143 	    checkForMissingParameter(loTypeKey, "loTypeKey");
144 	    LoType fetch = loDao.fetch(LoType.class, loTypeKey);
145 		return LearningObjectiveServiceAssembler.toLoTypeInfo(fetch);
146 	}
147 
148 	/*
149 	 * (non-Javadoc)
150 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoLoRelationTypes()
151 	 */
152 	@Override
153 	public List<LoLoRelationTypeInfo> getLoLoRelationTypes()
154 			throws OperationFailedException {
155 	    List<LoLoRelationType> fetch = loDao.find(LoLoRelationType.class);
156 		return LearningObjectiveServiceAssembler.toLoLoRelationTypeInfos(fetch);
157 	}
158 
159 	/*
160 	 * (non-Javadoc)
161 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoLoRelationType(java.lang.String)
162 	 */
163 	@Override
164 	public LoLoRelationTypeInfo getLoLoRelationType(String loLoRelationTypeKey)
165 			throws OperationFailedException, MissingParameterException, DoesNotExistException {
166 	    checkForMissingParameter(loLoRelationTypeKey, "loLoRelationTypeKey");
167 		return LearningObjectiveServiceAssembler.toLoLoRelationTypeInfo(loDao.fetch(LoLoRelationType.class, loLoRelationTypeKey));
168 	}
169 
170 	@Override
171 	public List<String> getAllowedLoLoRelationTypesForLoType(String loTypeKey, String relatedLoTypeKey)
172 			throws DoesNotExistException, InvalidParameterException,
173 					MissingParameterException, OperationFailedException {
174 	    checkForMissingParameter(loTypeKey, "loTypeKey");
175 	    checkForMissingParameter(relatedLoTypeKey, "relatedLoTypeKey");
176 	    
177 	    return loDao.getAllowedLoLoRelationTypesForLoType(loTypeKey, relatedLoTypeKey);
178 	}
179 
180     /*
181 	 * (non-Javadoc)
182 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#addLoCategoryToLo(java.lang.String, java.lang.String)
183 	 */
184 	@Override
185 	@Transactional(readOnly=false)
186 	public StatusInfo addLoCategoryToLo(String loCategoryId, String loId)
187 			throws AlreadyExistsException, DoesNotExistException,
188 			InvalidParameterException, MissingParameterException,
189 			OperationFailedException, PermissionDeniedException,
190 			UnsupportedActionException {
191 	    checkForMissingParameter(loCategoryId, "loCategoryId");
192 	    checkForMissingParameter(loId, "loId");
193         StatusInfo statusInfo = new StatusInfo();
194         statusInfo.setSuccess(loDao.addLoCategoryToLo(loCategoryId, loId));
195         return statusInfo;
196 	}
197 
198 	/* (non-Javadoc)
199 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#createLo(java.lang.String, java.lang.String, org.kuali.student.lum.lo.dto.LoInfo)
200 	 */
201 	@Override
202 	@Transactional(readOnly=false)
203 	public LoInfo createLo(String repositoryId, String loType, LoInfo loInfo)
204 			throws DataValidationErrorException, DoesNotExistException,
205 			InvalidParameterException, MissingParameterException,
206 			OperationFailedException, PermissionDeniedException {
207 	    checkForMissingParameter(repositoryId, "repositoryId");
208 	    checkForMissingParameter(loType, "loType");
209 	    checkForMissingParameter(loInfo, "loInfo");
210 	    
211 	    
212 		// Validate LO
213 		List<ValidationResultInfo> val = validateLo("SYSTEM", loInfo);
214 		if(null != val && val.size() > 0) {
215 			for (ValidationResultInfo result : val) {
216 				System.err.println("Validation error. Element: " + result.getElement() + ",  Value: " + result.getMessage());
217 			}
218             throw new DataValidationErrorException("Validation error!", val);
219 		}
220 		
221 	    // make sure LoType and LoRepository exist before trying to create
222 	    // if checkForMissingParameter above did its job, we don't have to null-check these id's
223 	    LoType type = null;
224 	    LoRepository repository = null;
225 	    try {
226 		    type = loDao.fetch(LoType.class, loType);
227 		    repository = loDao.fetch(LoRepository.class, repositoryId); 
228 	    } catch (DoesNotExistException dnee) {
229 	    	throw new DoesNotExistException("Specified " + (null == type ? "LoType" : "LoRepository") + " does not exist", dnee);
230 	    }
231 	    
232 	    loInfo.setLoRepositoryKey(repositoryId);
233 	    loInfo.setType(loType);
234 	    
235 	    Lo lo = null;
236 	    try {
237 		    lo = LearningObjectiveServiceAssembler.toLo(false, loInfo, loDao);
238 	    } catch (VersionMismatchException vme) {
239 	    	// should never happen in a create call, but
240 	    	throw new OperationFailedException("VersionMismatchException caught during Learning Objective creation");
241 	    }
242 	    lo.setLoType(type);
243 	    lo.setLoRepository(repository);
244 	    loDao.create(lo);
245 	    
246 		return LearningObjectiveServiceAssembler.toLoInfo(lo);
247 	}
248 
249 	/* (non-Javadoc)
250 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#deleteLo(java.lang.String)
251 	 */
252 	@Override
253 	@Transactional(readOnly=false)
254 	public StatusInfo deleteLo(String loId)
255 			throws DependentObjectsExistException, DoesNotExistException,
256 			InvalidParameterException, MissingParameterException,
257 			OperationFailedException, PermissionDeniedException {
258 	    checkForMissingParameter(loId, "loId");
259 	    
260 	    StatusInfo returnStatus = new StatusInfo();
261 	    returnStatus.setSuccess(loDao.deleteLo(loId));
262 		return returnStatus;
263 	}
264 
265 	/* (non-Javadoc)
266 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#deleteLoCategory(java.lang.String)
267 	 */
268 	@Override
269 	@Transactional(readOnly=false)
270 	public StatusInfo deleteLoCategory(String loCategoryId)
271 			throws DependentObjectsExistException, DoesNotExistException,
272 			InvalidParameterException, MissingParameterException,
273 			OperationFailedException, PermissionDeniedException {
274 	    checkForMissingParameter(loCategoryId, "loCategoryId");
275 	    
276 	    loDao.deleteLoCategory(loCategoryId);
277 	    
278 		return new StatusInfo();
279 	}
280 
281 	/* (non-Javadoc)
282 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLo(java.lang.String)
283 	 */
284 	@Override
285 	public LoInfo getLo(String loId) throws DoesNotExistException,
286 			InvalidParameterException, MissingParameterException,
287 			OperationFailedException {
288 	    checkForMissingParameter(loId, "loId");
289 	    
290 		return LearningObjectiveServiceAssembler.toLoInfo(loDao.fetch(Lo.class, loId));
291 	}
292 
293 	/* (non-Javadoc)
294 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoByIdList(java.util.List)
295 	 */
296 	@Override
297 	public List<LoInfo> getLoByIdList(List<String> loIds)
298 			throws InvalidParameterException, MissingParameterException,
299 			OperationFailedException {
300 	    checkForMissingParameter(loIds, "loId");
301 	    checkForEmptyList(loIds, "loId");
302 	    List<Lo> los = loDao.getLoByIdList(loIds);
303 		return LearningObjectiveServiceAssembler.toLoInfos(los);
304 	}
305 
306 	/* (non-Javadoc)
307 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoCategories(java.lang.String)
308 	 */
309 	@Override
310 	public List<LoCategoryInfo> getLoCategories(String loRepositoryKey)
311 			throws DoesNotExistException, InvalidParameterException,
312 			MissingParameterException, OperationFailedException {
313 	    checkForMissingParameter(loRepositoryKey, "loRepositoryKey");
314 	    List<LoCategory> categories = loDao.getLoCategories(loRepositoryKey);
315         return LearningObjectiveServiceAssembler.toLoCategoryInfos(categories);
316 	}
317 
318 	/* (non-Javadoc)
319 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoCategoriesForLo(java.lang.String)
320 	 */
321 	@Override
322 	public List<LoCategoryInfo> getLoCategoriesForLo(String loId)
323 			throws DoesNotExistException, InvalidParameterException,
324 			MissingParameterException, OperationFailedException {
325 	    checkForMissingParameter(loId, "loId");
326 	    List<LoCategory> categories = loDao.getLoCategoriesForLo(loId);
327 		return LearningObjectiveServiceAssembler.toLoCategoryInfos(categories);
328 	}
329 
330 	/* (non-Javadoc)
331 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoCategory(java.lang.String)
332 	 */
333 	@Override
334 	public LoCategoryInfo getLoCategory(String loCategoryId)
335 			throws DoesNotExistException, InvalidParameterException,
336 			MissingParameterException, OperationFailedException {
337 	    checkForMissingParameter(loCategoryId, "loCategoryId");
338 	    
339 		return LearningObjectiveServiceAssembler.toLoCategoryInfo(loDao.fetch(LoCategory.class, loCategoryId));
340 	}
341 
342 	/* (non-Javadoc)
343 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLoParents(java.lang.String)
344 	public List<LoInfo> getLoParents(String loId) throws DoesNotExistException,
345 			InvalidParameterException, MissingParameterException,
346 			OperationFailedException {
347 	    checkForMissingParameter(loId, "loId");
348 	    List<Lo> loParents = loDao.getLoParents(loId);
349 		return LearningObjectiveServiceAssembler.toLoInfos(loParents);
350 	}
351 	 */
352 
353 	/* (non-Javadoc)
354 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#getLosByLoCategory(java.lang.String)
355 	 */
356 	@Override
357 	public List<LoInfo> getLosByLoCategory(String loCategoryId)
358 			throws DoesNotExistException, InvalidParameterException,
359 			MissingParameterException, OperationFailedException {
360 	    checkForMissingParameter(loCategoryId, "loCategoryId");
361 	    List<Lo> los = loDao.getLosByLoCategory(loCategoryId);
362 		return LearningObjectiveServiceAssembler.toLoInfos(los);
363 	}
364 
365 	/* (non-Javadoc)
366 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#isDescendant(java.lang.String, java.lang.String)
367 	@Override
368 	public Boolean isDescendant(String loId, String descendantLoId)
369 			throws DoesNotExistException, InvalidParameterException,
370 			MissingParameterException, OperationFailedException {
371 	    checkForMissingParameter(loId, "loId");
372 	    checkForMissingParameter(descendantLoId, "descendantLoId");
373 		return loDao.isDescendant(loId, descendantLoId);
374 	}
375 	 */
376 
377 	/* (non-Javadoc)
378 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#isEquivalent(java.lang.String, java.lang.String)
379 	@Override
380 	public Boolean isEquivalent(String loId, String equivalentLoId)
381 			throws DoesNotExistException, InvalidParameterException,
382 			MissingParameterException, OperationFailedException {
383 	    checkForMissingParameter(loId, "loId");
384 	    checkForMissingParameter(equivalentLoId, "equivalentLoId");
385 		return loDao.isEquivalent(loId, equivalentLoId);
386 	}
387 	 */
388 
389 	/* (non-Javadoc)
390 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#removeChildLoFromLo(java.lang.String, java.lang.String)
391 	@Override
392 	@Transactional(readOnly=false)
393 	public StatusInfo removeChildLoFromLo(String loId, String parentLoId)
394 			throws DependentObjectsExistException, DoesNotExistException,
395 			InvalidParameterException, MissingParameterException,
396 			OperationFailedException, PermissionDeniedException {
397 	    checkForMissingParameter(loId, "loId");
398 	    checkForMissingParameter(parentLoId, "parentLoId");
399 	    
400 	    StatusInfo statusInfo = new StatusInfo();
401 	    statusInfo.setSuccess(loDao.removeChildLoFromLo(loId, parentLoId));
402 		return statusInfo;
403 	}
404 	 */
405 
406 	/* (non-Javadoc)
407 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#removeEquivalentLoFromLo(java.lang.String, java.lang.String)
408 	@Override
409 	@Transactional(readOnly=false)
410 	public StatusInfo removeEquivalentLoFromLo(String loId,
411 			String equivalentLoId) throws DoesNotExistException,
412 			InvalidParameterException, MissingParameterException,
413 			OperationFailedException, PermissionDeniedException {
414 	    checkForMissingParameter(loId, "loId");
415 	    checkForMissingParameter(equivalentLoId, "equivalentLoId");
416 	    
417         StatusInfo statusInfo = new StatusInfo();
418         statusInfo.setSuccess(loDao.removeEquivalentLoFromLo(loId, equivalentLoId));
419         return statusInfo;
420 	}
421 	 */
422 
423 	/* (non-Javadoc)
424 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#removeLoCategoryFromLo(java.lang.String, java.lang.String)
425 	 */
426 	@Override
427 	@Transactional(readOnly=false)
428 	public StatusInfo removeLoCategoryFromLo(String loCategoryId, String loId)
429 			throws DoesNotExistException, InvalidParameterException,
430 			MissingParameterException, OperationFailedException,
431 			PermissionDeniedException, UnsupportedActionException {
432 	    checkForMissingParameter(loCategoryId, "loCategoryId");
433 	    checkForMissingParameter(loId, "loId");
434 	    
435         StatusInfo statusInfo = new StatusInfo();
436         statusInfo.setSuccess(loDao.removeLoCategoryFromLo(loCategoryId, loId));
437         return statusInfo;
438 	}
439 
440 	/* (non-Javadoc)
441 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#updateLo(java.lang.String, org.kuali.student.lum.lo.dto.LoInfo)
442 	 */
443 	@Override
444 	@Transactional(readOnly=false)
445 	public LoInfo updateLo(String loId, LoInfo loInfo)
446 			throws DataValidationErrorException, DoesNotExistException,
447 			InvalidParameterException, MissingParameterException,
448 			OperationFailedException, PermissionDeniedException,
449 			VersionMismatchException {
450 	    checkForMissingParameter(loId, "loId");
451 	    checkForMissingParameter(loInfo, "loInfo");
452 
453 		// Validate LO
454 		List<ValidationResultInfo> val = validateLo("SYSTEM", loInfo);
455 		if(null != val && val.size() > 0) {
456 			for (ValidationResultInfo result : val) {
457 				System.err.println("Validation error. Element: " + result.getElement() + ",  Value: " + result.getMessage());
458 			}
459 			throw new DataValidationErrorException("Validation error!", val);
460 		}
461 		
462 	    Lo lo = loDao.fetch(Lo.class, loId);
463         
464         if (!String.valueOf(lo.getVersionNumber()).equals(loInfo.getMetaInfo().getVersionInd())){
465             throw new VersionMismatchException("LO to be updated is not the current version");
466         }
467         
468         lo = LearningObjectiveServiceAssembler.toLo(true, lo, loInfo, loDao);
469         loDao.update(lo);
470         return LearningObjectiveServiceAssembler.toLoInfo(lo);
471 	}
472 
473 	/* (non-Javadoc)
474 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#updateLoCategory(java.lang.String, org.kuali.student.lum.lo.dto.LoCategoryInfo)
475 	 */
476 	@Override
477 	@Transactional(readOnly=false)
478 	public LoCategoryInfo updateLoCategory(String loCategoryId,
479 			LoCategoryInfo loCategoryInfo) throws DataValidationErrorException,
480 			DoesNotExistException, InvalidParameterException,
481 			MissingParameterException, OperationFailedException,
482 			PermissionDeniedException, VersionMismatchException {
483 	    checkForMissingParameter(loCategoryId, "loCategoryId");
484 	    checkForMissingParameter(loCategoryInfo, "loCategoryInfo");
485 	    
486 		// Validate LoCategory
487 		List<ValidationResultInfo> val = validateLoCategory("SYSTEM", loCategoryInfo);
488 
489 		//kslum-136 - don't allow dups w/ same name (case insensitive), type, state & repository
490         if (doesLoCategoryExist(loCategoryInfo.getLoRepository(), loCategoryInfo, loCategoryId)) {
491             ValidationResultInfo vr = new ValidationResultInfo();
492             vr.setElement("LO Category Name");
493             vr.setError("LO Category already exists");
494             val.add(vr);
495         }
496         if(null != val && val.size() > 0) {
497             for (ValidationResultInfo result : val) {
498                 System.err.println("Validation error. Element: " + result.getElement() + ",  Value: " + result.getMessage());
499             }
500             throw new DataValidationErrorException("Validation error!", val);
501         }
502 	    LoCategory loCategory = loDao.fetch(LoCategory.class, loCategoryId);
503         
504         if (!String.valueOf(loCategory.getVersionNumber()).equals(loCategoryInfo.getMetaInfo().getVersionInd())){
505             throw new VersionMismatchException("LoCategory to be updated is not the current version");
506         }
507         
508         // if state is changing from "active"
509         if (loCategory.getState().equals("active") && ( ! loCategoryInfo.getState().equals("active") )) {
510     		// N.B. - ability to 'retire' LoCategory's that are still associated w/ active
511     		// LO's is configured and enforced on the client
512         	List<LoInfo> loInfos = getLosByLoCategory(loCategoryId);
513     		if (null != loInfos) {
514 				// remove associations of this LoCategory from active LO's
515     			for (LoInfo info : loInfos) {
516     				if (info.getState().equals("active"))  {
517 	    				try {
518 							removeLoCategoryFromLo(loCategoryId, info.getId());
519 						} catch (UnsupportedActionException uaee) {
520 				    		throw new OperationFailedException("Unable to update LoCategory: could not remove association with active LearningObjective", uaee);
521 						}
522     				}
523     			}
524     		}
525         }
526         	
527         // if type is changing
528         if ( ! loCategory.getLoCategoryType().getId().equals(loCategoryInfo.getType()) ) {
529         	loCategory = cloneLoCategory(loCategory, loCategoryInfo);
530         } else {
531 	        loCategory = LearningObjectiveServiceAssembler.toLoCategory(loCategory, loCategoryInfo, loDao);
532 	        loDao.update(loCategory);
533         }
534         return LearningObjectiveServiceAssembler.toLoCategoryInfo(loCategory);
535 	}
536 
537     // inactivate current LoCategory & clone it w/ its relationships,
538 	// used when changing immutable type of LoCategory
539 	// https://test.kuali.org/confluence/display/KULSTG/DS+-+LO+Centrally+Maintain+Categories
540 	private LoCategory cloneLoCategory(LoCategory loCategory, LoCategoryInfo loCategoryInfo) throws DoesNotExistException, InvalidParameterException, OperationFailedException {
541     	LoCategoryType catType = null;
542     	
543     	try {
544         	catType = loDao.fetch(LoCategoryType.class, loCategoryInfo.getType());
545     	} catch (DoesNotExistException dnee) {
546     		throw new DoesNotExistException("Attempt to set LoCategory's type to nonexistent LoCategoryType", dnee);
547     	}
548         	
549     	// clone the existing LO
550     	LoCategoryInfo newLoCategoryInfo = LearningObjectiveServiceAssembler.toLoCategoryInfo(loCategory);
551     	newLoCategoryInfo.setType(catType.getId());
552     	newLoCategoryInfo.setName(loCategoryInfo.getName());
553     	LoCategory newLoCategory = loDao.create(LearningObjectiveServiceAssembler.toLoCategory(newLoCategoryInfo, loDao));
554         	
555     	// clone Lo-LoCategory relations
556     	List<Lo> catsLos = loDao.getLosByLoCategory(loCategory.getId());         	
557     	for (Lo lo : catsLos) {
558     		try {
559     			// create the new one
560 				loDao.addLoCategoryToLo(newLoCategory.getId(), lo.getId());
561 				// remove the old one
562 				loDao.removeLoCategoryFromLo(loCategory.getId(), lo.getId());
563 			} catch (UnsupportedActionException uae) {
564 				throw new OperationFailedException(uae.getMessage(), uae);
565 			}
566     	}
567         	
568     	// inactivate old LoCategory
569     	loCategory.setState("inactive");
570     	loDao.update(loCategory);
571         	
572     	return newLoCategory;
573 	}
574 
575 	/* (non-Javadoc)
576 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#validateLo(java.lang.String, org.kuali.student.lum.lo.dto.LoInfo)
577 	 */
578 	@Override
579 	public List<ValidationResultInfo> validateLo(String validationType,
580 			LoInfo loInfo) throws DoesNotExistException,
581 			InvalidParameterException, MissingParameterException,
582 			OperationFailedException {
583 	    checkForMissingParameter(validationType, "validationType");
584 	    checkForMissingParameter(loInfo, "loInfo");
585 
586      // this is the job of the validator not some hard coded value
587 //	    try{
588 //	    	String loDesc = loInfo.getDesc().getPlain();
589 //	    	checkForEmptyString(loDesc, "loInfo.Desc");
590 //	    } catch (NullPointerException e){
591 //			//do not checkForEmptyString
592 //		}
593 	    
594 	    ObjectStructureDefinition objStructure = this.getObjectStructure(LoInfo.class.getName());
595 	    Validator validator = validatorFactory.getValidator();
596 	    return validator.validateObject(loInfo, objStructure);
597 	}
598 
599 	/* (non-Javadoc)
600 	 * @see org.kuali.student.lum.lo.service.LearningObjectiveService#validateLoCategory(java.lang.String, org.kuali.student.lum.lo.dto.LoCategoryInfo)
601 	 */
602 	@Override
603 	public List<ValidationResultInfo> validateLoCategory(String validationType,
604 			LoCategoryInfo loCategoryInfo) throws DoesNotExistException,
605 			InvalidParameterException, MissingParameterException,
606 			OperationFailedException {
607 	    checkForMissingParameter(validationType, "validationType");
608 	    checkForMissingParameter(loCategoryInfo, "loCategoryInfo");
609 
610      // this is the job of the validator not some hard coded logic
611 //	    try{
612 //	    	String catDesc = loCategoryInfo.getDesc().getPlain();
613 //	    	checkForEmptyString(catDesc, "loCategoryInfo.Desc");
614 //	    } catch (NullPointerException e){
615 //			//do not checkForEmptyString
616 //		}
617 
618         ObjectStructureDefinition objStructure = this.getObjectStructure(LoCategoryInfo.class.getName());
619         Validator validator = validatorFactory.getValidator();
620         return validator.validateObject(loCategoryInfo, objStructure);
621 
622 	}
623 
624 	@Override
625 	public List<ValidationResultInfo> validateLoLoRelation(
626 			String validationType, LoLoRelationInfo loLoRelationInfo)
627 			throws DoesNotExistException, InvalidParameterException,
628 			MissingParameterException, OperationFailedException {
629 
630         ObjectStructureDefinition objStructure = this.getObjectStructure(LoLoRelationInfo.class.getName());
631         Validator validator = validatorFactory.getValidator();
632         return validator.validateObject(loLoRelationInfo, objStructure);
633 	}
634 
635     /**
636      * Check for missing parameter and throw localized exception if missing
637      *
638      * @param param
639      * @param parameter name
640      * @throws MissingParameterException
641      */
642     private void checkForMissingParameter(Object param, String paramName)
643             throws MissingParameterException {
644         if (param == null) {
645             throw new MissingParameterException(paramName + " can not be null");
646         }
647     }
648 
649     /**
650      * @param param
651      * @param paramName
652      * @throws MissingParameterException
653      */
654     private void checkForEmptyList(Object param, String paramName)
655             throws MissingParameterException {
656         if (param != null && param instanceof List && ((List<?>)param).size() == 0) {
657             throw new MissingParameterException(paramName + " can not be an empty list");
658         }
659     }
660 
661     // this is the job of the validator not some hard coded logic
662     // besides it should create a validation result not a missing parameter exeception
663 //    /**
664 //     * @param param
665 //     * @param paramName
666 //     * @throws MissingParameterException
667 //     */
668 //    private void checkForEmptyString(String param, String paramName)
669 //            throws MissingParameterException {
670 //        if (param != null && "".equals(param.trim())) {
671 //            throw new MissingParameterException(paramName + " can not be empty");
672 //        }
673 //    }
674 //
675     /**
676      * @param loRepositoryKey
677      * @param loCategoryInfo
678      * @param loCategoryId
679      * @throws MissingParameterException,OperationFailedException
680      */
681     private boolean doesLoCategoryExist(String loRepositoryKey, LoCategoryInfo loCategoryInfo, String loCategoryId)
682             throws MissingParameterException, DataValidationErrorException {
683     if (loCategoryInfo.getName() == null)
684     {
685      return false;
686     }
687         boolean exists = false;
688 	    SearchRequest request = new SearchRequest();
689 	    request.setSearchKey("lo.search.loCategoriesByNameRepoTypeState");
690 	    
691  		List<SearchParam> searchParams = new ArrayList<SearchParam>();
692 		SearchParam qpv1 = new SearchParam();
693 		qpv1.setKey("lo.queryParam.loCategoryName");
694 		qpv1.setValue(loCategoryInfo.getName().toLowerCase());
695 		searchParams.add(qpv1);
696 		SearchParam qpv2 = new SearchParam();
697 		qpv2.setKey("lo.queryParam.loCategoryRepo");
698 		qpv2.setValue(loRepositoryKey);
699 		searchParams.add(qpv2);
700 		SearchParam qpv3 = new SearchParam();
701 		qpv3.setKey("lo.queryParam.loCategoryType");
702 		qpv3.setValue(loCategoryInfo.getType());
703 		searchParams.add(qpv3);
704 		SearchParam qpv4 = new SearchParam();
705 		qpv4.setKey("lo.queryParam.loCategoryState");
706 		qpv4.setValue(loCategoryInfo.getState());
707 		searchParams.add(qpv4);
708 		
709 		request.setParams(searchParams);
710 		
711 		SearchResult result = search(request);
712 		
713 		if(loCategoryId != null && !loCategoryId.trim().equals("")){
714 			if (result.getRows().size() > 0) {
715 				for(SearchResultRow srrow : result.getRows()){
716 					List<SearchResultCell> srCells = srrow.getCells();
717 					if(srCells != null && srCells.size() > 0){
718 						for(SearchResultCell srcell : srCells){
719 							if(!srcell.getValue().equals(loCategoryId)) {
720                                 exists = true;
721                             }
722 						}
723 					}
724 				}
725 			}
726 		}
727 		else{
728 			if (result.getRows().size() > 0) {
729                 exists = true;
730 			}
731 		}
732         return exists;
733     }
734     
735     @Override
736     public ObjectStructureDefinition getObjectStructure(String objectTypeKey) {
737         return dictionaryServiceDelegate.getObjectStructure(objectTypeKey);
738     }
739 
740     @Override
741     public List<String> getObjectTypes() {
742         return dictionaryServiceDelegate.getObjectTypes();
743     }
744 
745 	/* (non-Javadoc)
746 	 * @see org.kuali.student.core.search.service.SearchService#getSearchCriteriaType(java.lang.String)
747 	 */
748     @Override
749     public SearchCriteriaTypeInfo getSearchCriteriaType(
750             String searchCriteriaTypeKey) throws DoesNotExistException,
751             InvalidParameterException, MissingParameterException,
752             OperationFailedException {
753 
754         return searchManager.getSearchCriteriaType(searchCriteriaTypeKey);
755     }
756 
757 	/* (non-Javadoc)
758 	 * @see org.kuali.student.core.search.service.SearchService#getSearchCriteriaTypes()
759 	 */
760     @Override
761     public List<SearchCriteriaTypeInfo> getSearchCriteriaTypes()
762     throws OperationFailedException {
763         return searchManager.getSearchCriteriaTypes();
764     }
765 
766 	/* (non-Javadoc)
767 	 * @see org.kuali.student.core.search.service.SearchService#getSearchResultType(java.lang.String)
768 	 */
769     @Override
770     public SearchResultTypeInfo getSearchResultType(String searchResultTypeKey)
771     throws DoesNotExistException, InvalidParameterException,
772     MissingParameterException, OperationFailedException {
773         checkForMissingParameter(searchResultTypeKey, "searchResultTypeKey");
774         return searchManager.getSearchResultType(searchResultTypeKey);
775     }
776 
777 	/* (non-Javadoc)
778 	 * @see org.kuali.student.core.search.service.SearchService#getSearchResultTypes()
779 	 */
780     @Override
781     public List<SearchResultTypeInfo> getSearchResultTypes()
782     throws OperationFailedException {
783         return searchManager.getSearchResultTypes();
784     }
785 
786 	/* (non-Javadoc)
787 	 * @see org.kuali.student.core.search.service.SearchService#getSearchType(java.lang.String)
788 	 */
789     @Override
790     public SearchTypeInfo getSearchType(String searchTypeKey)
791     throws DoesNotExistException, InvalidParameterException,
792     MissingParameterException, OperationFailedException {
793         checkForMissingParameter(searchTypeKey, "searchTypeKey");
794         return searchManager.getSearchType(searchTypeKey);
795     }
796 
797 	/* (non-Javadoc)
798 	 * @see org.kuali.student.core.search.service.SearchService#getSearchTypes()
799 	 */
800     @Override
801     public List<SearchTypeInfo> getSearchTypes()
802     throws OperationFailedException {
803         return searchManager.getSearchTypes();
804     }
805 
806 	/* (non-Javadoc)
807 	 * @see org.kuali.student.core.search.service.SearchService#getSearchTypesByCriteria(java.lang.String)
808 	 */
809     @Override
810     public List<SearchTypeInfo> getSearchTypesByCriteria(
811             String searchCriteriaTypeKey) throws DoesNotExistException,
812             InvalidParameterException, MissingParameterException,
813             OperationFailedException {
814         checkForMissingParameter(searchCriteriaTypeKey, "searchCriteriaTypeKey");
815         return searchManager.getSearchTypesByCriteria(searchCriteriaTypeKey);
816     }
817 
818 	/* (non-Javadoc)
819 	 * @see org.kuali.student.core.search.service.SearchService#getSearchTypesByResult(java.lang.String)
820 	 */
821     @Override
822     public List<SearchTypeInfo> getSearchTypesByResult(
823             String searchResultTypeKey) throws DoesNotExistException,
824             InvalidParameterException, MissingParameterException,
825             OperationFailedException {
826         checkForMissingParameter(searchResultTypeKey, "searchResultTypeKey");
827         return searchManager.getSearchTypesByResult(searchResultTypeKey);
828     }
829 
830 	@Override
831 	@Transactional(readOnly=false)
832 	public LoLoRelationInfo createLoLoRelation(String loId, String relatedLoId,
833 			String loLoRelationType, LoLoRelationInfo loLoRelationInfo)
834 			throws AlreadyExistsException, 
835 			DataValidationErrorException, DoesNotExistException,
836 			InvalidParameterException, MissingParameterException,
837 			OperationFailedException, PermissionDeniedException {
838 	    checkForMissingParameter(loId, "loId");
839 	    checkForMissingParameter(relatedLoId, "relatedLoId");
840 	    checkForMissingParameter(loLoRelationType, "loLoRelationType");
841 	    checkForMissingParameter(loLoRelationInfo, "loLoRelationInfo");
842 	    
843 		// Validate LoLoRelation
844 		List<ValidationResultInfo> val = validateLoLoRelation("SYSTEM", loLoRelationInfo);
845 		if(null != val && val.size() > 0) {
846 			for (ValidationResultInfo result : val) {
847 				System.err.println("Validation error. Element: " + result.getElement() + ",  Value: " + result.getMessage());
848 			}
849 			throw new DataValidationErrorException("Validation error!", val);
850 		}
851 	    
852 	    if (null == loLoRelationInfo.getState()) {
853 	    	loLoRelationInfo.setState("draft"); // TODO - enum of allowed states? retrieve allowed states from dictionary?
854 	    }
855 	    Lo lo = loDao.fetch(Lo.class, loId);
856 	    Lo relatedLo = loDao.fetch(Lo.class, relatedLoId);
857 	    LoLoRelationType type = loDao.fetch(LoLoRelationType.class, loLoRelationType);
858 	    loLoRelationInfo.setLoId(loId);
859 	    loLoRelationInfo.setRelatedLoId(relatedLoId);
860 	    loLoRelationInfo.setType(loLoRelationType);
861 	    
862 	    LoLoRelation relation = null;
863 	    try {
864 		    relation = LearningObjectiveServiceAssembler.toLoLoRelation(false, loLoRelationInfo, loDao);
865 	    } catch (VersionMismatchException vme) {
866 	    	// should never happen in a create call, but
867 	    	throw new OperationFailedException("VersionMismatchException caught during LoLoRelation creation");
868 	    }
869 	    relation.setLo(lo);
870 	    relation.setRelatedLo(relatedLo);
871 	    relation.setLoLoRelationType(type);
872 	    
873 	    relation = loDao.create(relation);
874 	    
875 		return LearningObjectiveServiceAssembler.toLoLoRelationInfo(relation);
876 	}
877 
878 	@Override
879 	@Transactional(readOnly=false)
880 	public StatusInfo deleteLoLoRelation(String loLoRelationId)
881 			throws DoesNotExistException, InvalidParameterException,
882 			MissingParameterException, OperationFailedException,
883 			PermissionDeniedException {
884 	    checkForMissingParameter(loLoRelationId, "loLoRelationId");
885 	    
886 	    loDao.deleteLoLoRelation(loLoRelationId);
887 	    
888 		return new StatusInfo();
889 	}
890 
891 	@Override
892 	public LoLoRelationInfo getLoLoRelation(String loLoRelationId)
893 			throws DoesNotExistException, InvalidParameterException,
894 			MissingParameterException, OperationFailedException {
895 	    checkForMissingParameter(loLoRelationId, "loLoRelationId");
896 		return LearningObjectiveServiceAssembler.toLoLoRelationInfo(loDao.fetch(LoLoRelation.class, loLoRelationId));
897 	}
898 
899 	@Override
900 	public List<LoLoRelationInfo> getLoLoRelationsByLoId(String loId)
901 			throws DoesNotExistException, InvalidParameterException,
902 			MissingParameterException, OperationFailedException {
903 		List<LoLoRelation> llRelations = loDao.getLoLoRelationsByLoId(loId);
904 		return LearningObjectiveServiceAssembler.toLoLoRelationInfos(llRelations);
905 	}
906 
907 	@Override
908 	public List<LoInfo> getLosByRelatedLoId(String relatedLoId,
909 			String loLoRelationType) throws DoesNotExistException,
910 			InvalidParameterException, MissingParameterException,
911 			OperationFailedException {
912 		List<Lo> relatedLos = loDao.getLosByRelatedLoId(relatedLoId, loLoRelationType);
913 		return LearningObjectiveServiceAssembler.toLoInfos(relatedLos);
914 	}
915 
916 	@Override
917 	public List<LoInfo> getRelatedLosByLoId(String loId, String loLoRelationTypeKey)
918 			throws DoesNotExistException, InvalidParameterException,
919 			MissingParameterException, OperationFailedException {
920 	    checkForMissingParameter(loId, "loId");
921 	    checkForMissingParameter(loLoRelationTypeKey, "loLoRelationTypeKey");
922 	    List<Lo> relatedLos = loDao.getRelatedLosByLoId(loId, loLoRelationTypeKey);
923 		return LearningObjectiveServiceAssembler.toLoInfos(relatedLos);
924 	}
925 
926 	@Override
927 	@Transactional(readOnly=false)
928 	public LoLoRelationInfo updateLoLoRelation(String loLoRelationId,
929 			LoLoRelationInfo loLoRelationInfo)
930 			throws DataValidationErrorException, DoesNotExistException,
931 			InvalidParameterException, MissingParameterException,
932 			OperationFailedException, PermissionDeniedException,
933 			VersionMismatchException {
934 		
935 
936 		// Validate LoLoRelation
937 		List<ValidationResultInfo> val = validateLoLoRelation("SYSTEM", loLoRelationInfo);
938 		if(null != val && val.size() > 0) {
939 			throw new DataValidationErrorException("Validation error!", val);
940 		}
941 
942 	    
943 		return null;
944 	}
945 
946 	@Override
947 	@Transactional(readOnly=false)
948 	public LoCategoryInfo createLoCategory(String loRepositoryKey,
949 			String loCategoryTypeKey, LoCategoryInfo loCategoryInfo)
950 			throws DataValidationErrorException, DoesNotExistException,
951 			InvalidParameterException, MissingParameterException,
952 			OperationFailedException, PermissionDeniedException {
953 	    checkForMissingParameter(loRepositoryKey, "loRepositoryKey");
954 	    checkForMissingParameter(loCategoryTypeKey, "loCategoryTypeKey");
955 	    checkForMissingParameter(loCategoryInfo, "loCategoryInfo");
956 	    
957 		// Validate LoCategory
958 		List<ValidationResultInfo> val = validateLoCategory("SYSTEM", loCategoryInfo);
959 
960         //kslum-136 - don't allow dups w/ same name (case insensitive), type, state & repository       
961         if (doesLoCategoryExist(loRepositoryKey, loCategoryInfo, null)) {
962             ValidationResultInfo vr = new ValidationResultInfo();
963             vr.setElement("LO Category Name");
964             vr.setError("LO Category already exists");
965             val.add(vr);
966         }
967         if(null != val && val.size() > 0) {
968 			for (ValidationResultInfo result : val) {
969 				System.err.println("Validation error. Element: " + result.getElement() + ",  Value: " + result.getMessage());
970 			}
971 			throw new DataValidationErrorException("Validation error!", val);
972 		}
973 
974 	    LoCategory category = LearningObjectiveServiceAssembler.toLoCategory(loCategoryInfo, loDao);
975 	    LoCategoryType loCatType = loDao.fetch(LoCategoryType.class, loCategoryTypeKey);
976 	    category.setLoCategoryType(loCatType);
977 	    LoRepository loRepository = loDao.fetch(LoRepository.class, loRepositoryKey);
978 	    category.setLoRepository(loRepository);
979 	    loDao.create(category);
980 		return LearningObjectiveServiceAssembler.toLoCategoryInfo(category);
981 	}
982 
983 	@Override
984 	public LoCategoryTypeInfo getLoCategoryType(String loCategoryTypeKey)
985 			throws DoesNotExistException, InvalidParameterException,
986 			MissingParameterException, OperationFailedException {
987 	    checkForMissingParameter(loCategoryTypeKey, "loCategoryTypeKey");
988 	    LoCategoryType loCatType = loDao.fetch(LoCategoryType.class, loCategoryTypeKey);
989 	    return LearningObjectiveServiceAssembler.toLoCategoryTypeInfo(loCatType);
990 	}
991 
992 	@Override
993 	public List<LoCategoryTypeInfo> getLoCategoryTypes()
994 			throws OperationFailedException {
995 		List<LoCategoryType> categoryTypes = loDao.find(LoCategoryType.class);
996 		return LearningObjectiveServiceAssembler.toLoCategoryTypeInfos(categoryTypes);
997 	}
998 
999 	@Override
1000 	public List<LoInfo> getLosByRepository(String loRepositoryKey,
1001 			String loTypeKey, String loStateKey)
1002 			throws InvalidParameterException, MissingParameterException,
1003 			OperationFailedException {
1004 	    checkForMissingParameter(loRepositoryKey, "loRepositoryKey");
1005 	    List<Lo> los = loDao.getLosByRepository(loRepositoryKey);
1006 		return LearningObjectiveServiceAssembler.toLoInfos(los);
1007 	}
1008 
1009 	@Override
1010 	public SearchResult search(SearchRequest searchRequest) throws MissingParameterException {
1011         checkForMissingParameter(searchRequest, "searchRequest");
1012         return searchManager.search(searchRequest, loDao);
1013 	}
1014 
1015 }