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