View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.datadictionary;
17  
18  import org.junit.After;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.kuali.rice.kim.document.IdentityManagementGroupDocument;
22  import org.kuali.rice.kim.document.IdentityManagementKimDocument;
23  import org.kuali.rice.kim.document.IdentityManagementPersonDocument;
24  import org.kuali.rice.krad.bo.AdHocRoutePerson;
25  import org.kuali.rice.krad.bo.AdHocRouteRecipient;
26  import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
27  import org.kuali.rice.krad.bo.BusinessObject;
28  import org.kuali.rice.krad.datadictionary.exception.ClassValidationException;
29  import org.kuali.rice.krad.document.Document;
30  import org.kuali.rice.krad.document.DocumentBase;
31  import org.kuali.rice.krad.impls.RiceTestTransactionalDocumentDivergent;
32  import org.kuali.rice.krad.impls.RiceTestTransactionalDocumentDivergentParent;
33  import org.kuali.rice.krad.maintenance.MaintenanceDocumentBase;
34  import org.kuali.rice.krad.document.TransactionalDocumentBase;
35  import org.kuali.rice.krad.impls.RiceTestTransactionalDocument2;
36  import org.kuali.rice.krad.impls.RiceTestTransactionalDocument2Parent;
37  import org.kuali.rice.krad.test.document.AccountRequestDocument;
38  import org.kuali.rice.krad.test.document.bo.AccountType2;
39  import org.kuali.rice.krad.test.document.bo.AccountType2Parent;
40  import org.kuali.rice.krad.test.document.bo.AccountTypeDivergent;
41  import org.kuali.rice.krad.test.document.bo.AccountTypeDivergentParent;
42  import org.kuali.test.KRADTestCase;
43  
44  import static org.junit.Assert.*;
45  
46  /**
47   * BaseBOClassAndBaseDocumentClassTest tests for the data dictionary's ability to index entries by a "base" superclass
48   *
49   * <p>When running this test, the working directory should be set to two levels down from the root of the project e.g.
50   * it/krad</p>
51   * 
52   * @author Kuali Rice Team (rice.collab@kuali.org)
53   */
54  public class BaseBOClassAndBaseDocumentClassTest extends KRADTestCase {
55  
56  	DataDictionary dd = null;
57  
58  	/**
59  	 * Performs setup tasks similar to those in ExtensionAttributeTest.
60  	 */
61  	@Before
62  	public void setUp() throws Exception {
63  		super.setUp();
64  
65  		dd = new DataDictionary();
66  
67          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifControlDefinitions.xml");
68          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifFieldDefinitions.xml");
69          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifGroupDefinitions.xml");
70          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifHeaderFooterDefinitions.xml");
71          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifLayoutManagerDefinitions.xml");
72          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifViewPageDefinitions.xml");
73          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifWidgetDefinitions.xml");
74          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifConfigurationDefinitions.xml");
75          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifRiceDefinitions.xml");
76          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifLookupDefinitions.xml");
77          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifInquiryDefinitions.xml");
78          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifMaintenanceDefinitions.xml");
79          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifDocumentDefinitions.xml");
80          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifElementDefinitions.xml");
81          dd.addConfigFileLocation("KR-NS", "classpath:org/kuali/rice/krad/uif/UifActionDefinitions.xml");
82  		//dd.addConfigFileLocation("classpath:org/kuali/rice/krad/bo/datadictionary");
83          dd.addConfigFileLocation("KR-NS","file:" + getUserDir() + "/../../impl/src/main/resources/org/kuali/rice/krad/bo/datadictionary");
84  		dd.addConfigFileLocation("KR-NS","classpath:org/kuali/rice/kns/bo/datadictionary/DataDictionaryBaseTypes.xml");
85  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/bo/datadictionary/EmploymentStatus.xml");
86  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/bo/datadictionary/EmploymentType.xml");
87  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/impl/identity/PersonImpl.xml");
88  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/bo/datadictionary/KimBaseBeans.xml");
89  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/impl/group/Group.xml");
90  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/impl/role/RoleBo.xml");
91  		dd.addConfigFileLocation("KR-KIM","classpath:org/kuali/rice/kim/impl/type/KimType.xml");
92  		dd.addConfigFileLocation("KR-NS","classpath:org/kuali/rice/krad/test/document/");
93          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/campus/Campus.xml");
94          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/campus/CampusType.xml");
95          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/country/Country.xml");
96          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/state/State.xml");
97          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/county/County.xml");
98          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/postalcode/PostalCode.xml");
99          dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/parameter/Parameter.xml");
100         dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/parameter/ParameterType.xml");
101         dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/namespace/Namespace.xml");
102         dd.addConfigFileLocation("KR-NS","file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/component/Component.xml");
103         dd.parseDataDictionaryConfigurationFiles( false );
104 	}
105 
106 	/**
107 	 * Performs tearDown tasks similar to those in ExtensionAttributeTest.
108 	 */
109 	@After
110 	public void tearDown() throws Exception {
111 		super.tearDown();
112 		dd = null;
113 	}
114 	
115 	/**
116 	 * This method tests to make sure that business object entries and document entries can only define regular and "base" classes that are compatible.
117 	 * 
118 	 * @throws Exception
119 	 */
120 	@Test
121 	public void testValidAndInvalidDDEntries() throws Exception {
122 		// Ensure that we can specify a base class that is not the superclass of the document/businessObject class.
123 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, DocumentBase.class, true);
124 		assertExpectedOutcomeOfDocEntryConstruction(TransactionalDocumentBase.class, MaintenanceDocumentBase.class, true);
125 		assertExpectedOutcomeOfBOEntryConstruction(TransactionalDocumentBase.class, AdHocRouteRecipient.class, true);
126 		assertExpectedOutcomeOfDocEntryConstruction(AccountRequestDocument.class, IdentityManagementKimDocument.class, true);
127 		
128 		// Ensure that we can specify a base class that is the superclass of the document/businessObject class.
129 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, AdHocRouteRecipient.class, true);
130 		assertExpectedOutcomeOfDocEntryConstruction(TransactionalDocumentBase.class, DocumentBase.class, true);
131 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRouteWorkgroup.class, AdHocRouteRecipient.class, true);
132 		assertExpectedOutcomeOfDocEntryConstruction(IdentityManagementPersonDocument.class, IdentityManagementKimDocument.class, true);
133 		
134 		// Ensure that we can specify a document/businessObject class that is a superclass of the base class.
135 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRouteRecipient.class, AdHocRoutePerson.class, true);
136 		assertExpectedOutcomeOfDocEntryConstruction(IdentityManagementKimDocument.class, IdentityManagementGroupDocument.class, true);
137 		
138 		// Ensure that we can specify the same class for both the document/businessObject class and the base class
139 		// (as permitted by the use of Class.isAssignableFrom in the BO and doc entry validations).
140 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, AdHocRoutePerson.class, true);
141 		assertExpectedOutcomeOfDocEntryConstruction(MaintenanceDocumentBase.class, MaintenanceDocumentBase.class, true);
142 	}
143 	
144 	/**
145 	 * This method tests the DataDictionary's ability to grab entries based on a "base" class.
146 	 * 
147 	 * @throws Exception
148 	 */
149 	@Test
150 	public void testRetrieveDDEntriesByBaseClass() throws Exception {
151 		// Test the ability to retrieve a BusinessObjectEntry by "base" class, using both the full name and the simple name.
152         Object[][] tests = {
153             { "AccountType2Parent", "AccountType2",
154                AccountType2.class, AccountType2Parent.class, "accountTypeCode2", "Account Type 2" },
155             { "org.kuali.rice.krad.test.document.bo.AccountType2Parent", "org.kuali.rice.krad.test.document.bo.AccountType2",
156                AccountType2.class, AccountType2Parent.class, "accountTypeCode2", "Account Type 2" },
157             { "AccountTypeDivergentParent", "AccountTypeDivergent",
158                AccountTypeDivergent.class, AccountTypeDivergentParent.class, "accountTypeCode Divergent", "Account Type Divergent" },
159             { "org.kuali.rice.krad.test.document.bo.AccountTypeDivergentParent", "org.kuali.rice.krad.test.document.bo.AccountTypeDivergent",
160                AccountTypeDivergent.class, AccountTypeDivergentParent.class, "accountTypeCode Divergent", "Account Type Divergent" }
161         };
162 		for (Object[] test: tests) {
163 			// Attempt to retrieve a BusinessObjectEntry that is indexed under the "base" class.
164 			assertBusinessObjectEntry(dd.getBusinessObjectEntry((String) test[0]), (Class) test[2], (Class) test[3], (String) test[4], (String) test[5]);
165 			// Now check to ensure that the same BusinessObjectEntry can still be retrieved by specifying the actual BO class name.
166             assertBusinessObjectEntry(dd.getBusinessObjectEntry((String) test[1]), (Class) test[2], (Class) test[3], (String) test[4], (String) test[5]);
167 		}
168 		
169 		// Test the ability to retrieve a DocumentEntry by "base" class, using both the full name and the simple name.
170         tests = new Object[][] {
171             { "RiceTestTransactionalDocument2Parent", "RiceTestTransactionalDocument2",
172                RiceTestTransactionalDocument2.class, RiceTestTransactionalDocument2Parent.class },
173             { "org.kuali.rice.krad.impls.RiceTestTransactionalDocument2Parent", "org.kuali.rice.krad.impls.RiceTestTransactionalDocument2",
174                RiceTestTransactionalDocument2.class, RiceTestTransactionalDocument2Parent.class },
175             { "RiceTestTransactionalDocumentDivergentParent", "RiceTestTransactionalDocumentDivergent",
176                RiceTestTransactionalDocumentDivergent.class, RiceTestTransactionalDocumentDivergentParent.class },
177             { "org.kuali.rice.krad.impls.RiceTestTransactionalDocumentDivergentParent", "org.kuali.rice.krad.impls.RiceTestTransactionalDocumentDivergent",
178                RiceTestTransactionalDocumentDivergent.class, RiceTestTransactionalDocumentDivergentParent.class }
179         };
180         for (Object[] test: tests) {
181 			// Attempt to retrieve a DocumentEntry indexed under the "base" class
182             assertDocumentEntry(dd.getDocumentEntry((String) test[0]), (Class) test[2], (Class) test[3]);
183 			// Now check to ensure that the same DocumentEntry can still be retrieved by specifying the actual document class name.
184             assertDocumentEntry(dd.getDocumentEntry((String) test[1]), (Class) test[2], (Class) test[3]);
185 		}
186 		
187 		// Test the ability to retrieve a BusinessObjectEntry by JSTL key, where the "base" class's simple name is the JSTL key if it is defined. However,
188 		// the getDictionaryObjectEntry could still find the object even if the JSTL key map doesn't have it, since it checks the other maps for the
189 		// entry if it cannot be found in the entriesByJstlKey map.
190 		DataDictionaryEntry ddEntry = dd.getDictionaryObjectEntry("AccountType2");
191 		assertNotNull("The AccountType2 DD entry from the entriesByJstlKey map should not be null", ddEntry);
192 		assertTrue("The DD entry should have been a BusinessObjectEntry", ddEntry instanceof BusinessObjectEntry);
193 		assertBusinessObjectEntryIsAccountType2((BusinessObjectEntry) ddEntry);
194 	}
195 	
196 	/**
197 	 * A convenience method for testing the construction of a BusinessObjectEntry that has the given BO class and "base" class.
198 	 * 
199 	 * @param boClass The businessObjectClass of the entry.
200 	 * @param boBaseClass The "base" class of the entry.
201 	 * @param shouldSucceed Indicates whether the construction task should succeed or fail.
202 	 * @throws Exception
203 	 */
204 	private void assertExpectedOutcomeOfBOEntryConstruction(Class<? extends BusinessObject> boClass,
205 			Class<? extends BusinessObject> boBaseClass, boolean shouldSucceed) throws Exception {
206 		// Construct the entry and set the necessary properties.
207 		BusinessObjectEntry boEntry = new BusinessObjectEntry();
208 		boEntry.setBusinessObjectClass(boClass);
209 		boEntry.setBaseBusinessObjectClass(boBaseClass);
210 		boEntry.setObjectLabel(boClass.getSimpleName());
211 		// Now attempt to validate these properties.
212 		try {
213 			boEntry.completeValidation();
214 			// If the above operation succeeds, check whether or not the operation was meant to succeed.
215 			if (!shouldSucceed) {
216 				fail("The BO entry should have thrown a ClassValidationException during the validation process");
217 			}
218 		}
219 		catch (ClassValidationException e) {
220 			// If the above operation fails, check whether or not the operation was meant to fail.
221 			if (shouldSucceed) {
222 				fail("The BO entry should not have thrown a ClassValidationException during the validation process");
223 			}
224 		}
225 	}
226 	
227 	/**
228 	 * A convenience method for testing the construction of a DocumentEntry that has the given doc class and "base" class.
229 	 * 
230 	 * @param docClass The documentClass of the entry.
231 	 * @param docBaseClass The "base" class of the entry.
232 	 * @param shouldSucceed Indicates whether the construction task should succeed or fail.
233 	 * @throws Exception
234 	 */
235 	private void assertExpectedOutcomeOfDocEntryConstruction(Class<? extends Document> docClass,
236 			Class<? extends Document> docBaseClass, boolean shouldSucceed) throws Exception {
237 		// Construct the entry and set the necessary properties.
238 		DocumentEntry docEntry = new TransactionalDocumentEntry();
239 		docEntry.setDocumentClass(docClass);
240 		docEntry.setBaseDocumentClass(docBaseClass);
241 		// Now attempt to validate these properties.
242 		try {
243 			docEntry.completeValidation();
244 			// If the above operation succeeds, check whether or not the operation was meant to succeed.
245 			if (!shouldSucceed) {
246 				fail("The doc entry should have thrown a ClassValidationException during the validation process");
247 			}
248 		}
249 		catch (ClassValidationException e) {
250 			// If the above operation fails, check whether or not the operation was meant to fail.
251 			if (shouldSucceed) {
252 				fail("The doc entry should not have thrown a ClassValidationException during the validation process");
253 			}
254 		}
255 	}
256 	
257 	/**
258 	 * A convenience method for checking if a BusinessObjectEntry represents the AccountType2 DD entry.
259 	 * 
260 	 * @param boEntry The BusinessObjectEntry to test.
261 	 * @throws Exception
262 	 */
263 	private void assertBusinessObjectEntryIsAccountType2(BusinessObjectEntry boEntry) throws Exception {
264         assertBusinessObjectEntry(boEntry, AccountType2.class, AccountType2Parent.class, "accountTypeCode2", "Account Type 2");
265 	}
266 
267     /**
268      * A convenience method for checking if a BusinessObjectEntry represents the correct DD entry.
269      *
270      * @param boEntry The BusinessObjectEntry to test.
271      * @throws Exception
272      */
273     private void assertBusinessObjectEntry(BusinessObjectEntry boEntry, Class boClass, Class boBaseClass, String title, String label) throws Exception {
274         assertNotNull("The DD entry should not be null", boEntry);
275         assertEquals("The DD entry does not represent the " + boClass.getName() + " entry", boClass, boEntry.getBusinessObjectClass());
276         assertEquals("The DD entry does not have the expected base class", boBaseClass, boEntry.getBaseBusinessObjectClass());
277         assertEquals("The DD entry does not have the expected title attribute", title, boEntry.getTitleAttribute());
278         assertEquals("The DD entry does not have the expected object label", label, boEntry.getObjectLabel());
279     }
280 
281     /**
282      * A convenience method for checking if a DocumentEntry represents the correct DD entry.
283      *
284      * @param docEntry The DocumentEntry to test.
285      * @throws Exception
286      */
287     private void assertDocumentEntry(DocumentEntry docEntry, Class docClass, Class baseDocClass) throws Exception {
288         assertNotNull("The RiceTestTransactionalDocument2 DD entry should not be null", docEntry);
289         assertEquals("The DD entry does not represent the RiceTestTransactionalDocument2 entry",
290                 docClass, docEntry.getDocumentClass());
291         assertEquals("The DD entry does not have the expected base class", baseDocClass, docEntry.getBaseDocumentClass());
292     }
293 }