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 static org.junit.Assert.assertEquals;
19  import static org.junit.Assert.assertFalse;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.fail;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Date;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.junit.Test;
32  import org.kuali.student.common.dto.DtoConstants;
33  import org.kuali.student.common.dto.RichTextInfo;
34  import org.kuali.student.common.dto.StatusInfo;
35  import org.kuali.student.common.exceptions.AlreadyExistsException;
36  import org.kuali.student.common.exceptions.CircularReferenceException;
37  import org.kuali.student.common.exceptions.CircularRelationshipException;
38  import org.kuali.student.common.exceptions.DataValidationErrorException;
39  import org.kuali.student.common.exceptions.DependentObjectsExistException;
40  import org.kuali.student.common.exceptions.DoesNotExistException;
41  import org.kuali.student.common.exceptions.InvalidParameterException;
42  import org.kuali.student.common.exceptions.MissingParameterException;
43  import org.kuali.student.common.exceptions.OperationFailedException;
44  import org.kuali.student.common.exceptions.PermissionDeniedException;
45  import org.kuali.student.common.exceptions.UnsupportedActionException;
46  import org.kuali.student.common.exceptions.VersionMismatchException;
47  import org.kuali.student.common.search.dto.SearchParam;
48  import org.kuali.student.common.search.dto.SearchRequest;
49  import org.kuali.student.common.search.dto.SearchResult;
50  import org.kuali.student.common.search.dto.SearchResultCell;
51  import org.kuali.student.common.test.spring.AbstractServiceTest;
52  import org.kuali.student.common.test.spring.Client;
53  import org.kuali.student.common.test.spring.Dao;
54  import org.kuali.student.common.test.spring.Daos;
55  import org.kuali.student.common.test.spring.PersistenceFileLocation;
56  import org.kuali.student.lum.lo.dto.LoCategoryInfo;
57  import org.kuali.student.lum.lo.dto.LoCategoryTypeInfo;
58  import org.kuali.student.lum.lo.dto.LoInfo;
59  import org.kuali.student.lum.lo.dto.LoLoRelationInfo;
60  import org.kuali.student.lum.lo.dto.LoLoRelationTypeInfo;
61  import org.kuali.student.lum.lo.dto.LoRepositoryInfo;
62  import org.kuali.student.lum.lo.dto.LoTypeInfo;
63  import org.kuali.student.lum.lo.service.LearningObjectiveService;
64  
65  @Daos({@Dao(value = "org.kuali.student.lum.lo.dao.impl.LoDaoImpl", testSqlFile = "classpath:ks-lo.sql")})
66  @PersistenceFileLocation("classpath:META-INF/lo-persistence.xml")
67  public class TestLearningObjectiveServiceImpl extends AbstractServiceTest {
68      @Client(value = "org.kuali.student.lum.lo.service.impl.LearningObjectiveServiceImpl", additionalContextFile = "classpath:lo-additional-context.xml")
69      public LearningObjectiveService client;
70  
71      @Test
72      public void testLo() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, DataValidationErrorException, PermissionDeniedException, VersionMismatchException, DependentObjectsExistException, AlreadyExistsException, CircularRelationshipException {
73          LoInfo loInfo = new LoInfo();
74          loInfo.setName("How Lo Can You Go");
75          RichTextInfo richText = new RichTextInfo();
76          richText.setFormatted("<p>New ResultComponent</p>");
77          richText.setPlain("New ResultComponent");
78          loInfo.setDesc(richText);
79          Date date = new Date();
80          loInfo.setEffectiveDate(date);
81          loInfo.setExpirationDate(date);
82          loInfo.setLoRepositoryKey("kuali.loRepository.key.singleUse");
83          Map<String, String> attributes = new HashMap<String, String>();
84          attributes.put("attrKey", "attrValue");
85          loInfo.setAttributes(attributes);
86          loInfo.setType("kuali.lo.type.singleUse");
87          loInfo.setState(DtoConstants.STATE_DRAFT);
88  
89          LoInfo created = client.createLo("kuali.loRepository.key.singleUse", "kuali.lo.type.singleUse", loInfo); 
90          assertNotNull(created);
91          String loId = created.getId();
92          assertNotNull(loId);
93          
94          created = client.getLo(loId);
95  
96          RichTextInfo desc = created.getDesc();
97          assertNotNull(desc);
98          assertEquals("<p>New ResultComponent</p>", desc.getFormatted());
99          assertEquals("New ResultComponent", desc.getPlain());
100         assertEquals(date.toString(), created.getEffectiveDate().toString());
101         assertEquals(date.toString(), created.getExpirationDate().toString());
102         Map<String, String> newAttributes = created.getAttributes();
103         assertNotNull(newAttributes);
104         assertEquals("attrValue", newAttributes.get("attrKey"));
105         assertEquals("kuali.lo.type.singleUse", created.getType()); 
106         assertEquals(DtoConstants.STATE_DRAFT, created.getState());
107 
108         loInfo = client.getLo(loId);
109         loInfo.setName("Lo in the mid 30s");
110 
111         LoInfo updated = client.updateLo(loId, loInfo);
112         assertNotNull(updated);
113         assertEquals(loId, updated.getId());
114         desc = updated.getDesc();
115         assertNotNull(desc);
116         assertEquals("<p>New ResultComponent</p>", desc.getFormatted());
117         assertEquals("New ResultComponent", desc.getPlain());
118         assertEquals(date.toString(), updated.getEffectiveDate().toString());
119         assertEquals(date.toString(), updated.getExpirationDate().toString());
120         newAttributes = updated.getAttributes();
121         assertNotNull(newAttributes);
122         assertEquals("attrValue", newAttributes.get("attrKey"));
123         assertEquals("kuali.lo.type.singleUse", updated.getType()); 
124         assertEquals(DtoConstants.STATE_DRAFT, updated.getState());
125 
126         try {
127             client.updateLo(loId, loInfo);
128             fail("VersionMismatchException expected");
129         } catch (VersionMismatchException e) {}
130 
131         // Detecting expected errors
132         loInfo = new LoInfo();
133         try {
134             client.createLo(null, "kuali.lo.type.singleUse", loInfo);
135             fail("MissingParameterException expected for loRepositoryId");
136         } catch (MissingParameterException e) {}
137         try {
138             client.createLo("kuali.loRepository.key.singleUse", null, loInfo);
139             fail("MissingParameterException expected for loTypeId");
140         } catch (MissingParameterException e) {}
141         try {
142             client.createLo("kuali.loRepository.key.singleUse", "kuali.lo.type.singleUse", null);
143             fail("MissingParameterException expected for loInfo");
144         } catch (MissingParameterException e) {}
145         
146         try {
147             client.getLo(null);
148             fail("MissingParameterException expected for loId");
149         } catch (MissingParameterException e) {}
150         
151         try {
152             client.updateLo(null, loInfo);
153             fail("MissingParameterException expected for loId");
154         } catch (MissingParameterException e) {}
155         try {
156             client.updateLo(loId, null);
157             fail("MissingParameterException expected for loInfo");
158         } catch (MissingParameterException e) {}
159         
160         StatusInfo statusInfo = client.deleteLo(loId);
161         assertTrue(statusInfo.getSuccess());
162         
163         // now make sure we can't orphan "included" LO's
164     	LoLoRelationInfo llrInfo = new LoLoRelationInfo();
165     	llrInfo.setLoId ("7bcd7c0e-3e6b-4527-ac55-254c58cecc22");
166      llrInfo.setRelatedLoId ("91a91860-d796-4a17-976b-a6165b1a0b05");
167      llrInfo.setType ("kuali.lo.relation.type.includes");
168 		llrInfo = client.createLoLoRelation(llrInfo.getLoId (), llrInfo.getRelatedLoId (), llrInfo.getType (), llrInfo);
169     	assertNotNull(llrInfo);
170     	llrInfo = client.getLoLoRelation(llrInfo.getId());
171     	try {
172     		client.deleteLo("7bcd7c0e-3e6b-4527-ac55-254c58cecc22");
173     		fail("Deleted an LO which orphaned included LO(s)");
174     	} catch (DependentObjectsExistException doee) {}
175     }
176     
177     @Test
178     public void testGetLoByIdList() throws DoesNotExistException, InvalidParameterException, OperationFailedException, MissingParameterException {
179     	List<LoInfo> loInfos = client.getLoByIdList(Arrays.asList("81abea67-3bcc-4088-8348-e265f3670145",
180     																"dd0658d2-fdc9-48fa-9578-67a2ce53bf8a",
181     																"91a91860-d796-4a17-976b-a6165b1a0b05"));
182     	assertEquals(3, loInfos.size());
183     }
184     
185 	/*
186 	 * Creating an LoCategory with the same name, type & state
187 	 */
188 	@Test
189 	public void testDisallowLoCategoryDuplication() throws DoesNotExistException, DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, DependentObjectsExistException {
190 		String catName = "DontDupThisCategory";
191 		String catState = "active";
192 		String catType = "loCategoryType.accreditation";
193 		String catRepo = "kuali.loRepository.key.singleUse";
194 		
195 		LoCategoryInfo newCatInfo = new LoCategoryInfo();
196 		newCatInfo.setName(catName);
197 		newCatInfo.setType(catType);
198 		newCatInfo.setState(catState);
199 		newCatInfo.setLoRepository(catRepo);
200 		
201 		newCatInfo = client.createLoCategory(catRepo, catType, newCatInfo);
202 		
203 		LoCategoryInfo dupCatInfo = new LoCategoryInfo();
204 		dupCatInfo.setName(catName);
205 		dupCatInfo.setType(catType);
206 		dupCatInfo.setState(catState);
207 		dupCatInfo.setLoRepository(catRepo);
208 		
209 		
210 		try {
211 			dupCatInfo = client.createLoCategory(catRepo, catType, dupCatInfo);
212 			// delete the two (one erroneously) created so as to not mess up other tests
213 			client.deleteLoCategory(newCatInfo.getId());
214 			client.deleteLoCategory(dupCatInfo.getId());
215             fail("DataValidationErrorException expected when creating LoCategory with the same name, type and state");
216 		} catch (DataValidationErrorException e) {
217 			// expected result
218 		}
219 		// delete the one created so as to not mess up other tests
220 		client.deleteLoCategory(newCatInfo.getId());
221 	}	
222 
223     @Test
224     public void testDisallowLoWEmptyDesc() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, DataValidationErrorException, PermissionDeniedException, VersionMismatchException, DependentObjectsExistException, AlreadyExistsException, CircularRelationshipException {
225         LoInfo loInfo = new LoInfo();
226         loInfo.setName("Lo with Empty Desc");
227         RichTextInfo richText = new RichTextInfo();
228         richText.setFormatted("<p> </p>");
229         richText.setPlain(" ");
230         loInfo.setDesc(richText);
231         Date date = new Date();
232         loInfo.setEffectiveDate(date);
233         loInfo.setExpirationDate(date);
234         loInfo.setLoRepositoryKey("kuali.loRepository.key.singleUse");
235         Map<String, String> attributes = new HashMap<String, String>();
236         attributes.put("attrKey", "attrValue");
237         loInfo.setAttributes(attributes);
238         loInfo.setType("kuali.lo.type.singleUse");
239         loInfo.setState(DtoConstants.STATE_DRAFT);
240 
241         try {
242         	 LoInfo created = client.createLo(loInfo.getLoRepositoryKey (), loInfo.getType (), loInfo);
243         	 assertNotNull(created);
244         	
245           // delete the one erroneously created so as to not mess up other tests
246         	 StatusInfo statusInfo = client.deleteLo(created.getId());
247              assertTrue(statusInfo.getSuccess());            
248              fail("OperationFailedException expected when creating Lo with empty description");
249         } catch (DataValidationErrorException mpe) {
250 			// expected result
251 		}
252       }
253     
254     @Test
255     public void testDisallowLoCategoryWEmptyName() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, DataValidationErrorException, PermissionDeniedException, VersionMismatchException, DependentObjectsExistException, AlreadyExistsException, CircularRelationshipException {
256 //    	String catName = "DontDupThisCategorytest";
257 		String catState = "active";
258 		String catType = "loCategoryType.accreditation";
259 		String catRepo = "kuali.loRepository.key.singleUse";
260 		
261 		LoCategoryInfo newCatInfo = new LoCategoryInfo();
262 //		newCatInfo.setName(catName);
263 		newCatInfo.setType(catType);
264 		newCatInfo.setState(catState);
265 		newCatInfo.setLoRepository(catRepo);
266 		
267 		//Testing KSLAB-692 *** this was not the intention of this jira
268   // it was that you needed to have at least one category with the LO
269 	      RichTextInfo richText = new RichTextInfo();
270 	      richText.setFormatted("<p> </p>");
271 	      richText.setPlain("  ");
272 	      newCatInfo.setDesc(richText);
273 		
274 		try{
275 				newCatInfo = client.createLoCategory(catRepo, catType, newCatInfo);
276 				assertNotNull(newCatInfo);
277 	        	
278 	          // delete the one erroneously created so as to not mess up other tests
279 	        	 StatusInfo statusInfo = client.deleteLoCategory(newCatInfo.getId());
280 	             assertTrue(statusInfo.getSuccess());            
281 	             fail("OperationFailedException expected when creating LoCategory with empty description");
282 		} catch (DataValidationErrorException mpe) {
283 			// expected result
284 		}
285 			
286     }
287        
288 	/*
289 	 * Creating an LoCategory with the same name (case insensitive), type & state
290 	 */
291 	
292 	@Test
293 	public void testDisallowLoCategoryDuplicationCaseInsensitive() throws DoesNotExistException, DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, DependentObjectsExistException {
294 		String catName = "DontDupThisCategory";
295 		String catState = "active";
296 		String catType = "loCategoryType.accreditation";
297 		String catRepo = "kuali.loRepository.key.singleUse";
298 		
299 		LoCategoryInfo newCatInfo = new LoCategoryInfo();
300 		newCatInfo.setName(catName);
301 		newCatInfo.setType(catType);
302 		newCatInfo.setState(catState);
303 		newCatInfo.setLoRepository(catRepo);
304 		
305 		try{				
306 			newCatInfo = client.createLoCategory(catRepo, catType, newCatInfo);
307 			newCatInfo = client.getLoCategory(newCatInfo.getId());
308 			newCatInfo.getName();
309 			catRepo = newCatInfo.getLoRepository();
310 		} catch (OperationFailedException ofe) {
311 			System.err.println(ofe.getMessage());
312 		} catch (Exception e){
313 			System.err.println(e.getMessage());
314 		}
315 		
316 		String dupCatName = "dontDupThisCategory";
317 		LoCategoryInfo dupCatInfo = new LoCategoryInfo();
318 		dupCatInfo.setName(dupCatName);
319 		dupCatInfo.setType(catType);
320 		dupCatInfo.setState(catState);
321 		dupCatInfo.setLoRepository(catRepo);
322 		
323 		
324 		try {
325 			dupCatInfo = client.createLoCategory(catRepo, catType, dupCatInfo);
326 			dupCatInfo = client.getLoCategory(dupCatInfo.getId());
327 			dupCatName = dupCatInfo.getName();
328 			
329 			// delete the two (one erroneously) created so as to not mess up other tests
330 			client.deleteLoCategory(newCatInfo.getId());
331 			client.deleteLoCategory(dupCatInfo.getId());
332             fail("DataValidationErrorException expected when creating LoCategory with the same name, type and state");
333 		} catch (DataValidationErrorException e) {
334 			// expected result
335 		}
336 		// delete the one created so as to not mess up other tests
337 		client.deleteLoCategory(newCatInfo.getId());
338 	}	
339 
340 	/*
341 	 * Updating a LoCategory with checking LoCategory duplication(based on name (case insensitive), type, state & repository
342 	 */
343 	
344 	@Test
345 	public void testUpdateLoCategoryDuplicationCaseInsensitive() throws DoesNotExistException, DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, DependentObjectsExistException {
346 		String catState = "active";
347 		String catType = "loCategoryType.accreditation";
348 		String catRepo = "kuali.loRepository.key.singleUse";
349 		String catId1 = null;
350 		String catId2 = null;
351 		
352 		LoCategoryInfo catInfo1 = new LoCategoryInfo();
353 		catInfo1.setName( "DontDupThisCategory");
354 		catInfo1.setType(catType);
355 		catInfo1.setState(catState);
356 		catInfo1.setLoRepository(catRepo);
357 		
358 		LoCategoryInfo catInfo2 = new LoCategoryInfo();
359 		catInfo2.setName("DontDupThisCategory2");
360 		catInfo2.setType(catType);
361 		catInfo2.setState(catState);
362 		catInfo2.setLoRepository(catRepo);
363 		
364 		try{				
365 			catInfo1 = client.createLoCategory(catRepo, catType, catInfo1);
366 			catId1 = catInfo1.getId();
367 			
368 			catInfo2 = client.createLoCategory(catRepo, catType, catInfo2);
369 			catId2 = catInfo2.getId();
370 		} catch (OperationFailedException ofe) {
371 			System.err.println(ofe.getMessage());
372 		} catch (Exception e){
373 			System.err.println(e.getMessage());
374 		}
375 		
376 		
377 		try {
378 			catInfo2.setName( "dontDupThisCategory");
379 			client.updateLoCategory(catId2, catInfo2);
380 			
381 	
382             fail("DataValidationErrorException expected when updating LoCategory with the same name, type and state");
383 		} catch (DataValidationErrorException e) {
384 			// expected result
385 		}catch (VersionMismatchException e){
386 			//expected for testing
387 		}
388 		
389 		// delete the two created so as to not mess up other tests
390 		client.deleteLoCategory(catId1);
391 		client.deleteLoCategory(catId2);
392 	}	
393 	
394     @Test
395     public void testGetRelatedLosByLoId() throws DoesNotExistException, InvalidParameterException, OperationFailedException {
396     	List<LoInfo> relatedLos = null;
397     	try {
398     		relatedLos = client.getRelatedLosByLoId("81abea67-3bcc-4088-8348-e265f3670145", "kuali.lo.relation.type.includes");
399     	} catch (Exception e) {
400             fail("Exception caught when calling LearningObjectiveService.getRelatedLosByLoId(): " + e.getMessage());
401     	}
402     	assertNotNull(relatedLos);
403     	assertEquals(2, relatedLos.size());
404 		assertTrue(relatedLos.get(0).getId().equals("e0b456b2-62cb-4bd3-8867-a0d59fd8f2cf") || relatedLos.get(1).getId().equals("e0b456b2-62cb-4bd3-8867-a0d59fd8f2cf"));
405 
406         // Detecting expected errors
407         try {
408     		relatedLos = client.getRelatedLosByLoId(null, "kuali.lo.relation.type.includes");
409             fail("MissingParameterException expected for loId");
410         } catch (MissingParameterException e) {}
411         try {
412     		relatedLos = client.getRelatedLosByLoId("81abea67-3bcc-4088-8348-e265f3670145", null);
413             fail("MissingParameterException expected for loLoRelationTypeKey");
414         } catch (MissingParameterException e) {}
415     }
416     
417     @Test
418     public void testGetLoRepositories() throws DoesNotExistException, InvalidParameterException, OperationFailedException {
419     	List<LoRepositoryInfo> repos = null;
420     	try {
421     		repos = client.getLoRepositories();
422     	} catch (Exception e) {
423             fail("Exception caught when calling LearningObjectiveService.getLoRepositories(): " + e.getMessage());
424     	}
425     	assertNotNull(repos);
426     	assertEquals(3, repos.size());
427     	
428 		boolean found = false;
429 		String  repoId = "kuali.loRepository.key.state";
430 		for (LoRepositoryInfo loRInfo : repos) {
431 			if (loRInfo.getId().equals(repoId)) {
432 				found = true;
433 			}
434 		}
435 		if (!found) {
436 			fail("Unable to find expected LoRepository with ID == " + repoId);
437 		}
438     }
439     
440     @Test
441     public void testGetLoRepository() throws DoesNotExistException, InvalidParameterException, OperationFailedException {
442     	LoRepositoryInfo repo = null;
443     	try {
444     		repo = client.getLoRepository("kuali.loRepository.key.state");
445     	} catch (Exception e) {
446             fail("Exception caught when calling LearningObjectiveService.getLoRepository(): " + e.getMessage());
447     	}
448     	assertNotNull(repo);
449     	assertEquals("Learning objectives mandated by the state", repo.getDesc().getPlain());
450         // Detecting expected errors
451         try {
452     		client.getLoRepository(null);
453             fail("MissingParameterException expected for loRepositoryKey");
454         } catch (MissingParameterException e) {}
455     }
456     
457     @Test
458     public void testGetLoCategoryTypes() throws DoesNotExistException, InvalidParameterException, OperationFailedException {
459     	List<LoCategoryTypeInfo> loCatTypeInfos = client.getLoCategoryTypes();
460     	assertEquals(3, loCatTypeInfos.size());
461     }
462     	
463     @Test
464     public void testGetLoTypesAndGetLoType() throws OperationFailedException, DoesNotExistException, InvalidParameterException, MissingParameterException {
465         List<LoTypeInfo> loTypes = client.getLoTypes();
466         assertNotNull(loTypes);
467         assertTrue(!loTypes.isEmpty());
468         
469         LoTypeInfo loType = client.getLoType(loTypes.get(0).getId());
470         assertEquals(loTypes.get(0).getName(), loType.getName());
471         
472         loType = client.getLoType("kuali.lo.type.governed");
473         assertEquals("Governed", loType.getName());
474         
475         // Detecting expected errors
476         try {
477     		client.getLoType(null);
478             fail("MissingParameterException expected for loTypeKey");
479         } catch (MissingParameterException e) {}
480     }
481     
482     @Test
483     public void testGetLoLoRelationTypes()  {
484     	List<LoLoRelationTypeInfo> llrtInfos = null;
485     	try {
486     		llrtInfos = client.getLoLoRelationTypes();
487     	} catch (Exception e) {
488             fail("Exception caught when calling LearningObjectiveService.getLoLoRelationTypes(): " + e.getMessage());
489     	}
490     	assertNotNull(llrtInfos);
491     	assertEquals(2, llrtInfos.size());
492     	assertTrue(llrtInfos.get(0).getName().equals("inSupportOf") || llrtInfos.get(1).getName().equals("inSupportOf"));
493     			
494     }
495     
496     @Test
497     public void testGetLoLoRelationType() throws OperationFailedException, DoesNotExistException  {
498     	LoLoRelationTypeInfo llrtInfo = null;
499     	try {
500     		llrtInfo = client.getLoLoRelationType("kuali.lo.relation.type.includes");
501     	} catch (Exception e) {
502             fail("Exception caught when calling LearningObjectiveService.getLoLoRelationType(): " + e.getMessage());
503     	}
504     	assertNotNull(llrtInfo);
505     	assertEquals("includes", llrtInfo.getName());
506         // Detecting expected errors
507         try {
508     		client.getLoLoRelationType(null);
509             fail("MissingParameterException expected for loLoRelationTypeKey");
510         } catch (MissingParameterException e) {}
511     }
512     
513     @Test
514     public void testGetAllowedLoLoRelationTypesForLoType() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
515     	List<String> allowedTypes = client.getAllowedLoLoRelationTypesForLoType("kuali.lo.type.singleUse", "kuali.lo.type.singleUse");
516     	assertEquals(1, allowedTypes.size());
517     	allowedTypes = client.getAllowedLoLoRelationTypesForLoType("kuali.lo.type.governed", "kuali.lo.type.governed");
518     	assertTrue(null == allowedTypes || allowedTypes.size() == 0);
519     }
520     
521     @Test
522     public void testGetLoLoRelation() throws OperationFailedException, DoesNotExistException, InvalidParameterException  {
523     	LoLoRelationInfo llrInfo = null;
524     	try {
525     		llrInfo = client.getLoLoRelation("61ff5b2c-5d2f-464b-b6d8-082fbf671fcb");
526     	} catch (Exception e) {
527             fail("Exception caught when calling LearningObjectiveService.getLoLoRelation(): " + e.getMessage());
528     	}
529     	assertNotNull(llrInfo);
530     	assertEquals("81abea67-3bcc-4088-8348-e265f3670145", llrInfo.getLoId());
531     	assertEquals("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a", llrInfo.getRelatedLoId());
532     	assertEquals("kuali.lo.relation.type.includes", llrInfo.getType());
533     	assertEquals(DtoConstants.STATE_DRAFT, llrInfo.getState());
534         // Detecting expected errors
535         try {
536     		client.getLoLoRelation(null);
537             fail("MissingParameterException expected for loLoRelationId");
538         } catch (MissingParameterException e) {}
539     }
540     
541 	@Test
542 	public void testGetLoCategories() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
543 		List<LoCategoryInfo> categories = client.getLoCategories("kuali.loRepository.key.singleUse");
544 		assertEquals(5, categories.size());
545 		categories = client.getLoCategories("kuali.loRepository.key.state");
546 		assertTrue(null == categories || categories.size() == 0);
547 	}
548 	
549 	@Test
550 	public void testGetLoCategoriesForLo() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
551 		List<LoCategoryInfo> categories = client.getLoCategoriesForLo("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
552 		assertNotNull(categories);
553 		assertEquals(2, categories.size());
554 		categories = client.getLoCategoriesForLo("e0619a90-66d6-4af4-b357-e73ae44f7e88");
555 		assertEquals(1, categories.size());
556 		assertEquals("Test Category 3", categories.get(0).getName());
557 		categories = client.getLoCategoriesForLo("e0b456b2-62cb-4bd3-8867-a0d59fd8f2cf");
558 		assertTrue(null == categories || categories.size() == 0);
559 	}
560     
561 	@Test
562 	public void testAddRemoveLoCategoryToFromLo() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, AlreadyExistsException, PermissionDeniedException, UnsupportedActionException {
563 		List<LoCategoryInfo> categories = client.getLoCategoriesForLo("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
564 		assertEquals(2, categories.size());
565 		assertTrue(containsLoCatInfo(categories, Arrays.asList("550e8400-e29b-41d4-a716-446655440000", "7114d2a4-f66d-4d3a-9d41-a7aa4299c797")));
566 		client.addLoCategoryToLo("f2f02922-4e77-4144-aa07-8c2c956370dc", "dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
567 		categories = client.getLoCategoriesForLo("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
568 		assertEquals(3, categories.size());
569 		assertTrue(containsLoCatInfo(categories, Arrays.asList("550e8400-e29b-41d4-a716-446655440000", "7114d2a4-f66d-4d3a-9d41-a7aa4299c797", "f2f02922-4e77-4144-aa07-8c2c956370dc")));
570 		client.removeLoCategoryFromLo("f2f02922-4e77-4144-aa07-8c2c956370dc", "dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
571 		categories = client.getLoCategoriesForLo("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a");
572 		assertEquals(2, categories.size());
573 	}
574 
575     private boolean containsLoCatInfo(List<LoCategoryInfo> categories, List<String> idList) {
576     	List<String> ids = new ArrayList<String>();
577     	
578     	for (LoCategoryInfo info : categories) {
579     		ids.add(info.getId());
580     	}
581 		return ids.containsAll(idList);
582 	}
583 
584     @Test
585     public void testCreateLoLoRelation() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, AlreadyExistsException, CircularReferenceException, DataValidationErrorException, PermissionDeniedException, CircularRelationshipException {
586     	LoLoRelationInfo llrInfo = new LoLoRelationInfo();
587     	llrInfo.setLoId ("7bcd7c0e-3e6b-4527-ac55-254c58cecc22");
588      llrInfo.setRelatedLoId ("91a91860-d796-4a17-976b-a6165b1a0b05");
589      llrInfo.setType ("kuali.lo.relation.type.includes");
590     	try {
591     		llrInfo = client.createLoLoRelation(llrInfo.getLoId (), llrInfo.getRelatedLoId (), llrInfo.getType (), llrInfo);
592     	} catch (Exception e) {
593            fail("Exception caught when calling LearningObjectiveService.createLoLoRelation(): " + e.getMessage());
594     	}
595     	assertNotNull(llrInfo);
596     	llrInfo = client.getLoLoRelation(llrInfo.getId());
597     	assertEquals("7bcd7c0e-3e6b-4527-ac55-254c58cecc22", llrInfo.getLoId());
598     	assertEquals("91a91860-d796-4a17-976b-a6165b1a0b05", llrInfo.getRelatedLoId());
599     	assertEquals("kuali.lo.relation.type.includes", llrInfo.getType());
600     	assertEquals(DtoConstants.STATE_DRAFT, llrInfo.getState());
601         // Detecting expected errors
602         try {
603     		client.createLoLoRelation(null, "foo", "bar", llrInfo);
604             fail("MissingParameterException expected for loId");
605         } catch (MissingParameterException e) {}
606         try {
607     		client.createLoLoRelation("foo", null, "bar", llrInfo);
608             fail("MissingParameterException expected for relatedLoId");
609         } catch (MissingParameterException e) {}
610         try {
611     		client.createLoLoRelation("foo", "bar", null, llrInfo);
612             fail("MissingParameterException expected for loLoRelationType");
613         } catch (MissingParameterException e) {}
614         try {
615     		client.createLoLoRelation("foo", "bar", "baz", null);
616             fail("MissingParameterException expected for loLoRelationInfo");
617         } catch (MissingParameterException e) {}
618     }
619     
620     /*
621     @Test
622     public void testIncludedLo() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, AlreadyExistsException, CircularReferenceException, PermissionDeniedException, UnsupportedActionException, DependentObjectsExistException {
623         List<String> ancestors = client.getAncestors("E0B456B2-62CB-4BD3-8867-A0D59FD8F2CF"); 
624         assertTrue(!ancestors.contains("ABD8AE21-34E9-4858-A714-B04134F55D68"));
625         
626         StatusInfo result = client.addChildLoToLo("7BCD7C0E-3E6B-4527-AC55-254C58CECC22", "ABD8AE21-34E9-4858-A714-B04134F55D68");
627         assertNotNull(result);
628         assertTrue(result.getSuccess());
629         
630         ancestors = client.getAncestors("7BCD7C0E-3E6B-4527-AC55-254C58CECC22");
631         assertTrue(ancestors.contains("ABD8AE21-34E9-4858-A714-B04134F55D68")); 
632         
633         try {
634 	        result = client.addChildLoToLo("7BCD7C0E-3E6B-4527-AC55-254C58CECC22", "ABD8AE21-34E9-4858-A714-B04134F55D68");
635             fail("relationship should already exists and thus throw AlreadyExistsException");
636         } catch (AlreadyExistsException e) {
637         }
638         
639         List<String> descendants = client.getAllDescendants("ABD8AE21-34E9-4858-A714-B04134F55D68");
640         assertTrue(descendants.contains("7BCD7C0E-3E6B-4527-AC55-254C58CECC22"));
641         
642         assertTrue(client.isDescendant("ABD8AE21-34E9-4858-A714-B04134F55D68", "7BCD7C0E-3E6B-4527-AC55-254C58CECC22"));
643         
644         List<LoInfo> children = client.getLoChildren("ABD8AE21-34E9-4858-A714-B04134F55D68");
645         boolean foundLo = false;
646         for (LoInfo loInfo : children) {
647             if(loInfo.getId().equals("7BCD7C0E-3E6B-4527-AC55-254C58CECC22")) {
648                 foundLo = true;
649                 break;
650             }
651         }
652         assertTrue(foundLo);
653         
654         List<LoInfo> parents = client.getLoParents("7BCD7C0E-3E6B-4527-AC55-254C58CECC22"); 
655         foundLo = false;
656         for (LoInfo loInfo : parents) {
657             if(loInfo.getId().equals("ABD8AE21-34E9-4858-A714-B04134F55D68")) {
658                 foundLo = true;
659                 break;
660             }
661         }
662         assertTrue(foundLo);
663         
664         try { // this would result in "7B..." being orphaned
665 	        result = client.removeChildLoFromLo("7BCD7C0E-3E6B-4527-AC55-254C58CECC22", "ABD8AE21-34E9-4858-A714-B04134F55D68");
666 	        fail("LearningObjectiveService.removeChildLoFromLo should have thrown DependentObjectsExistException");
667         } catch (DependentObjectsExistException doee) {}
668         
669         // add it as a child to another parent
670         result = client.addChildLoToLo("7BCD7C0E-3E6B-4527-AC55-254C58CECC22", "DD0658D2-FDC9-48FA-9578-67A2CE53BF8A");
671         assertNotNull(result);
672         assertTrue(result.getSuccess());
673         
674         // and now remove it from "AB..."'s children
675         result = client.removeChildLoFromLo("7BCD7C0E-3E6B-4527-AC55-254C58CECC22", "ABD8AE21-34E9-4858-A714-B04134F55D68");
676         assertNotNull(result);
677         assertTrue(result.getSuccess());
678         
679         assertTrue(!client.isDescendant("ABD8AE21-34E9-4858-A714-B04134F55D68", "7BCD7C0E-3E6B-4527-AC55-254C58CECC22"));
680     }
681     */
682     
683     @Test
684     public void testLoCategory() throws OperationFailedException, DoesNotExistException, InvalidParameterException, MissingParameterException, DataValidationErrorException, PermissionDeniedException, VersionMismatchException, DependentObjectsExistException, AlreadyExistsException, UnsupportedActionException {
685         
686         List<LoCategoryInfo> categories = client.getLoCategories("foo.bar.baz");
687         assertTrue(null == categories || categories.isEmpty());
688         
689         LoCategoryInfo category = new LoCategoryInfo();
690         RichTextInfo richText = new RichTextInfo();
691         richText.setFormatted("<p>New Category</p>");
692         richText.setPlain("New Category");
693         category.setDesc(richText);
694         Date date = new Date();
695         category.setEffectiveDate(date);
696         category.setExpirationDate(date);
697         category.setName("BOB, THE AMAAAAAAZING WONDER LLAMA!!");
698         Map<String, String> attributes = new HashMap<String, String>();
699         attributes.put("attrKey", "attrValue");
700         category.setAttributes(attributes);
701         
702         
703         String categoryId = "550e8400-e29b-41d4-a716-446655440000";
704         
705         category = client.getLoCategory(categoryId);
706         assertEquals("Perception", category.getName());
707         assertEquals("loCategoryType.skillarea", category.getType());
708         category.setName("LENNY, THE LECHEROUS MILK THIEF");
709         category.setType("loCategoryType.accreditation");
710         
711         List<LoInfo> twoLos = client.getLosByLoCategory(categoryId);
712         assertTrue(null != twoLos);
713         assertEquals(2, twoLos.size());
714         assertTrue(twoLos.get(0).getId().equals("81abea67-3bcc-4088-8348-e265f3670145") ||
715         			twoLos.get(0).getId().equals("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a"));
716         assertTrue(twoLos.get(1).getId().equals("81abea67-3bcc-4088-8348-e265f3670145") ||
717         			twoLos.get(1).getId().equals("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a"));
718         
719         LoCategoryInfo updated = client.updateLoCategory(categoryId, category);
720         assertNotNull(updated);
721         assertNotNull(updated.getId());
722         
723         // make sure it all stuck
724         updated = client.getLoCategory(updated.getId());
725         assertEquals("LENNY, THE LECHEROUS MILK THIEF", updated.getName());
726         assertEquals("loCategoryType.accreditation", updated.getType());
727         
728         try {
729             client.updateLoCategory(categoryId, category);
730             fail("DataValidationErrorException expected: LO Category already exists");
731         } catch (VersionMismatchException e) {}
732            catch (DataValidationErrorException e) {}
733            
734         // switch to new LoCategory id; new one was created when we changed its type
735         String newCategoryId = updated.getId();
736         
737         // make sure it's new
738         assertFalse(categoryId.equals(newCategoryId));
739        
740         // make sure the LoCategories were cloned
741         List<LoInfo> los = client.getLosByLoCategory(newCategoryId);
742         assertEquals(2, los.size());
743         assertTrue(los.get(0).getId().equals("81abea67-3bcc-4088-8348-e265f3670145") ||
744         			los.get(0).getId().equals("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a"));
745         assertTrue(los.get(1).getId().equals("81abea67-3bcc-4088-8348-e265f3670145") ||
746         			los.get(1).getId().equals("dd0658d2-fdc9-48fa-9578-67a2ce53bf8a"));
747         
748         los = client.getLosByLoCategory(categoryId);
749         assertTrue(null == los || los.isEmpty());
750         
751         // add one to an LO that didn't have one
752         categoryId = "054caa88-c21d-4496-8287-36a311a11d68";
753         StatusInfo statusInfo = client.addLoCategoryToLo(categoryId, "91a91860-d796-4a17-976b-a6165b1a0b05");
754         assertTrue(statusInfo.getSuccess());
755         
756         los = client.getLosByLoCategory(categoryId);
757         assertEquals(1, los.size());
758         assertEquals("91a91860-d796-4a17-976b-a6165b1a0b05", los.get(0).getId());
759         
760         categories = client.getLoCategoriesForLo("91a91860-d796-4a17-976b-a6165b1a0b05");
761         assertEquals(1, categories.size());
762         
763         try {
764             statusInfo = client.deleteLoCategory(categoryId);
765             fail("DependentObjectsExistException expected"); 
766         } catch(DependentObjectsExistException e) {}
767         
768         statusInfo = client.removeLoCategoryFromLo(categoryId, "91a91860-d796-4a17-976b-a6165b1a0b05");
769         assertTrue(statusInfo.getSuccess());
770         
771         los = client.getLosByLoCategory(categoryId);
772         assertTrue(null == los || los.size() == 0);
773         statusInfo = client.deleteLoCategory(categoryId);
774         assertTrue(statusInfo.getSuccess());
775     }
776     
777 	@Test
778 	public void testSearchForResults() throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException{
779 		String testLoName = "Navigate Wiki";
780 		List<SearchParam> queryParamValues = new ArrayList<SearchParam>();
781 		SearchParam qpv1 = new SearchParam();
782 		qpv1.setKey("lo.queryParam.loName");
783 		qpv1.setValue(testLoName);
784 		queryParamValues.add(qpv1);
785 		SearchRequest searchRequest = new SearchRequest();
786 		searchRequest.setParams(queryParamValues);
787 		searchRequest.setSearchKey("lo.search.loByName");
788 		SearchResult result = client.search(searchRequest);
789 		assertEquals(1,result.getRows().size());
790 		
791         List<SearchResultCell> resultCells = result.getRows().get(0).getCells();
792         assertEquals(2, resultCells.size());
793         SearchResultCell cell = resultCells.get(0);
794         assertEquals("lo.resultColumn.loId", cell.getKey());
795         assertEquals("e0b456b2-62cb-4bd3-8867-a0d59fd8f2cf", cell.getValue());
796         cell = resultCells.get(1);
797         assertEquals("lo.resultColumn.loName", cell.getKey());
798         assertEquals(testLoName, cell.getValue());
799 	}
800 }