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