001    /*
002     * Copyright 2011 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     */
016    package org.kuali.kfs.sec.businessobject.lookup;
017    
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    
023    import org.apache.commons.lang.StringUtils;
024    import org.kuali.kfs.sec.SecConstants;
025    import org.kuali.kfs.sec.SecPropertyConstants;
026    import org.kuali.kfs.sec.businessobject.SecurityAttributeMetadata;
027    import org.kuali.kfs.sec.identity.SecKimAttributes;
028    import org.kuali.kfs.sec.service.AccessSecurityService;
029    import org.kuali.kfs.sys.KFSPropertyConstants;
030    import org.kuali.kfs.sys.context.SpringContext;
031    import org.kuali.kfs.sys.service.UniversityDateService;
032    import org.kuali.rice.kim.bo.Person;
033    import org.kuali.rice.kim.bo.types.dto.AttributeSet;
034    import org.kuali.rice.kim.service.PersonService;
035    import org.kuali.rice.kns.bo.BusinessObject;
036    import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
037    import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
038    import org.kuali.rice.kns.service.KNSServiceLocator;
039    import org.kuali.rice.kns.util.FieldUtils;
040    import org.kuali.rice.kns.util.KNSConstants;
041    import org.kuali.rice.kns.web.format.Formatter;
042    import org.kuali.rice.kns.web.ui.Column;
043    import org.kuali.rice.kns.web.ui.Row;
044    
045    
046    /**
047     * Calls the access security service to simulate validation for the specified user, attribute, and action
048     */
049    public class AccessSecuritySimulationLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
050        protected AccessSecurityService accessSecurityService;
051        protected UniversityDateService universityDateService;
052    
053        protected List<Row> rows;
054    
055        public AccessSecuritySimulationLookupableHelperServiceImpl() {
056            rows = null;
057        }
058    
059        /**
060         * @see org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl#getSearchResults(java.util.Map)
061         */
062        @Override
063        public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
064            String principalName = fieldValues.get(SecPropertyConstants.SECURITY_PERSON_PRINCIPAL_NAME);
065            Person person = SpringContext.getBean(PersonService.class).getPersonByPrincipalName(principalName);
066    
067            String attributeName = fieldValues.get(SecPropertyConstants.ATTRIBUTE_NAME);
068            String templateId = fieldValues.get(SecPropertyConstants.TEMPLATE_ID);
069    
070            AttributeSet additionalPermissionDetails = new AttributeSet();
071            if (accessSecurityService.getInquiryWithFieldValueTemplateId().equals(templateId)) {
072                String namespaceCode = fieldValues.get(SecPropertyConstants.INQUIRY_NAMESPACE_CODE);
073                additionalPermissionDetails.put(SecKimAttributes.NAMESPACE_CODE, namespaceCode);
074            }
075            else if (!accessSecurityService.getLookupWithFieldValueTemplateId().equals(templateId)) {
076                String documentTypeCode = fieldValues.get(SecPropertyConstants.FINANCIAL_SYSTEM_DOCUMENT_TYPE_CODE);
077                additionalPermissionDetails.put(SecKimAttributes.DOCUMENT_TYPE_NAME, documentTypeCode);
078            }
079    
080            return runSimulation(person, attributeName, templateId, additionalPermissionDetails);
081        }
082    
083        /**
084         * @param person
085         * @param attribute
086         * @param templateId
087         * @param additionalPermissionDetails
088         * @return
089         */
090        protected List<? extends BusinessObject> runSimulation(Person person, String attributeName, String templateId, AttributeSet additionalPermissionDetails) {
091            List<BusinessObject> resultRecords = new ArrayList<BusinessObject>();
092    
093            if (!SecConstants.ATTRIBUTE_SIMULATION_MAP.containsKey(attributeName)) {
094                throw new RuntimeException("Unable to find attribute metadata for attribute: " + attributeName);
095            }
096            SecurityAttributeMetadata attributeMetadata = SecConstants.ATTRIBUTE_SIMULATION_MAP.get(attributeName);
097            Class attributeClass = attributeMetadata.getAttributeClass();
098    
099            // build criteria for retrieving attribute records
100            Map<String, Object> searchCriteria = new HashMap<String, Object>();
101            List<String> fieldNames = getPersistenceStructureService().listFieldNames(attributeClass);
102            if (fieldNames.contains(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR)) {
103                searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityDateService.getCurrentFiscalYear());
104            }
105    
106            if (fieldNames.contains(KFSPropertyConstants.ACTIVE)) {
107                searchCriteria.put(KFSPropertyConstants.ACTIVE, true);
108            }
109    
110            // retrieve records for this attribute to iterate over and call security service
111            List allAttributeData = (List) getBusinessObjectService().findMatching(attributeClass, searchCriteria);
112            accessSecurityService.applySecurityRestrictions(allAttributeData, person, templateId, additionalPermissionDetails);
113    
114            // iterate through business object instances and construct simulation info result objects
115            // for (Iterator iterator = allAttributeData.iterator(); iterator.hasNext();) {
116            // BusinessObject businessObject = (BusinessObject) iterator.next();
117            //
118            // AccessSecuritySimulation securitySimulation = new AccessSecuritySimulation();
119            //
120            // Object boKeyFieldValue = ObjectUtils.getPropertyValue(businessObject, attributeMetadata.getAttributeField());
121            // Object boNameFieldValue = ObjectUtils.getPropertyValue(businessObject, attributeMetadata.getAttributeNameField());
122            //
123            // securitySimulation.setAttributeValue(boKeyFieldValue.toString());
124            // securitySimulation.setAttributeValueName(boNameFieldValue.toString());
125            //
126            // resultRecords.add(securitySimulation);
127            // }
128    
129            return allAttributeData;
130        }
131    
132        /**
133         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#setRows()
134         */
135        @Override
136        protected void setRows() {
137            List<String> lookupFieldAttributeList = new ArrayList<String>();
138            if (getParameters().containsKey(SecPropertyConstants.TEMPLATE_ID)) {
139                String templateId = ((String[]) getParameters().get(SecPropertyConstants.TEMPLATE_ID))[0];
140    
141                if (accessSecurityService.getInquiryWithFieldValueTemplateId().equals(templateId)) {
142                    lookupFieldAttributeList = getInquiryTemplateFields();
143                }
144                else if (accessSecurityService.getLookupWithFieldValueTemplateId().equals(templateId)) {
145                    lookupFieldAttributeList = getLookupTemplateFields();
146                }
147                else {
148                    lookupFieldAttributeList = getDocumentTemplateFields();
149                }
150            }
151            else {
152                lookupFieldAttributeList = getLookupTemplateFields();
153            }
154    
155            // construct field object for each search attribute
156            List fields = new ArrayList();
157            int numCols;
158            try {
159                fields = FieldUtils.createAndPopulateFieldsForLookup(lookupFieldAttributeList, getReadOnlyFieldsList(), getBusinessObjectClass());
160    
161                BusinessObjectEntry boe = KNSServiceLocator.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(this.getBusinessObjectClass().getName());
162                numCols = boe.getLookupDefinition().getNumOfColumns();
163    
164            }
165            catch (InstantiationException e) {
166                throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
167            }
168            catch (IllegalAccessException e) {
169                throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
170            }
171    
172            if (numCols == 0)
173                numCols = KNSConstants.DEFAULT_NUM_OF_COLUMNS;
174    
175            rows = FieldUtils.wrapFields(fields, numCols);
176        }
177    
178        /**
179         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getRows()
180         */
181        @Override
182        public List<Row> getRows() {
183            return rows;
184        }
185    
186        /**
187         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getColumns()
188         */
189        @Override
190        public List<Column> getColumns() {
191            String searchAttributeName = ((String[]) getParameters().get(SecPropertyConstants.ATTRIBUTE_NAME))[0];
192    
193            SecurityAttributeMetadata attributeMetadata = SecConstants.ATTRIBUTE_SIMULATION_MAP.get(searchAttributeName);
194            Class attributeClass = attributeMetadata.getAttributeClass();
195    
196            ArrayList<Column> columns = new ArrayList<Column>();
197            for (String attributeName : getBusinessObjectDictionaryService().getLookupResultFieldNames(attributeClass)) {
198                Column column = new Column();
199                column.setPropertyName(attributeName);
200    
201                String columnTitle = getDataDictionaryService().getAttributeLabel(attributeClass, attributeName);
202                Boolean useShortLabel = getBusinessObjectDictionaryService().getLookupResultFieldUseShortLabel(attributeClass, attributeName);
203                if (useShortLabel != null && useShortLabel) {
204                    columnTitle = getDataDictionaryService().getAttributeShortLabel(attributeClass, attributeName);
205                }
206                if (StringUtils.isBlank(columnTitle)) {
207                    columnTitle = getDataDictionaryService().getCollectionLabel(attributeClass, attributeName);
208                }
209                column.setColumnTitle(columnTitle);
210    
211                Integer fieldDefinedMaxLength = getBusinessObjectDictionaryService().getLookupResultFieldMaxLength(attributeClass, attributeName);
212                if (fieldDefinedMaxLength == null) {
213                    try {
214                        fieldDefinedMaxLength = Integer.valueOf(getParameterService().getParameterValue(KNSConstants.KNS_NAMESPACE, KNSConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE, KNSConstants.RESULTS_DEFAULT_MAX_COLUMN_LENGTH));
215                    }
216                    catch (NumberFormatException ex) {
217                        LOG.error("Lookup field max length parameter not found and unable to parse default set in system parameters (RESULTS_DEFAULT_MAX_COLUMN_LENGTH).");
218                    }
219                }
220                column.setMaxLength(fieldDefinedMaxLength.intValue());
221    
222                Class formatterClass = getDataDictionaryService().getAttributeFormatter(attributeClass, attributeName);
223                if (formatterClass != null) {
224                    try {
225                        column.setFormatter((Formatter) formatterClass.newInstance());
226                    }
227                    catch (InstantiationException e) {
228                        LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
229                        throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
230                    }
231                    catch (IllegalAccessException e) {
232                        LOG.error("Unable to get new instance of formatter class: " + formatterClass.getName());
233                        throw new RuntimeException("Unable to get new instance of formatter class: " + formatterClass.getName());
234                    }
235                }
236    
237                columns.add(column);
238            }
239    
240            return columns;
241        }
242    
243        /**
244         * Builds List of search field names for searching the inquiry template
245         * 
246         * @return List<String> containing lookup field names
247         */
248        protected List<String> getInquiryTemplateFields() {
249            List<String> lookupFields = new ArrayList<String>();
250    
251            lookupFields.add(SecPropertyConstants.SECURITY_PERSON_PRINCIPAL_NAME);
252            lookupFields.add(SecPropertyConstants.ATTRIBUTE_NAME);
253            lookupFields.add(SecPropertyConstants.TEMPLATE_ID);
254            lookupFields.add(SecPropertyConstants.INQUIRY_NAMESPACE_CODE);
255    
256            return lookupFields;
257        }
258    
259        /**
260         * Builds List of search field names for searching the lookup template
261         * 
262         * @return List<String> containing lookup field names
263         */
264        protected List<String> getLookupTemplateFields() {
265            List<String> lookupFields = new ArrayList<String>();
266    
267            lookupFields.add(SecPropertyConstants.SECURITY_PERSON_PRINCIPAL_NAME);
268            lookupFields.add(SecPropertyConstants.ATTRIBUTE_NAME);
269            lookupFields.add(SecPropertyConstants.TEMPLATE_ID);
270    
271            return lookupFields;
272        }
273    
274        /**
275         * Builds List of search field names for searching document templates
276         * 
277         * @return List<String> containing lookup field names
278         */
279        protected List<String> getDocumentTemplateFields() {
280            List<String> lookupFields = new ArrayList<String>();
281    
282            lookupFields.add(SecPropertyConstants.SECURITY_PERSON_PRINCIPAL_NAME);
283            lookupFields.add(SecPropertyConstants.ATTRIBUTE_NAME);
284            lookupFields.add(SecPropertyConstants.TEMPLATE_ID);
285            lookupFields.add(SecPropertyConstants.FINANCIAL_SYSTEM_DOCUMENT_TYPE_CODE);
286    
287            return lookupFields;
288        }
289    
290        /**
291         * Sets the accessSecurityService attribute value.
292         * 
293         * @param accessSecurityService The accessSecurityService to set.
294         */
295        public void setAccessSecurityService(AccessSecurityService accessSecurityService) {
296            this.accessSecurityService = accessSecurityService;
297        }
298    
299        /**
300         * Sets the universityDateService attribute value.
301         * 
302         * @param universityDateService The universityDateService to set.
303         */
304        public void setUniversityDateService(UniversityDateService universityDateService) {
305            this.universityDateService = universityDateService;
306        }
307    
308    }