001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kns.service.impl;
017
018import org.apache.commons.beanutils.PropertyUtils;
019import org.apache.commons.collections.CollectionUtils;
020import org.apache.commons.lang.StringUtils;
021import org.kuali.rice.core.api.config.property.ConfigurationService;
022import org.kuali.rice.kim.api.KimConstants;
023import org.kuali.rice.kim.api.identity.Person;
024import org.kuali.rice.kim.api.permission.PermissionService;
025import org.kuali.rice.kim.api.services.KimApiServiceLocator;
026import org.kuali.rice.kns.authorization.BusinessObjectAuthorizer;
027import org.kuali.rice.kns.bo.authorization.InquiryOrMaintenanceDocumentAuthorizer;
028import org.kuali.rice.kns.bo.authorization.InquiryOrMaintenanceDocumentPresentationController;
029import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
030import org.kuali.rice.kns.datadictionary.FieldDefinition;
031import org.kuali.rice.kns.datadictionary.InquiryCollectionDefinition;
032import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
033import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
034import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
035import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
036import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
037import org.kuali.rice.kns.document.MaintenanceDocument;
038import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
039import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictionsBase;
040import org.kuali.rice.kns.document.authorization.InquiryOrMaintenanceDocumentRestrictions;
041import org.kuali.rice.kns.document.authorization.InquiryOrMaintenanceDocumentRestrictionsBase;
042import org.kuali.rice.kns.document.authorization.MaintenanceDocumentAuthorizer;
043import org.kuali.rice.kns.document.authorization.MaintenanceDocumentPresentationController;
044import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
045import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictionsBase;
046import org.kuali.rice.kns.inquiry.InquiryAuthorizer;
047import org.kuali.rice.kns.inquiry.InquiryPresentationController;
048import org.kuali.rice.kns.inquiry.InquiryRestrictions;
049import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
050import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
051import org.kuali.rice.kns.service.DocumentHelperService;
052import org.kuali.rice.kns.service.KNSServiceLocator;
053import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
054import org.kuali.rice.krad.bo.BusinessObject;
055import org.kuali.rice.krad.datadictionary.AttributeDefinition;
056import org.kuali.rice.krad.datadictionary.DataObjectEntry;
057import org.kuali.rice.krad.document.Document;
058import org.kuali.rice.krad.service.DataDictionaryService;
059import org.kuali.rice.krad.service.KRADServiceLocator;
060import org.kuali.rice.krad.service.impl.DataObjectAuthorizationServiceImpl;
061import org.kuali.rice.krad.util.KRADConstants;
062import org.kuali.rice.krad.util.KRADUtils;
063import org.kuali.rice.krad.util.ObjectUtils;
064
065import java.util.Collection;
066import java.util.Collections;
067import java.util.HashMap;
068import java.util.Iterator;
069import java.util.List;
070import java.util.Map;
071
072@Deprecated
073public class BusinessObjectAuthorizationServiceImpl extends DataObjectAuthorizationServiceImpl implements BusinessObjectAuthorizationService {
074        private DataDictionaryService dataDictionaryService;
075        private PermissionService permissionService;
076        private BusinessObjectDictionaryService businessObjectDictionaryService;
077        private DocumentHelperService documentHelperService;
078        private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
079        private ConfigurationService kualiConfigurationService;
080        
081        public BusinessObjectRestrictions getLookupResultRestrictions(
082                        Object dataObject, Person user) {
083                BusinessObjectRestrictions businessObjectRestrictions = new BusinessObjectRestrictionsBase();
084                considerBusinessObjectFieldUnmaskAuthorization(dataObject, user,
085                                businessObjectRestrictions, "", null);
086                return businessObjectRestrictions;
087        }
088
089        public InquiryRestrictions getInquiryRestrictions(
090                        BusinessObject businessObject, Person user) {
091                InquiryRestrictions inquiryRestrictions = new InquiryOrMaintenanceDocumentRestrictionsBase();
092                BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry) getDataDictionaryService()
093                                .getDataDictionary().getBusinessObjectEntry(
094                                                businessObject.getClass().getName());
095                InquiryPresentationController inquiryPresentationController = getBusinessObjectDictionaryService()
096                                .getInquiryPresentationController(businessObject.getClass());
097                InquiryAuthorizer inquiryAuthorizer = getBusinessObjectDictionaryService()
098                                .getInquiryAuthorizer(businessObject.getClass());
099                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 = KRADServiceLocator.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}