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 }