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.maintenance.MaintenanceDocumentBase;
32  import org.kuali.rice.krad.document.TransactionalDocumentBase;
33  import org.kuali.rice.krad.impls.RiceTestTransactionalDocument2;
34  import org.kuali.rice.krad.impls.RiceTestTransactionalDocument2Parent;
35  import org.kuali.rice.krad.test.document.AccountRequestDocument;
36  import org.kuali.rice.krad.test.document.bo.AccountType2;
37  import org.kuali.rice.krad.test.document.bo.AccountType2Parent;
38  import org.kuali.test.KRADTestCase;
39  
40  import static org.junit.Assert.*;
41  
42  /**
43   * This is a test case for the data dictionary's ability to index entries by a "base" superclass. 
44   * 
45   * @author Kuali Rice Team (rice.collab@kuali.org)
46   */
47  public class BaseBOClassAndBaseDocumentClassTest extends KRADTestCase {
48  
49  	DataDictionary dd = null;
50  
51  	/**
52  	 * Performs setup tasks similar to those in ExtensionAttributeTest.
53  	 */
54  	@Before
55  	public void setUp() throws Exception {
56  		super.setUp();
57  
58  		dd = new DataDictionary();
59  
60          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifControlDefinitions.xml");
61          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifConfigurationDefinitions.xml");
62          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifRiceDefinitions.xml");
63          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifFieldDefinitions.xml");
64          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifLookupDefinitions.xml");
65          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifInquiryDefinitions.xml");
66          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifGroupDefinitions.xml");
67          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifHeaderFooterDefinitions.xml");
68          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifLayoutManagerDefinitions.xml");
69          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifViewPageDefinitions.xml");
70          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifWidgetDefinitions.xml");
71          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifMaintenanceDefinitions.xml");
72          dd.addConfigFileLocation("classpath:org/kuali/rice/krad/uif/UifDocumentDefinitions.xml");
73  		//dd.addConfigFileLocation("classpath:org/kuali/rice/krad/bo/datadictionary");
74          dd.addConfigFileLocation("file:" + getUserDir() + "/../../impl/src/main/resources/org/kuali/rice/krad/bo/datadictionary");
75  		dd.addConfigFileLocation("classpath:org/kuali/rice/kns/bo/datadictionary/DataDictionaryBaseTypes.xml");
76  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/bo/datadictionary/EmploymentStatus.xml");
77  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/bo/datadictionary/EmploymentType.xml");
78  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/impl/identity/PersonImpl.xml");
79  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/bo/datadictionary/KimBaseBeans.xml");
80  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/impl/group/Group.xml");
81  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/impl/role/RoleBo.xml");
82  		dd.addConfigFileLocation("classpath:org/kuali/rice/kim/impl/type/KimType.xml");
83  		dd.addConfigFileLocation("classpath:org/kuali/rice/krad/test/document/");
84          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/campus/Campus.xml");
85          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/campus/CampusType.xml");
86          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/country/Country.xml");
87          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/state/State.xml");
88          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/county/County.xml");
89          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../location/web/src/main/resources/org/kuali/rice/location/web/postalcode/PostalCode.xml");
90          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/parameter/Parameter.xml");
91          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/parameter/ParameterType.xml");
92          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/namespace/Namespace.xml");
93          dd.addConfigFileLocation("file:" + getBaseDir() + "/../../core-service/web/src/main/resources/org/kuali/rice/coreservice/web/component/Component.xml");
94          dd.parseDataDictionaryConfigurationFiles( false );
95  	}
96  
97  	/**
98  	 * Performs tearDown tasks similar to those in ExtensionAttributeTest.
99  	 */
100 	@After
101 	public void tearDown() throws Exception {
102 		super.tearDown();
103 		dd = null;
104 	}
105 	
106 	/**
107 	 * This method tests to make sure that business object entries and document entries can only define regular and "base" classes that are compatible.
108 	 * 
109 	 * @throws Exception
110 	 */
111 	@Test
112 	public void testValidAndInvalidDDEntries() throws Exception {
113 		// Ensure that we cannot specify a base class that is not the superclass of the document/businessObject class.
114 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, DocumentBase.class, false);
115 		assertExpectedOutcomeOfDocEntryConstruction(TransactionalDocumentBase.class, MaintenanceDocumentBase.class, false);
116 		assertExpectedOutcomeOfBOEntryConstruction(TransactionalDocumentBase.class, AdHocRouteRecipient.class, false);
117 		assertExpectedOutcomeOfDocEntryConstruction(AccountRequestDocument.class, IdentityManagementKimDocument.class, false);
118 		
119 		// Ensure that we can specify a base class that is the superclass of the document/businessObject class.
120 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, AdHocRouteRecipient.class, true);
121 		assertExpectedOutcomeOfDocEntryConstruction(TransactionalDocumentBase.class, DocumentBase.class, true);
122 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRouteWorkgroup.class, AdHocRouteRecipient.class, true);
123 		assertExpectedOutcomeOfDocEntryConstruction(IdentityManagementPersonDocument.class, IdentityManagementKimDocument.class, true);
124 		
125 		// Ensure that we cannot specify a document/businessObject class that is a superclass of the base class.
126 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRouteRecipient.class, AdHocRoutePerson.class, false);
127 		assertExpectedOutcomeOfDocEntryConstruction(IdentityManagementKimDocument.class, IdentityManagementGroupDocument.class, false);
128 		
129 		// Ensure that we can specify the same class for both the document/businessObject class and the base class
130 		// (as permitted by the use of Class.isAssignableFrom in the BO and doc entry validations).
131 		assertExpectedOutcomeOfBOEntryConstruction(AdHocRoutePerson.class, AdHocRoutePerson.class, true);
132 		assertExpectedOutcomeOfDocEntryConstruction(MaintenanceDocumentBase.class, MaintenanceDocumentBase.class, true);
133 	}
134 	
135 	/**
136 	 * This method tests the DataDictionary's ability to grab entries based on a "base" class.
137 	 * 
138 	 * @throws Exception
139 	 */
140 	@Test
141 	public void testRetrieveDDEntriesByBaseClass() throws Exception {
142 		// Test the ability to retrieve a BusinessObjectEntry by "base" class, using both the full name and the simple name.
143 		String[] baseClassNames = {"AccountType2Parent", "AccountType2Parent"};
144 		String[] actualClassNames = {"AccountType2", "AccountType2"};
145 		for (int i = 0; i < baseClassNames.length; i++) {
146 			// Attempt to retrieve a BusinessObjectEntry that is indexed under AccountType2Parent, the "base" class of AccountType2.
147 			assertBusinessObjectEntryIsAccountType2(dd.getBusinessObjectEntry(baseClassNames[i]));
148 			// Now check to ensure that the same BusinessObjectEntry can still be retrieved by specifying the actual BO class name.
149 			assertBusinessObjectEntryIsAccountType2(dd.getBusinessObjectEntry(actualClassNames[i]));
150 		}
151 		
152 		// Test the ability to retrieve a DocumentEntry by "base" class, using both the full name and the simple name.
153 		baseClassNames = new String[] {"org.kuali.rice.krad.impls.RiceTestTransactionalDocument2Parent", "org.kuali.rice.krad.impls.RiceTestTransactionalDocument2Parent"};
154 		actualClassNames = new String[] {"org.kuali.rice.krad.impls.RiceTestTransactionalDocument2", "org.kuali.rice.krad.impls.RiceTestTransactionalDocument2"};
155 		for (int i = 0; i < baseClassNames.length; i++) {
156 			// Attempt to retrieve a DocumentEntry indexed under RiceTestTransactionalDocument2Parent, the "base" class of RiceTestTransactionalDocument2.
157 			assertDocumentEntryIsRiceTestTransactionalDocument2(dd.getDocumentEntry(baseClassNames[i]));
158 			// Now check to ensure that the same DocumentEntry can still be retrieved by specifying the actual document class name.
159 			assertDocumentEntryIsRiceTestTransactionalDocument2(dd.getDocumentEntry(actualClassNames[i]));
160 		}
161 		
162 		// 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,
163 		// 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
164 		// entry if it cannot be found in the entriesByJstlKey map.
165 		DataDictionaryEntry ddEntry = dd.getDictionaryObjectEntry("AccountType2");
166 		assertNotNull("The AccountType2 DD entry from the entriesByJstlKey map should not be null", ddEntry);
167 		assertTrue("The DD entry should have been a BusinessObjectEntry", ddEntry instanceof BusinessObjectEntry);
168 		assertBusinessObjectEntryIsAccountType2((BusinessObjectEntry) ddEntry);
169 	}
170 	
171 	/**
172 	 * A convenience method for testing the construction of a BusinessObjectEntry that has the given BO class and "base" class.
173 	 * 
174 	 * @param boClass The businessObjectClass of the entry.
175 	 * @param boBaseClass The "base" class of the entry.
176 	 * @param shouldSucceed Indicates whether the construction task should succeed or fail.
177 	 * @throws Exception
178 	 */
179 	private void assertExpectedOutcomeOfBOEntryConstruction(Class<? extends BusinessObject> boClass,
180 			Class<? extends BusinessObject> boBaseClass, boolean shouldSucceed) throws Exception {
181 		// Construct the entry and set the necessary properties.
182 		BusinessObjectEntry boEntry = new BusinessObjectEntry();
183 		boEntry.setBusinessObjectClass(boClass);
184 		boEntry.setBaseBusinessObjectClass(boBaseClass);
185 		boEntry.setObjectLabel(boClass.getSimpleName());
186 		// Now attempt to validate these properties.
187 		try {
188 			boEntry.completeValidation();
189 			// If the above operation succeeds, check whether or not the operation was meant to succeed.
190 			if (!shouldSucceed) {
191 				fail("The BO entry should have thrown a ClassValidationException during the validation process");
192 			}
193 		}
194 		catch (ClassValidationException e) {
195 			// If the above operation fails, check whether or not the operation was meant to fail.
196 			if (shouldSucceed) {
197 				fail("The BO entry should not have thrown a ClassValidationException during the validation process");
198 			}
199 		}
200 	}
201 	
202 	/**
203 	 * A convenience method for testing the construction of a DocumentEntry that has the given doc class and "base" class.
204 	 * 
205 	 * @param docClass The documentClass of the entry.
206 	 * @param docBaseClass The "base" class of the entry.
207 	 * @param shouldSucceed Indicates whether the construction task should succeed or fail.
208 	 * @throws Exception
209 	 */
210 	private void assertExpectedOutcomeOfDocEntryConstruction(Class<? extends Document> docClass,
211 			Class<? extends Document> docBaseClass, boolean shouldSucceed) throws Exception {
212 		// Construct the entry and set the necessary properties.
213 		DocumentEntry docEntry = new TransactionalDocumentEntry();
214 		docEntry.setDocumentClass(docClass);
215 		docEntry.setBaseDocumentClass(docBaseClass);
216 		// Now attempt to validate these properties.
217 		try {
218 			docEntry.completeValidation();
219 			// If the above operation succeeds, check whether or not the operation was meant to succeed.
220 			if (!shouldSucceed) {
221 				fail("The doc entry should have thrown a ClassValidationException during the validation process");
222 			}
223 		}
224 		catch (ClassValidationException e) {
225 			// If the above operation fails, check whether or not the operation was meant to fail.
226 			if (shouldSucceed) {
227 				fail("The doc entry should not have thrown a ClassValidationException during the validation process");
228 			}
229 		}
230 	}
231 	
232 	/**
233 	 * A convenience method for checking if a BusinessObjectEntry represents the AccountType2 DD entry.
234 	 * 
235 	 * @param boEntry The BusinessObjectEntry to test.
236 	 * @throws Exception
237 	 */
238 	private void assertBusinessObjectEntryIsAccountType2(BusinessObjectEntry boEntry) throws Exception {
239 		assertNotNull("The AccountType2 DD entry should not be null", boEntry);
240 		assertEquals("The DD entry does not represent the AccountType2 entry", AccountType2.class, boEntry.getBusinessObjectClass());
241 		assertEquals("The DD entry does not have the expected base class", AccountType2Parent.class, boEntry.getBaseBusinessObjectClass());
242 		assertEquals("The DD entry does not have the expected title attribute", "accountTypeCode2", boEntry.getTitleAttribute());
243 		assertEquals("The DD entry does not have the expected object label", "Account Type 2", boEntry.getObjectLabel());
244 	}
245 	
246 	/**
247 	 * A convenience method for checking if a DocumentEntry represents the RiceTestTransactionalDocument2 DD entry.
248 	 * 
249 	 * @param docEntry The DocumentEntry to test.
250 	 * @throws Exception
251 	 */
252 	private void assertDocumentEntryIsRiceTestTransactionalDocument2(DocumentEntry docEntry) throws Exception {
253 		assertNotNull("The RiceTestTransactionalDocument2 DD entry should not be null", docEntry);
254 		assertEquals("The DD entry does not represent the RiceTestTransactionalDocument2 entry",
255 				RiceTestTransactionalDocument2.class, docEntry.getDocumentClass());
256 		assertEquals("The DD entry does not have the expected base class", RiceTestTransactionalDocument2Parent.class, docEntry.getBaseDocumentClass());
257 	}
258 }