View Javadoc

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