001 /** 002 * Copyright 2005-2013 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.rice.krad.uif.control; 017 018 import org.kuali.rice.core.api.util.KeyValue; 019 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 020 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 021 import org.kuali.rice.krad.uif.UifConstants; 022 import org.kuali.rice.krad.uif.component.Component; 023 import org.kuali.rice.krad.uif.container.Container; 024 import org.kuali.rice.krad.uif.element.Message; 025 import org.kuali.rice.krad.uif.field.InputField; 026 import org.kuali.rice.krad.uif.util.ComponentFactory; 027 import org.kuali.rice.krad.uif.util.ExpressionUtils; 028 import org.kuali.rice.krad.uif.util.KeyMessage; 029 import org.kuali.rice.krad.uif.util.UrlInfo; 030 import org.kuali.rice.krad.uif.util.UifKeyValueLocation; 031 import org.kuali.rice.krad.uif.view.View; 032 033 import java.util.ArrayList; 034 import java.util.List; 035 036 /** 037 * Base class for controls that accept/display multiple values 038 * 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041 public abstract class MultiValueControlBase extends ControlBase implements MultiValueControl { 042 private static final long serialVersionUID = -8691367056245775455L; 043 044 private List<KeyValue> options; 045 private List<KeyMessage> richOptions; 046 private List<Component> inlineComponents; 047 048 private boolean locationSelect = false; 049 050 public MultiValueControlBase() { 051 super(); 052 } 053 054 /** 055 * Process rich message content that may be in the options, by creating and initializing the richOptions 056 * 057 * @see org.kuali.rice.krad.uif.component.ComponentBase#performApplyModel(org.kuali.rice.krad.uif.view.View, 058 * Object, org.kuali.rice.krad.uif.component.Component) 059 */ 060 @Override 061 public void performApplyModel(View view, Object model, Component parent) { 062 super.performApplyModel(view, model, parent); 063 064 if (options != null && richOptions == null) { 065 richOptions = new ArrayList<KeyMessage>(); 066 067 for (KeyValue option : options) { 068 Message message = ComponentFactory.getMessage(); 069 view.assignComponentIds(message); 070 message.setMessageText(option.getValue()); 071 message.setInlineComponents(inlineComponents); 072 message.setGenerateSpan(false); 073 074 view.getViewHelperService().performComponentInitialization(view, model, message); 075 richOptions.add(new KeyMessage(option.getKey(), option.getValue(), message)); 076 } 077 } 078 } 079 080 /** 081 * Adds appropriate parent data to inputs internal to the controls that may be in rich content of options 082 * 083 * @see org.kuali.rice.krad.uif.component.Component#performFinalize(org.kuali.rice.krad.uif.view.View, Object, 084 * org.kuali.rice.krad.uif.component.Component) 085 */ 086 @Override 087 public void performFinalize(View view, Object model, Component parent) { 088 super.performFinalize(view, model, parent); 089 090 if (options != null && !options.isEmpty()) { 091 for (KeyValue option : options) { 092 if (option instanceof UifKeyValueLocation) { 093 locationSelect = true; 094 UrlInfo url = ((UifKeyValueLocation) option).getLocation(); 095 ExpressionUtils.populatePropertyExpressionsFromGraph(url, false); 096 KRADServiceLocatorWeb.getExpressionEvaluatorService().evaluateExpressionsOnConfigurable(view, url, 097 model, view.getContext()); 098 } 099 } 100 } 101 102 if (richOptions == null || richOptions.isEmpty()) { 103 return; 104 } 105 106 //Messages included in options which have have rich message content need to be aware of their parent for 107 //validation purposes 108 for (KeyMessage richOption : richOptions) { 109 List<Component> components = richOption.getMessage().getMessageComponentStructure(); 110 111 if (components != null && !components.isEmpty()) { 112 for (Component c : components) { 113 if (c instanceof Container || c instanceof InputField) { 114 c.addDataAttribute(UifConstants.DataAttributes.PARENT, parent.getId()); 115 } 116 } 117 } 118 } 119 120 } 121 122 /** 123 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle() 124 */ 125 @Override 126 public List<Component> getComponentsForLifecycle() { 127 List<Component> components = super.getComponentsForLifecycle(); 128 129 if (richOptions != null) { 130 for (KeyMessage richOption : richOptions) { 131 components.add(richOption.getMessage()); 132 } 133 } 134 135 return components; 136 } 137 138 /** 139 * @see MultiValueControl#getOptions() 140 */ 141 @BeanTagAttribute(name = "options", type = BeanTagAttribute.AttributeType.LISTBEAN) 142 public List<KeyValue> getOptions() { 143 return this.options; 144 } 145 146 /** 147 * @see MultiValueControl#setOptions(java.util.List<org.kuali.rice.core.api.util.KeyValue>) 148 */ 149 public void setOptions(List<KeyValue> options) { 150 this.options = options; 151 } 152 153 /** 154 * Gets the inlineComponents which represent components that can be referenced in an option's value 155 * by index 156 * 157 * @return the components that can be used in rich values of options 158 */ 159 @BeanTagAttribute(name = "inlineComponents", type = BeanTagAttribute.AttributeType.LISTBEAN) 160 public List<Component> getInlineComponents() { 161 return inlineComponents; 162 } 163 164 /** 165 * Sets the inlineComponents which represent components that can be referenced in an option's value 166 * by index 167 * 168 * @param inlineComponents 169 */ 170 public void setInlineComponents(List<Component> inlineComponents) { 171 this.inlineComponents = inlineComponents; 172 } 173 174 /** 175 * @see MultiValueControl#getRichOptions() 176 */ 177 public List<KeyMessage> getRichOptions() { 178 return richOptions; 179 } 180 181 /** 182 * Sets the richOptions. This will always override/ignore options if set. 183 * 184 * <p><b>Messages MUST be defined</b> when using this setter, do not use this setter for most cases 185 * as setting options through setOptions, with a richMessage value, is appropriate in MOST cases. This 186 * setter is only available for full control.</p> 187 * 188 * @param richOptions with their messages predefined 189 */ 190 public void setRichOptions(List<KeyMessage> richOptions) { 191 this.richOptions = richOptions; 192 } 193 194 /** 195 * If true, this select represents a location select (navigate on select of option) 196 * 197 * @return true if this is a location select 198 */ 199 public boolean isLocationSelect() { 200 return locationSelect; 201 } 202 }