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.util; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.CoreApiServiceLocator; 020import org.kuali.rice.krad.keyvalues.KeyValuesFinder; 021import org.kuali.rice.krad.keyvalues.PersistableBusinessObjectValuesFinder; 022import org.kuali.rice.krad.util.KRADConstants; 023 024import java.lang.reflect.Method; 025import java.security.GeneralSecurityException; 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.List; 029 030/** 031 * Utility map for the action form to provide a way for calling functions through jstl. 032 * 033 * 034 */ 035@SuppressWarnings("unchecked") 036public class ActionFormUtilMap extends HashMap { 037 private static final long serialVersionUID = 1L; 038 private boolean cacheValueFinderResults; 039 040 /** 041 * This method parses from the key the actual method to run. 042 * 043 * @see java.util.Map#get(java.lang.Object) 044 */ 045 @Override 046 public Object get(Object key) { 047 if (cacheValueFinderResults) { 048 if (super.containsKey(key)) { 049 // doing a 2 step retrieval allows us to also cache the null key correctly 050 Object cachedObject = super.get(key); 051 return cachedObject; 052 } 053 } 054 String[] methodKey = StringUtils.split((String) key, KRADConstants.ACTION_FORM_UTIL_MAP_METHOD_PARM_DELIMITER); 055 056 String methodToCall = methodKey[0]; 057 058 // handle method calls with more than one parameter 059 Object[] methodParms = new Object[methodKey.length - 1]; 060 Class[] methodParmsPrototype = new Class[methodKey.length - 1]; 061 for (int i=1;i<methodKey.length;i++) { 062 methodParms[i-1] = methodKey[i]; 063 methodParmsPrototype[i-1] = Object.class; 064 } 065 066 Method method = null; 067 try { 068 method = ActionFormUtilMap.class.getMethod(methodToCall, methodParmsPrototype); 069 } 070 catch (SecurityException e) { 071 throw new RuntimeException("Unable to object handle on method given to ActionFormUtilMap: " + e.getMessage()); 072 } 073 catch (NoSuchMethodException e1) { 074 throw new RuntimeException("Unable to object handle on method given to ActionFormUtilMap: " + e1.getMessage()); 075 } 076 077 Object methodValue = null; 078 try { 079 methodValue = method.invoke(this, methodParms); 080 } 081 catch (Exception e) { 082 throw new RuntimeException("Unable to invoke method " + methodToCall,e); 083 } 084 085 if (cacheValueFinderResults) { 086 super.put(key, methodValue); 087 } 088 089 return methodValue; 090 } 091 092 /* 093 * Will take in a class name parameter and attempt to create a KeyValueFinder instance, then call the finder to return a list of 094 * KeyValue pairs. This is used by the htmlControlAttribute.tag to render select options from a given finder class specified in 095 * the data dictionary. 096 */ 097 public Object getOptionsMap(Object key) { 098 List optionsList = new ArrayList(); 099 100 if (StringUtils.isBlank((String) key)) { 101 return optionsList; 102 } 103 104 /* 105 * the class name has . replaced with | in the jsp to prevent struts from treating each part of the class name as a property 106 * substitute back here to get the correct name 107 */ 108 key = StringUtils.replace((String) key, "|", "."); 109 110 KeyValuesFinder finder; 111 try { 112 Class finderClass = Class.forName((String) key); 113 finder = (KeyValuesFinder) finderClass.newInstance(); 114 optionsList = finder.getKeyValues(); 115 } 116 catch (ClassNotFoundException e) { 117 throw new RuntimeException(e.getMessage()); 118 } 119 catch (InstantiationException e) { 120 throw new RuntimeException(e.getMessage()); 121 } 122 catch (IllegalAccessException e) { 123 throw new RuntimeException(e.getMessage()); 124 } 125 126 return optionsList; 127 } 128 129 // Method added to keep backward compatibility for non-kimTypeId cases 130 public Object getOptionsMap(Object key, Object boClass, Object keyAttribute, Object labelAttribute, Object includeKeyInLabel) { 131 return getOptionsMap(key, boClass, keyAttribute, labelAttribute, null, includeKeyInLabel ); 132 } 133 134 /** 135 * This method will take in a key parameter (values finder class name - in this case the generic 136 * PersistableObjectValuesFinder) along with the related parameters required by this ValuesFinder, 137 * and attempt to create a KeyValueFinder instance, then call the finder to return a list of 138 * KeyValue pairs. This is used by the htmlControlAttribute.tag to render select options from 139 * a given finder class specified in the data dictionary. 140 * 141 * @param key values finder class name 142 * @param boClass BO class name 143 * @param keyAttribute name of BO attribute for key 144 * @param labelAttribute name of BO attribute for label 145 * @param includeKeyInLabel whether to include the key in the label or not 146 * @return list of KeyValue pairs 147 */ 148 public Object getOptionsMap(Object key, Object boClass, Object keyAttribute, Object labelAttribute, Object includeBlankRow, Object includeKeyInLabel) { 149 List optionsList = new ArrayList(); 150 151 if (StringUtils.isBlank((String) key)) { 152 return optionsList; 153 } 154 155 /* 156 * the class name has . replaced with | in the jsp to prevent struts from treating each part of the class name as a property 157 * substitute back here to get the correct name 158 */ 159 key = StringUtils.replace((String) key, "|", "."); 160 161 KeyValuesFinder finder; 162 try { 163 Class finderClass = Class.forName((String) key); 164 finder = (KeyValuesFinder) finderClass.newInstance(); 165 if (finder instanceof PersistableBusinessObjectValuesFinder) { 166 String businessObjectClassName = StringUtils.replace((String) boClass, "|", "."); 167 Class businessObjectClass = Class.forName((String) businessObjectClassName); 168 ((PersistableBusinessObjectValuesFinder) finder).setBusinessObjectClass(businessObjectClass); 169 ((PersistableBusinessObjectValuesFinder) finder).setKeyAttributeName((String)keyAttribute); 170 ((PersistableBusinessObjectValuesFinder) finder).setLabelAttributeName((String)labelAttribute); 171 ((PersistableBusinessObjectValuesFinder) finder).setIncludeBlankRow(Boolean.parseBoolean((String)includeBlankRow)); 172 ((PersistableBusinessObjectValuesFinder) finder).setIncludeKeyInDescription(Boolean.parseBoolean((String)includeKeyInLabel)); 173 } 174 175 optionsList = finder.getKeyValues(); 176 } 177 catch (ClassNotFoundException e) { 178 throw new RuntimeException(e.getMessage(),e); 179 } 180 catch (InstantiationException e) { 181 throw new RuntimeException(e.getMessage(),e); 182 } 183 catch (IllegalAccessException e) { 184 throw new RuntimeException(e.getMessage(),e); 185 } 186 187 return optionsList; 188 } 189 190 /** 191 * Encrypts a value passed from the ui. 192 * @param value - clear text 193 * @return String - encrypted text 194 */ 195 public String encryptValue(Object value) { 196 String encrypted = ""; 197 if (value != null) { 198 encrypted = value.toString(); 199 } 200 201 try { 202 if(CoreApiServiceLocator.getEncryptionService().isEnabled()) { 203 encrypted = CoreApiServiceLocator.getEncryptionService().encrypt(value); 204 } 205 } 206 catch (GeneralSecurityException e) { 207 throw new RuntimeException("Unable to encrypt value in action form: " + e.getMessage()); 208 } 209 210 return encrypted; 211 } 212 213 public void setCacheValueFinderResults(boolean cacheValueFinderResults) { 214 this.cacheValueFinderResults = cacheValueFinderResults; 215 } 216 217 218}