View Javadoc

1   /*
2    * Copyright 2007-2008 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.kns.service.impl;
17  
18  import java.util.Collection;
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.beanutils.PropertyUtils;
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.rice.kim.bo.Person;
27  import org.kuali.rice.kim.bo.impl.KimAttributes;
28  import org.kuali.rice.kim.bo.types.dto.AttributeSet;
29  import org.kuali.rice.kim.service.IdentityManagementService;
30  import org.kuali.rice.kim.service.KIMServiceLocator;
31  import org.kuali.rice.kim.util.KimCommonUtils;
32  import org.kuali.rice.kim.util.KimConstants;
33  import org.kuali.rice.kns.authorization.BusinessObjectAuthorizer;
34  import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
35  import org.kuali.rice.kns.authorization.BusinessObjectRestrictionsBase;
36  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentAuthorizer;
37  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentPresentationController;
38  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentRestrictions;
39  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentRestrictionsBase;
40  import org.kuali.rice.kns.bo.BusinessObject;
41  import org.kuali.rice.kns.datadictionary.AttributeDefinition;
42  import org.kuali.rice.kns.datadictionary.AttributeSecurity;
43  import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
44  import org.kuali.rice.kns.datadictionary.DataDictionaryEntryBase;
45  import org.kuali.rice.kns.datadictionary.FieldDefinition;
46  import org.kuali.rice.kns.datadictionary.InquiryCollectionDefinition;
47  import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
48  import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
49  import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
50  import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
51  import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
52  import org.kuali.rice.kns.document.Document;
53  import org.kuali.rice.kns.document.MaintenanceDocument;
54  import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
55  import org.kuali.rice.kns.document.authorization.DocumentPresentationController;
56  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentAuthorizer;
57  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentPresentationController;
58  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
59  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictionsBase;
60  import org.kuali.rice.kns.inquiry.InquiryAuthorizer;
61  import org.kuali.rice.kns.inquiry.InquiryPresentationController;
62  import org.kuali.rice.kns.inquiry.InquiryRestrictions;
63  import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
64  import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
65  import org.kuali.rice.kns.service.DataDictionaryService;
66  import org.kuali.rice.kns.service.DocumentHelperService;
67  import org.kuali.rice.kns.service.KNSServiceLocator;
68  import org.kuali.rice.kns.service.KualiConfigurationService;
69  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
70  import org.kuali.rice.kns.util.KNSConstants;
71  import org.kuali.rice.kns.util.ObjectUtils;
72  
73  public class BusinessObjectAuthorizationServiceImpl implements
74  		BusinessObjectAuthorizationService {
75  	private DataDictionaryService dataDictionaryService;
76  	private IdentityManagementService identityManagementService;
77  	private BusinessObjectDictionaryService businessObjectDictionaryService;
78  	private DocumentHelperService documentHelperService;
79  	private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
80  	private KualiConfigurationService kualiConfigurationService;
81  	
82  	public BusinessObjectRestrictions getLookupResultRestrictions(
83  			BusinessObject businessObject, Person user) {
84  		BusinessObjectRestrictions businessObjectRestrictions = new BusinessObjectRestrictionsBase();
85  		considerBusinessObjectFieldUnmaskAuthorization(businessObject, user,
86  				businessObjectRestrictions, "", null);
87  		return businessObjectRestrictions;
88  	}
89  
90  	public InquiryRestrictions getInquiryRestrictions(
91  			BusinessObject businessObject, Person user) {
92  		InquiryRestrictions inquiryRestrictions = new InquiryOrMaintenanceDocumentRestrictionsBase();
93  		BusinessObjectEntry businessObjectEntry = getDataDictionaryService()
94  				.getDataDictionary().getBusinessObjectEntry(
95  						businessObject.getClass().getName());
96  		InquiryPresentationController inquiryPresentationController = getBusinessObjectDictionaryService()
97  				.getInquiryPresentationController(businessObject.getClass());
98  		InquiryAuthorizer inquiryAuthorizer = getBusinessObjectDictionaryService()
99  				.getInquiryAuthorizer(businessObject.getClass());
100 		considerBusinessObjectFieldUnmaskAuthorization(businessObject, user,
101 				inquiryRestrictions, "", null);
102 		considerBusinessObjectFieldViewAuthorization(businessObjectEntry,
103 				businessObject, null, user, inquiryAuthorizer, inquiryRestrictions,
104 				"");
105 		considerInquiryOrMaintenanceDocumentPresentationController(
106 				inquiryPresentationController, businessObject,
107 				inquiryRestrictions);
108 		considerInquiryOrMaintenanceDocumentAuthorizer(inquiryAuthorizer,
109 				businessObject, user, inquiryRestrictions);
110 		for (InquirySectionDefinition inquirySectionDefinition : businessObjectEntry.getInquiryDefinition().getInquirySections()) {
111 			if (inquirySectionDefinition.getInquiryCollections() != null) {
112 				addInquirableItemRestrictions(inquirySectionDefinition.getInquiryCollections().values(), inquiryAuthorizer, 
113 						inquiryRestrictions, businessObject, businessObject, "", user);
114 			}
115 			// Collections may also be stored in the inquiry fields, so we need to parse through that
116 			List<FieldDefinition> inquiryFields = inquirySectionDefinition.getInquiryFields();
117 			if (inquiryFields != null) {
118 				for (FieldDefinition fieldDefinition : inquiryFields) {
119 					addInquirableItemRestrictions(inquiryFields, inquiryAuthorizer, 
120 							inquiryRestrictions, businessObject, businessObject, "", user);
121 				}
122 			}
123 		}
124 		
125 		return inquiryRestrictions;
126 	}
127 
128 	public MaintenanceDocumentRestrictions getMaintenanceDocumentRestrictions(
129 			MaintenanceDocument maintenanceDocument, Person user) {
130 
131 		MaintenanceDocumentRestrictions maintenanceDocumentRestrictions = new MaintenanceDocumentRestrictionsBase();
132 		BusinessObjectEntry businessObjectEntry = getDataDictionaryService()
133 				.getDataDictionary().getBusinessObjectEntry(
134 						maintenanceDocument.getNewMaintainableObject()
135 								.getBusinessObject().getClass().getName());
136 		MaintenanceDocumentPresentationController maintenanceDocumentPresentationController = (MaintenanceDocumentPresentationController) getDocumentHelperService()
137 				.getDocumentPresentationController(maintenanceDocument);
138 		MaintenanceDocumentAuthorizer maintenanceDocumentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService()
139 				.getDocumentAuthorizer(maintenanceDocument);
140 		considerBusinessObjectFieldUnmaskAuthorization(maintenanceDocument
141 				.getNewMaintainableObject().getBusinessObject(), user,
142 				maintenanceDocumentRestrictions, "", maintenanceDocument );
143 		considerBusinessObjectFieldViewAuthorization(businessObjectEntry,
144 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
145 				null, user, maintenanceDocumentAuthorizer,
146 				maintenanceDocumentRestrictions, "");
147 		considerBusinessObjectFieldModifyAuthorization(businessObjectEntry,
148 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
149 				null, user, maintenanceDocumentAuthorizer,
150 				maintenanceDocumentRestrictions, "");
151 		considerCustomButtonFieldAuthorization(businessObjectEntry,
152 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
153 				null, user, maintenanceDocumentAuthorizer,
154 				maintenanceDocumentRestrictions, "");
155 		considerInquiryOrMaintenanceDocumentPresentationController(
156 				maintenanceDocumentPresentationController, maintenanceDocument,
157 				maintenanceDocumentRestrictions);
158 		considerInquiryOrMaintenanceDocumentAuthorizer(
159 				maintenanceDocumentAuthorizer, maintenanceDocument, user,
160 				maintenanceDocumentRestrictions);
161 		considerMaintenanceDocumentPresentationController(
162 				maintenanceDocumentPresentationController, maintenanceDocument,
163 				maintenanceDocumentRestrictions);
164 		considerMaintenanceDocumentAuthorizer(maintenanceDocumentAuthorizer,
165 				maintenanceDocument, user, maintenanceDocumentRestrictions);
166 		
167 		MaintenanceDocumentEntry maintenanceDocumentEntry = getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(maintenanceDocument
168 				.getDocumentHeader().getWorkflowDocument().getDocumentType());
169 		for (MaintainableSectionDefinition maintainableSectionDefinition : maintenanceDocumentEntry.getMaintainableSections()) {
170 			addMaintainableItemRestrictions(maintainableSectionDefinition.getMaintainableItems(), maintenanceDocumentAuthorizer, maintenanceDocumentRestrictions,
171 					maintenanceDocument, maintenanceDocument.getNewMaintainableObject().getBusinessObject(), "", user);
172 		}
173 		return maintenanceDocumentRestrictions;
174 	}
175 
176 	protected void considerBusinessObjectFieldUnmaskAuthorization(
177 			BusinessObject businessObject, Person user,
178 			BusinessObjectRestrictions businessObjectRestrictions,
179 			String propertyPrefix, Document document ) {
180 		DataDictionaryEntryBase dictionaryEntry = (DataDictionaryEntryBase)getDataDictionaryService()
181 				.getDataDictionary().getDictionaryObjectEntry(
182 						businessObject.getClass().getName());
183 		for (String attributeName : dictionaryEntry.getAttributeNames()) {
184 			AttributeDefinition attributeDefinition = dictionaryEntry
185 					.getAttributeDefinition(attributeName);
186 			if (attributeDefinition.getAttributeSecurity() != null) {
187 				if (attributeDefinition.getAttributeSecurity().isMask()
188 						&& !canFullyUnmaskField(user,
189 								businessObject.getClass(), attributeName, document)) {
190 					businessObjectRestrictions.addFullyMaskedField(
191 							propertyPrefix + attributeName, attributeDefinition
192 									.getAttributeSecurity().getMaskFormatter());
193 				}
194 				if (attributeDefinition.getAttributeSecurity().isPartialMask()
195 						&& !canPartiallyUnmaskField(user, businessObject
196 								.getClass(), attributeName, document)) {
197 					businessObjectRestrictions.addPartiallyMaskedField(
198 							propertyPrefix + attributeName, attributeDefinition
199 									.getAttributeSecurity()
200 									.getPartialMaskFormatter());
201 				}
202 			}
203 		}
204 	}
205 
206 	/**
207 	 * @param dictionaryObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
208 	 * Otherwise, it is the entry for primaryBusinessObject
209 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
210 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
211 	 * @param user the logged in user
212 	 * @param businessObjectAuthorizer
213 	 * @param inquiryOrMaintenanceDocumentRestrictions
214 	 * @param propertyPrefix
215 	 */
216 	protected void considerBusinessObjectFieldViewAuthorization(
217 			DataDictionaryEntryBase dictionaryObjectEntry,
218 			BusinessObject primaryBusinessObject,
219 			BusinessObject collectionItemBusinessObject,
220 			Person user,
221 			BusinessObjectAuthorizer businessObjectAuthorizer,
222 			InquiryOrMaintenanceDocumentRestrictions inquiryOrMaintenanceDocumentRestrictions,
223 			String propertyPrefix) {
224 		for (String attributeName : dictionaryObjectEntry.getAttributeNames()) {
225 			AttributeDefinition attributeDefinition = dictionaryObjectEntry
226 					.getAttributeDefinition(attributeName);
227 			if (attributeDefinition.getAttributeSecurity() != null) {
228 				if (attributeDefinition.getAttributeSecurity().isHide()) {
229 					AttributeSet collectionItemPermissionDetails = new AttributeSet();
230 					AttributeSet collectionItemRoleQualifications = null;
231 					if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
232 						collectionItemPermissionDetails.putAll(getFieldPermissionDetails(collectionItemBusinessObject, attributeName));
233 						collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
234 								getCollectionItemPermissionDetails(collectionItemBusinessObject));
235 						collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
236 								getCollectionItemRoleQualifications(collectionItemBusinessObject));
237 					}
238 					else {
239 						collectionItemPermissionDetails.putAll(getFieldPermissionDetails(primaryBusinessObject, attributeName));
240 					}
241 					if (!businessObjectAuthorizer
242 							.isAuthorizedByTemplate(
243 									primaryBusinessObject,
244 									KNSConstants.KNS_NAMESPACE,
245 									KimConstants.PermissionTemplateNames.VIEW_FIELD,
246 									user.getPrincipalId(),
247 									collectionItemPermissionDetails,
248 									collectionItemRoleQualifications)) {
249 						inquiryOrMaintenanceDocumentRestrictions
250 								.addHiddenField(propertyPrefix + attributeName);
251 					}
252 				}
253 			}
254 		}
255 	}
256 
257 	/**
258 	 * @param businessObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
259 	 * Otherwise, it is the entry for primaryBusinessObject
260 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
261 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
262 	 * @param user the logged in user
263 	 * @param businessObjectAuthorizer
264 	 * @param inquiryOrMaintenanceDocumentRestrictions
265 	 * @param propertyPrefix
266 	 */
267 	protected void considerBusinessObjectFieldModifyAuthorization(
268 			BusinessObjectEntry businessObjectEntry,
269 			BusinessObject primaryBusinessObject,
270 			BusinessObject collectionItemBusinessObject, Person user,
271 			BusinessObjectAuthorizer businessObjectAuthorizer,
272 			MaintenanceDocumentRestrictions maintenanceDocumentRestrictions,
273 			String propertyPrefix) {
274 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
275 			AttributeDefinition attributeDefinition = businessObjectEntry
276 					.getAttributeDefinition(attributeName);
277 			if (attributeDefinition.getAttributeSecurity() != null) {
278 				AttributeSet collectionItemPermissionDetails = new AttributeSet();
279 				AttributeSet collectionItemRoleQualifications = null;
280 				if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
281 					collectionItemPermissionDetails.putAll(getFieldPermissionDetails(collectionItemBusinessObject, attributeName));
282 					collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
283 							getCollectionItemPermissionDetails(collectionItemBusinessObject));
284 					collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
285 							getCollectionItemRoleQualifications(collectionItemBusinessObject));
286 				}
287 				else {
288 					collectionItemPermissionDetails.putAll(getFieldPermissionDetails(primaryBusinessObject, attributeName));
289 				}
290 				if (attributeDefinition.getAttributeSecurity().isReadOnly()) {
291 					if (!businessObjectAuthorizer
292 								.isAuthorizedByTemplate(
293 										primaryBusinessObject,
294 										KNSConstants.KNS_NAMESPACE,
295 										KimConstants.PermissionTemplateNames.MODIFY_FIELD,
296 										user.getPrincipalId(),
297 										collectionItemPermissionDetails,
298 										collectionItemRoleQualifications)) {
299 						maintenanceDocumentRestrictions
300 								.addReadOnlyField(propertyPrefix + attributeName);
301 					}
302 				}
303 			}
304 		}
305 	}
306 	
307 	/**
308 	 * @param businessObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
309 	 * Otherwise, it is the entry for primaryBusinessObject
310 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
311 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
312 	 * @param user the logged in user
313 	 * @param businessObjectAuthorizer
314 	 * @param inquiryOrMaintenanceDocumentRestrictions
315 	 * @param propertyPrefix
316 	 */
317 	protected void considerCustomButtonFieldAuthorization(
318 			BusinessObjectEntry businessObjectEntry,
319 			BusinessObject primaryBusinessObject,
320 			BusinessObject collectionItemBusinessObject,
321 			Person user,
322 			BusinessObjectAuthorizer businessObjectAuthorizer,
323 			MaintenanceDocumentRestrictions maintenanceDocumentRestrictions,
324 			String propertyPrefix) {
325 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
326 			AttributeDefinition attributeDefinition = businessObjectEntry
327 					.getAttributeDefinition(attributeName);
328 			if (attributeDefinition.getControl().isButton()) {
329 				AttributeSet collectionItemPermissionDetails = new AttributeSet();
330 				AttributeSet collectionItemRoleQualifications = null;
331 				if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
332 					collectionItemPermissionDetails.putAll(getButtonFieldPermissionDetails(collectionItemBusinessObject, attributeName));
333 					collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
334 							getCollectionItemPermissionDetails(collectionItemBusinessObject));
335 					collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
336 							getCollectionItemRoleQualifications(collectionItemBusinessObject));
337 				}
338 				else {
339 					getButtonFieldPermissionDetails(primaryBusinessObject, attributeName);
340 				}
341 				
342 				if (!businessObjectAuthorizer
343 						.isAuthorizedByTemplate(
344 								primaryBusinessObject,
345 								KNSConstants.KNS_NAMESPACE,
346 								KimConstants.PermissionTemplateNames.PERFORM_CUSTOM_MAINTENANCE_DOCUMENT_FUNCTION,
347 								user.getPrincipalId(),
348 								collectionItemPermissionDetails,
349 								collectionItemRoleQualifications)) {
350 					maintenanceDocumentRestrictions
351 							.addHiddenField(propertyPrefix + attributeName);
352 				}
353 			}
354 		}
355 	}
356 
357 	protected void considerInquiryOrMaintenanceDocumentPresentationController(
358 			InquiryOrMaintenanceDocumentPresentationController businessObjectPresentationController,
359 			BusinessObject businessObject,
360 			InquiryOrMaintenanceDocumentRestrictions inquiryOrMaintenanceDocumentRestrictions) {
361 		for (String attributeName : businessObjectPresentationController
362 				.getConditionallyHiddenPropertyNames(businessObject)) {
363 			inquiryOrMaintenanceDocumentRestrictions
364 					.addHiddenField(attributeName);
365 		}
366 		for (String sectionId : businessObjectPresentationController
367 				.getConditionallyHiddenSectionIds(businessObject)) {
368 			inquiryOrMaintenanceDocumentRestrictions
369 					.addHiddenSectionId(sectionId);
370 		}
371 	}
372 
373 	protected void considerInquiryOrMaintenanceDocumentAuthorizer(
374 			InquiryOrMaintenanceDocumentAuthorizer authorizer,
375 			BusinessObject businessObject, Person user,
376 			InquiryOrMaintenanceDocumentRestrictions restrictions) {
377 		for (String sectionId : authorizer
378 				.getSecurePotentiallyHiddenSectionIds()) {
379 			Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
380 			additionalPermissionDetails
381 					.put(KimAttributes.SECTION_ID, sectionId);
382 			if (!authorizer.isAuthorizedByTemplate(businessObject,
383 					KNSConstants.KNS_NAMESPACE,
384 					KimConstants.PermissionTemplateNames.VIEW_SECTION, user
385 							.getPrincipalId(), additionalPermissionDetails,
386 					null)) {
387 				restrictions.addHiddenSectionId(sectionId);
388 			}
389 		}
390 	}
391 
392 	protected void considerMaintenanceDocumentPresentationController(
393 			MaintenanceDocumentPresentationController presentationController,
394 			MaintenanceDocument document,
395 			MaintenanceDocumentRestrictions restrictions) {
396 		for (String attributeName : presentationController
397 				.getConditionallyReadOnlyPropertyNames(document)) {
398 			restrictions.addReadOnlyField(attributeName);
399 		}
400 		for (String sectionId : presentationController
401 				.getConditionallyReadOnlySectionIds(document)) {
402 			restrictions.addReadOnlySectionId(sectionId);
403 		}
404 	}
405 
406 	protected void considerMaintenanceDocumentAuthorizer(
407 			MaintenanceDocumentAuthorizer authorizer,
408 			MaintenanceDocument document, Person user,
409 			MaintenanceDocumentRestrictions restrictions) {
410 		for (String sectionId : authorizer
411 				.getSecurePotentiallyReadOnlySectionIds()) {
412 			Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
413 			additionalPermissionDetails
414 					.put(KimAttributes.SECTION_ID, sectionId);
415 			if (!authorizer.isAuthorizedByTemplate(document,
416 					KNSConstants.KNS_NAMESPACE,
417 					KimConstants.PermissionTemplateNames.MODIFY_SECTION, user
418 							.getPrincipalId(), additionalPermissionDetails,
419 					null)) {
420 				restrictions.addReadOnlySectionId(sectionId);
421 			}
422 		}
423 	}
424 
425 	@SuppressWarnings("unchecked")
426 	protected void addInquirableItemRestrictions(Collection sectionDefinitions,
427 			InquiryAuthorizer authorizer, InquiryRestrictions restrictions,
428 			BusinessObject primaryBusinessObject,
429 			BusinessObject businessObject, String propertyPrefix, Person user) {
430 		for (Object inquirableItemDefinition : sectionDefinitions) {
431 			if (inquirableItemDefinition instanceof InquiryCollectionDefinition) {
432 				InquiryCollectionDefinition inquiryCollectionDefinition = (InquiryCollectionDefinition) inquirableItemDefinition;
433 				DataDictionaryEntryBase collectionDictionaryEntry = (DataDictionaryEntryBase)getDataDictionaryService()
434 						.getDataDictionary().getDictionaryObjectEntry(
435 								inquiryCollectionDefinition.getBusinessObjectClass().getName());
436 
437 				try {
438 					Collection<BusinessObject> collection = (Collection<BusinessObject>) PropertyUtils
439 							.getProperty(businessObject,
440 									inquiryCollectionDefinition.getName());
441 					int i = 0;
442 					for (Iterator<BusinessObject> iterator = collection.iterator(); iterator
443 							.hasNext();) {
444 						String newPropertyPrefix = propertyPrefix + inquiryCollectionDefinition.getName() + "[" + i + "].";
445 						BusinessObject collectionItemBusinessObject = iterator.next();
446 						considerBusinessObjectFieldUnmaskAuthorization(
447 								collectionItemBusinessObject, user, restrictions,
448 								newPropertyPrefix, null);
449 						considerBusinessObjectFieldViewAuthorization(
450 								collectionDictionaryEntry, primaryBusinessObject, collectionItemBusinessObject,
451 								user, authorizer, restrictions, newPropertyPrefix);
452 						addInquirableItemRestrictions(
453 								inquiryCollectionDefinition
454 										.getInquiryCollections(),
455 								authorizer,
456 								restrictions,
457 								primaryBusinessObject,
458 								collectionItemBusinessObject,
459 								newPropertyPrefix,
460 								user);
461 						i++;
462 					}
463 				} catch (Exception e) {
464 					throw new RuntimeException(
465 							"Unable to resolve collection property: "
466 									+ businessObject.getClass() + ":"
467 									+ inquiryCollectionDefinition.getName(), e);
468 				}
469 			}
470 		}
471 	}
472 
473 	@SuppressWarnings("unchecked")
474 	protected void addMaintainableItemRestrictions(List<? extends MaintainableItemDefinition> itemDefinitions,
475 			MaintenanceDocumentAuthorizer authorizer,
476 			MaintenanceDocumentRestrictions restrictions,
477 			MaintenanceDocument maintenanceDocument,
478 			BusinessObject businessObject, String propertyPrefix, Person user) {
479 		for (MaintainableItemDefinition maintainableItemDefinition : itemDefinitions) {
480 			if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) {
481 				try {
482 					MaintainableCollectionDefinition maintainableCollectionDefinition = (MaintainableCollectionDefinition) maintainableItemDefinition;
483 					
484 					Collection<BusinessObject> collection = (Collection<BusinessObject>) ObjectUtils
485 							.getNestedValue(businessObject,
486 									maintainableItemDefinition.getName());
487 					BusinessObjectEntry collectionBusinessObjectEntry = getDataDictionaryService()
488 							.getDataDictionary().getBusinessObjectEntry(
489 									maintainableCollectionDefinition.getBusinessObjectClass().getName());
490 					if (collection != null) {
491 				    	int i = 0;
492 			     		for (Iterator<BusinessObject> iterator = collection.iterator(); iterator
493 							.hasNext();) {
494 			     			String newPropertyPrefix = propertyPrefix + maintainableItemDefinition.getName() + "[" + i + "].";
495 					    	BusinessObject collectionBusinessObject = iterator.next();
496 					    	considerBusinessObjectFieldUnmaskAuthorization(
497 								collectionBusinessObject, user, restrictions,
498 								newPropertyPrefix, maintenanceDocument);
499 					    	considerBusinessObjectFieldViewAuthorization(
500 								collectionBusinessObjectEntry, maintenanceDocument, collectionBusinessObject, user,
501 								authorizer, restrictions, newPropertyPrefix);
502 					    	considerBusinessObjectFieldModifyAuthorization(
503 								collectionBusinessObjectEntry, maintenanceDocument, collectionBusinessObject, user,
504 								authorizer, restrictions, newPropertyPrefix);
505 					    	addMaintainableItemRestrictions(
506 								((MaintainableCollectionDefinition) maintainableItemDefinition)
507 										.getMaintainableCollections(),
508 								authorizer, restrictions, maintenanceDocument,
509 								collectionBusinessObject, newPropertyPrefix,
510 								user);
511 				     		addMaintainableItemRestrictions(
512 								((MaintainableCollectionDefinition) maintainableItemDefinition)
513 										.getMaintainableFields(), authorizer,
514 								restrictions, maintenanceDocument,
515 								collectionBusinessObject, newPropertyPrefix,
516 								user);
517 					    	i++;
518 				    	}
519 					}
520 				} catch (Exception e) {
521 					throw new RuntimeException(
522 							"Unable to resolve collection property: "
523 									+ businessObject.getClass() + ":"
524 									+ maintainableItemDefinition.getName(), e);
525 				}
526 			}
527 		}
528 	}
529 	
530 	public <T extends BusinessObject> boolean canFullyUnmaskField(Person user,
531 			Class<T> businessObjectClass, String fieldName, Document document) {
532 		// KFSMI-5095
533 		if(isNonProductionEnvAndUnmaskingTurnedOff())
534 			return false;
535 
536 		if(user==null || StringUtils.isEmpty(user.getPrincipalId())) 
537 			return false;
538 		Boolean result = null;
539 		if (document != null) { // if a document was passed, evaluate the permission in the context of a document
540 			try { // try/catch and fallthrough is a fix for KULRICE-3365
541 				result = getDocumentHelperService().getDocumentAuthorizer( document )
542 				.isAuthorizedByTemplate( document, 
543 						KNSConstants.KNS_NAMESPACE, 
544 						KimConstants.PermissionTemplateNames.FULL_UNMASK_FIELD, 
545 						user.getPrincipalId(), getFieldPermissionDetails(businessObjectClass, fieldName), null  );
546 			} catch (IllegalArgumentException e) { 
547 				// document didn't have needed metadata
548 				// TODO: this requires intimate knowledge of DocumentHelperServiceImpl 
549 			} 
550 		}
551 		if (result == null) { 
552 			result = getIdentityManagementService().isAuthorizedByTemplateName(
553 					user.getPrincipalId(),
554 					KNSConstants.KNS_NAMESPACE,
555 					KimConstants.PermissionTemplateNames.FULL_UNMASK_FIELD,
556 					new AttributeSet(getFieldPermissionDetails(businessObjectClass, fieldName)), 
557 					null);
558 		}
559 		return result; // should be safe to return Boolean here since the only circumstances that
560 		               // will leave it null will result in an exception being thrown above.
561 	}
562 
563 	public <T extends BusinessObject> boolean canPartiallyUnmaskField(
564 			Person user, Class<T> businessObjectClass, String fieldName, Document document) {
565 		// KFSMI-5095
566 		if(isNonProductionEnvAndUnmaskingTurnedOff())
567 			return false;
568 		
569 		if(user==null || StringUtils.isEmpty(user.getPrincipalId())) 
570 			return false;
571 
572 		if ( document == null ) {
573 			return getIdentityManagementService().isAuthorizedByTemplateName(
574 					user.getPrincipalId(),
575 					KNSConstants.KNS_NAMESPACE,
576 					KimConstants.PermissionTemplateNames.PARTIAL_UNMASK_FIELD,
577 					new AttributeSet(getFieldPermissionDetails(businessObjectClass,fieldName)), 
578 					null);
579 		} else { // if a document was passed, evaluate the permission in the context of a document
580 			return getDocumentHelperService().getDocumentAuthorizer( document )
581 					.isAuthorizedByTemplate( document, 
582 											 KNSConstants.KNS_NAMESPACE, 
583 											 KimConstants.PermissionTemplateNames.PARTIAL_UNMASK_FIELD, 
584 											 user.getPrincipalId(), getFieldPermissionDetails(businessObjectClass, fieldName), null  );
585 		}
586 	}
587 	
588 	public <T extends BusinessObject> boolean canCreate(Class<T> boClass, Person user, String docTypeName){
589 		DocumentPresentationController documentPresentationController = getDocumentHelperService().getDocumentPresentationController(docTypeName);
590 	    boolean canCreate = ((MaintenanceDocumentPresentationController) documentPresentationController).canCreate(boClass);
591 	    if(canCreate){
592 			DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(docTypeName);
593 	    	canCreate = ((MaintenanceDocumentAuthorizer) documentAuthorizer).canCreate(boClass, user);
594 	    }
595 		return canCreate;
596 	}
597 	
598 	public boolean canMaintain(BusinessObject businessObject, Person user,
599 			String docTypeName) {
600 		return ((MaintenanceDocumentAuthorizer) getDocumentHelperService()
601 				.getDocumentAuthorizer(docTypeName)).canMaintain(
602 				businessObject, user);
603 	}
604 
605 	protected <T extends BusinessObject> Map<String, String> getFieldPermissionDetails(
606 			Class<T> businessObjectClass, String attributeName) {
607 		try {
608 			return getFieldPermissionDetails(businessObjectClass.newInstance(),
609 					attributeName);
610 		} catch (Exception e) {
611 			throw new RuntimeException(
612 					"The getPermissionDetails method of BusinessObjectAuthorizationServiceImpl was unable to instantiate the businessObjectClass"
613 							+ businessObjectClass, e);
614 		}
615 	}
616 
617 	protected Map<String, String> getFieldPermissionDetails(
618 			BusinessObject businessObject, String attributeName) {
619 		Map<String, String> permissionDetails = null;
620 		String namespaceCode = null;
621 		String componentName = null;
622 		String propertyName = null;
623 		// JHK: commenting out for KFSMI-2398 - permission checks need to be done at the level specified
624 		// that is, if the parent object specifies the security, that object should be used for the 
625 		// component
626 //		if (attributeName.contains(".")) {
627 //			try {
628 //				permissionDetails = KimCommonUtils
629 //						.getNamespaceAndComponentSimpleName(PropertyUtils
630 //								.getPropertyType(businessObject, attributeName
631 //										.substring(0, attributeName
632 //												.lastIndexOf("."))));
633 //			} catch (Exception e) {
634 //				throw new RuntimeException(
635 //						"Unable to discover nested business object class: "
636 //								+ businessObject.getClass() + " : "
637 //								+ attributeName, e);
638 //			}
639 //			permissionDetails.put(KimAttributes.PROPERTY_NAME, attributeName
640 //					.substring(attributeName.indexOf(".") + 1));
641 //		} else {
642 			permissionDetails = KimCommonUtils
643 					.getNamespaceAndComponentSimpleName(businessObject
644 							.getClass());
645 			permissionDetails.put(KimAttributes.PROPERTY_NAME, attributeName);
646 //		}
647 		return permissionDetails;
648 	}
649 	
650 	protected Map<String, String> getButtonFieldPermissionDetails(
651 			BusinessObject businessObject, String attributeName) {
652 		Map<String, String> permissionDetails = new AttributeSet();
653 		if (attributeName.contains(".")) {
654 			permissionDetails.put(KimAttributes.BUTTON_NAME, attributeName);
655 		} else {
656 			permissionDetails.put(KimAttributes.BUTTON_NAME, attributeName);
657 		}
658 		return permissionDetails;
659 	}
660 
661 	private DataDictionaryService getDataDictionaryService() {
662 		if (dataDictionaryService == null) {
663 			dataDictionaryService = KNSServiceLocator
664 					.getDataDictionaryService();
665 		}
666 		return dataDictionaryService;
667 	}
668 
669 	private IdentityManagementService getIdentityManagementService() {
670 		if (identityManagementService == null) {
671 			identityManagementService = KIMServiceLocator
672 					.getIdentityManagementService();
673 		}
674 		return identityManagementService;
675 	}
676 
677 	private BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
678 		if (businessObjectDictionaryService == null) {
679 			businessObjectDictionaryService = KNSServiceLocator
680 					.getBusinessObjectDictionaryService();
681 		}
682 		return businessObjectDictionaryService;
683 	}
684 
685 	private DocumentHelperService getDocumentHelperService() {
686 		if (documentHelperService == null) {
687 			documentHelperService = KNSServiceLocator.getDocumentHelperService();
688 		}
689 		return documentHelperService;
690 	}
691 
692 	private MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
693 		if (maintenanceDocumentDictionaryService == null) {
694 			maintenanceDocumentDictionaryService = KNSServiceLocator
695 					.getMaintenanceDocumentDictionaryService();
696 		}
697 		return maintenanceDocumentDictionaryService;
698 	}
699 
700 	private KualiConfigurationService getKualiConfigurationService() {
701 		if (kualiConfigurationService == null) {
702 			kualiConfigurationService = KNSServiceLocator.getKualiConfigurationService();
703 		}
704 		return kualiConfigurationService;
705 	}
706 	
707 	/**
708 	 * @see org.kuali.rice.kns.service.BusinessObjectAuthorizationService#attributeValueNeedsToBeEncryptedOnFormsAndLinks(java.lang.Class, java.lang.String)
709 	 */
710 	public boolean attributeValueNeedsToBeEncryptedOnFormsAndLinks(
711 			Class<? extends BusinessObject> businessObjectClass,
712 			String attributeName) {
713 		AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(businessObjectClass.getName(), attributeName);
714 		return attributeSecurity != null && attributeSecurity.hasRestrictionThatRemovesValueFromUI();
715 	}
716 
717 	private boolean isNonProductionEnvAndUnmaskingTurnedOff(){
718 		return !getKualiConfigurationService().isProductionEnvironment() && 
719 				!getKualiConfigurationService().getPropertyAsBoolean(KNSConstants.ENABLE_NONPRODUCTION_UNMASKING);
720 	}
721 
722 }