001package org.kuali.rice.krad.uif.field; 002 003import org.apache.commons.lang.StringUtils; 004import org.kuali.rice.core.api.util.ConcreteKeyValue; 005import org.kuali.rice.krad.datadictionary.AttributeDefinition; 006import org.kuali.rice.krad.datadictionary.parse.BeanTag; 007import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 008import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 009import org.kuali.rice.krad.uif.UifConstants; 010import org.kuali.rice.krad.uif.component.Component; 011import org.kuali.rice.krad.uif.control.*; 012import org.kuali.rice.krad.uif.element.Message; 013import org.kuali.rice.krad.uif.util.ComponentFactory; 014import org.kuali.rice.krad.uif.util.ComponentUtils; 015import org.kuali.rice.krad.uif.util.KeyMessage; 016import org.kuali.rice.krad.uif.view.View; 017import org.kuali.rice.krad.util.KRADConstants; 018import org.kuali.rice.krad.util.KRADPropertyConstants; 019 020import java.util.Map; 021 022/** 023 * Created by angelind on 8/3/15. 024 * 025 * Overridden for fixing the issue with setting maxLength for the lookup fields. 026 * Modified method name: copyFromAttributeDefinition. 027 * Changes description : Getting the maxLength from attributeDefinition if the attribute definition is having maxLength. 028 */ 029@BeanTag(name = "lookupCriteriaInputField-bean", parent = "Uif-LookupCriteriaInputField") 030public class LookupInputField extends InputField { 031 private static final long serialVersionUID = -8294275596836322699L; 032 033 public static final String CHECKBOX_CONVERTED_RADIO_CONTROL = "Uif-CheckboxConvertedRadioControl"; 034 035 private boolean disableWildcardsAndOperators; 036 private boolean addControlSelectAllOption; 037 private boolean triggerOnChange; 038 private boolean ranged; 039 040 public LookupInputField() { 041 super(); 042 043 disableWildcardsAndOperators = false; 044 addControlSelectAllOption = false; 045 setTriggerOnChange(false); 046 } 047 048 /** 049 * The following actions are performed: 050 * 051 * <ul> 052 * <li>Add all option if enabled and control is multi-value</li> 053 * </ul> 054 * 055 * @see org.kuali.rice.krad.uif.component.ComponentBase#performFinalize(org.kuali.rice.krad.uif.view.View, 056 * java.lang.Object, org.kuali.rice.krad.uif.component.Component) 057 */ 058 @Override 059 public void performFinalize(View view, Object model, Component parent) { 060 super.performFinalize(view, model, parent); 061 062 // if enabled add option to select all values 063 if (addControlSelectAllOption && (getControl() != null) && getControl() instanceof MultiValueControl) { 064 String allOptionText = KRADServiceLocatorWeb.getMessageService().getMessageText( 065 UifConstants.MessageKeys.OPTION_ALL); 066 067 MultiValueControl multiValueControl = (MultiValueControl) getControl(); 068 if (multiValueControl.getOptions() != null) { 069 multiValueControl.getOptions().add(0, new ConcreteKeyValue("", allOptionText)); 070 } 071 072 if (multiValueControl.getRichOptions() != null) { 073 Message message = ComponentFactory.getMessage(); 074 075 view.assignComponentIds(message); 076 message.setMessageText(allOptionText); 077 message.setGenerateSpan(false); 078 079 multiValueControl.getRichOptions().add(0, new KeyMessage("", allOptionText, message)); 080 } 081 } 082 } 083 084 /** 085 * Override of InputField copy to setup properties necessary to make the field usable for inputting 086 * search criteria 087 * 088 * @param attributeDefinition AttributeDefinition instance the property values should be copied from 089 * @see DataField#copyFromAttributeDefinition(org.kuali.rice.krad.uif.view.View, 090 * org.kuali.rice.krad.datadictionary.AttributeDefinition) 091 */ 092 @Override 093 public void copyFromAttributeDefinition(View view, AttributeDefinition attributeDefinition) { 094 // label 095 if (StringUtils.isEmpty(getLabel())) { 096 setLabel(attributeDefinition.getLabel()); 097 } 098 099 // short label 100 if (StringUtils.isEmpty(getShortLabel())) { 101 setShortLabel(attributeDefinition.getShortLabel()); 102 } 103 104 // security 105 if (getDataFieldSecurity().getAttributeSecurity() == null) { 106 getDataFieldSecurity().setAttributeSecurity(attributeDefinition.getAttributeSecurity()); 107 } 108 109 // options 110 if (getOptionsFinder() == null) { 111 setOptionsFinder(attributeDefinition.getOptionsFinder()); 112 } 113 114 // TODO: what about formatter? 115 116 // use control from dictionary if not specified and convert for searching 117 if (getControl() == null) { 118 Control control = convertControlToLookupControl(attributeDefinition); 119 view.assignComponentIds(control); 120 121 setControl(control); 122 } 123 124 // overwrite maxLength to allow for wildcards and ranges 125 setMaxLength(100); 126 /* Modified by 'Angelin Dayana' for fixing the issue with setting maxLength for the lookup fields. 127 * Getting the maxLength from attributeDefinition if the attribute definition is having maxLength. */ 128 if ( attributeDefinition.getMaxLength()!=null && (attributeDefinition.getMaxLength() > 100)) { 129 setMaxLength(attributeDefinition.getMaxLength()); 130 } 131 132 // set default value for active field to true 133 if (StringUtils.isEmpty(getDefaultValue())) { 134 if ((StringUtils.equals(getPropertyName(), KRADPropertyConstants.ACTIVE))) { 135 setDefaultValue(KRADConstants.YES_INDICATOR_VALUE); 136 } 137 } 138 139 /* 140 * TODO delyea: FieldUtils.createAndPopulateFieldsForLookup used to allow for a set of property names to be passed in via the URL 141 * parameters of the lookup url to set fields as 'read only' 142 */ 143 144 } 145 146 /** 147 * If control definition is defined on the given attribute definition, converts to an appropriate control for 148 * searching (if necessary) and returns a copy for setting on the field 149 * 150 * @param attributeDefinition attribute definition instance to retrieve control from 151 * @return Control instance or null if not found 152 */ 153 protected static Control convertControlToLookupControl(AttributeDefinition attributeDefinition) { 154 if (attributeDefinition.getControlField() == null) { 155 return null; 156 } 157 158 Control newControl = null; 159 160 // convert checkbox to radio with yes/no/both options 161 if (CheckboxControl.class.isAssignableFrom(attributeDefinition.getControlField().getClass())) { 162 newControl = getCheckboxConvertedRadioControl(); 163 } 164 // text areas get converted to simple text inputs 165 else if (TextAreaControl.class.isAssignableFrom(attributeDefinition.getControlField().getClass())) { 166 newControl = ComponentFactory.getTextControl(); 167 } else { 168 newControl = ComponentUtils.copy(attributeDefinition.getControlField(), ""); 169 } 170 171 return newControl; 172 } 173 174 /** 175 * @return the treatWildcardsAndOperatorsAsLiteral 176 */ 177 @BeanTagAttribute(name = "disableWildcardsAndOperators") 178 public boolean isDisableWildcardsAndOperators() { 179 return this.disableWildcardsAndOperators; 180 } 181 182 /** 183 * @param disableWildcardsAndOperators the treatWildcardsAndOperatorsAsLiteral to set 184 */ 185 public void setDisableWildcardsAndOperators(boolean disableWildcardsAndOperators) { 186 this.disableWildcardsAndOperators = disableWildcardsAndOperators; 187 } 188 189 /** 190 * Indicates whether the option for all values (blank key, 'All' label) should be added to the lookup 191 * field, note this is only supported for {@link org.kuali.rice.krad.uif.control.MultiValueControl} instance 192 * 193 * @return boolean true if all option should be added, false if not 194 */ 195 @BeanTagAttribute(name = "addControlSelectAllOption") 196 public boolean isAddControlSelectAllOption() { 197 return addControlSelectAllOption; 198 } 199 200 /** 201 * Setter for the add all option indicator 202 * 203 * @param addControlSelectAllOption 204 */ 205 public void setAddControlSelectAllOption(boolean addControlSelectAllOption) { 206 this.addControlSelectAllOption = addControlSelectAllOption; 207 } 208 209 /** 210 * Indicates that the search must execute on changing of a value in the lookup input field 211 * 212 * @return boolean 213 */ 214 public boolean isTriggerOnChange() { 215 return triggerOnChange; 216 } 217 218 /** 219 * Setter for the trigger search on change flag 220 * 221 * @param triggerOnChange 222 */ 223 public void setTriggerOnChange(boolean triggerOnChange) { 224 this.triggerOnChange = triggerOnChange; 225 } 226 227 /** 228 * Indicates that a field must be rendered as a from and to value 229 * 230 * @return 231 */ 232 public boolean isRanged() { 233 return ranged; 234 } 235 236 /** 237 * Setter for ranged flag to indicate this is a range field 238 * 239 * @param ranged 240 */ 241 public void setRanged(boolean ranged) { 242 this.ranged = ranged; 243 } 244 245 /** 246 * Remove any search criteria that are not part of the database lookup 247 * 248 * @param searchCriteria the search criteria to be filtered 249 * @return the filteredSearchCriteria 250 */ 251 public Map<String, String> filterSearchCriteria(Map<String, String> searchCriteria) { 252 if (getControl() instanceof FilterableLookupCriteriaControl) { 253 return ((FilterableLookupCriteriaControl) getControl()).filterSearchCriteria(getPropertyName(), 254 searchCriteria); 255 } else { 256 return searchCriteria; 257 } 258 } 259 260 /** 261 * @see org.kuali.rice.krad.uif.component.ComponentBase#copy() 262 */ 263 @Override 264 protected <T> void copyProperties(T component) { 265 super.copyProperties(component); 266 LookupInputField lookupInputFieldCopy = (LookupInputField) component; 267 lookupInputFieldCopy.setDisableWildcardsAndOperators(this.disableWildcardsAndOperators); 268 lookupInputFieldCopy.setAddControlSelectAllOption(this.addControlSelectAllOption); 269 lookupInputFieldCopy.setTriggerOnChange(this.triggerOnChange); 270 lookupInputFieldCopy.setRanged(this.ranged); 271 } 272 273 /** 274 * Retrieves a new radio group control instance for converted lookup criteria checkboxes from Spring 275 * (initialized by the bean definition with the given id) 276 * 277 * @return RadioGroupControl 278 */ 279 private static RadioGroupControl getCheckboxConvertedRadioControl() { 280 return (RadioGroupControl) ComponentFactory.getNewComponentInstance(CHECKBOX_CONVERTED_RADIO_CONTROL); 281 } 282} 283