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