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