001    /**
002     * Copyright 2005-2012 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.container;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.krad.uif.component.Component;
020    import org.kuali.rice.krad.uif.component.DataBinding;
021    import org.kuali.rice.krad.uif.field.Field;
022    import org.kuali.rice.krad.uif.field.FieldGroup;
023    import org.kuali.rice.krad.uif.view.View;
024    import org.kuali.rice.krad.uif.widget.Scrollpane;
025    import org.kuali.rice.krad.uif.widget.Disclosure;
026    
027    import java.util.ArrayList;
028    import java.util.HashSet;
029    import java.util.List;
030    import java.util.Set;
031    
032    /**
033     * Container that holds a list of <code>Field</code> or other <code>Group</code>
034     * instances
035     * 
036     * <p>
037     * Groups can exist at different levels of the <code>View</code>, providing
038     * conceptual groupings such as the page, section, and group. In addition, other
039     * group types can be created to add behavior like collection support
040     * </p>
041     * 
042     * <p>
043     * <code>Group</code> implementation has properties for defaulting the binding
044     * information (such as the parent object path and a binding prefix) for the
045     * fields it contains. During the phase these properties (if given) are set on
046     * the fields contained in the <code>Group</code> that implement
047     * <code>DataBinding</code>, unless they have already been set on the field.
048     * </p>
049     * 
050     * @author Kuali Rice Team (rice.collab@kuali.org)
051     */
052    public class Group extends ContainerBase {
053            private static final long serialVersionUID = 7953641325356535509L;
054    
055            private String fieldBindByNamePrefix;
056            private String fieldBindingObjectPath;
057    
058            private Disclosure disclosure;
059        private Scrollpane scrollpane;
060    
061            private List<? extends Component> items;
062    
063            /**
064             * Default Constructor
065             */
066            public Group() {
067                    items = new ArrayList<Component>();
068            }
069    
070            /**
071             * The following actions are performed:
072             * 
073             * <ul>
074             * <li>Sets the bindByNamePrefix if blank on any InputField and
075             * FieldGroup instances within the items List</li>
076             * </ul>
077             * 
078             * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object)
079             */
080        @Override
081        public void performInitialization(View view, Object model) {
082            super.performInitialization(view, model);
083    
084            for (Component component : getItems()) {
085                // append group's field bind by name prefix (if set) to each
086                // attribute field's binding prefix
087                if (component instanceof DataBinding) {
088                    DataBinding dataBinding = (DataBinding) component;
089    
090                    if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
091                        String bindByNamePrefixToSet = getFieldBindByNamePrefix();
092    
093                        if (StringUtils.isNotBlank(dataBinding.getBindingInfo().getBindByNamePrefix())) {
094                            bindByNamePrefixToSet += "." + dataBinding.getBindingInfo().getBindByNamePrefix();
095                        }
096                        dataBinding.getBindingInfo().setBindByNamePrefix(bindByNamePrefixToSet);
097                    }
098    
099                    if (StringUtils.isNotBlank(fieldBindingObjectPath) &&
100                            StringUtils.isBlank(dataBinding.getBindingInfo().getBindingObjectPath())) {
101                        dataBinding.getBindingInfo().setBindingObjectPath(fieldBindingObjectPath);
102                    }
103                }
104                // set on FieldGroup's group to recursively set AttributeFields
105                else if (component instanceof FieldGroup) {
106                    FieldGroup fieldGroup = (FieldGroup) component;
107    
108                    if (fieldGroup.getGroup() != null) {
109                        if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindByNamePrefix())) {
110                            fieldGroup.getGroup().setFieldBindByNamePrefix(fieldBindByNamePrefix);
111                        }
112                        if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindingObjectPath())) {
113                            fieldGroup.getGroup().setFieldBindingObjectPath(fieldBindingObjectPath);
114                        }
115                    }
116                } else if (component instanceof Group) {
117                    Group subGroup = (Group) component;
118                    if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
119                        if (StringUtils.isNotBlank(subGroup.getFieldBindByNamePrefix())) {
120                            subGroup.setFieldBindByNamePrefix(
121                                    getFieldBindByNamePrefix() + "." + subGroup.getFieldBindByNamePrefix());
122                        } else {
123                            subGroup.setFieldBindByNamePrefix(getFieldBindByNamePrefix());
124                        }
125                    }
126                    if (StringUtils.isNotBlank(getFieldBindingObjectPath())) {
127                        if (StringUtils.isNotBlank(subGroup.getFieldBindingObjectPath())) {
128                            subGroup.setFieldBindingObjectPath(
129                                    getFieldBindingObjectPath() + "." + subGroup.getFieldBindingObjectPath());
130                        } else {
131                            subGroup.setFieldBindingObjectPath(getFieldBindingObjectPath());
132                        }
133                    }
134                }
135            }
136        }
137    
138            /**
139             * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
140             */
141            @Override
142            public List<Component> getComponentsForLifecycle() {
143                    List<Component> components = super.getComponentsForLifecycle();
144    
145                    components.add(disclosure);
146            components.add(scrollpane);
147    
148                    return components;
149            }
150    
151            /**
152             * @see org.kuali.rice.krad.uif.container.Container#getSupportedComponents()
153             */
154            @Override
155            public Set<Class<? extends Component>> getSupportedComponents() {
156                    Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
157                    supportedComponents.add(Field.class);
158                    supportedComponents.add(Group.class);
159    
160                    return supportedComponents;
161            }
162    
163            /**
164             * @see org.kuali.rice.krad.uif.component.Component#getComponentTypeName()
165             */
166            @Override
167            public String getComponentTypeName() {
168                    return "group";
169            }
170    
171            /**
172             * Binding prefix string to set on each of the groups <code>DataField</code> instances
173         *
174             * <p>
175             * As opposed to setting the bindingPrefix on each attribute field instance,
176             * it can be set here for the group. During initialize the string will then
177             * be set on each attribute field instance if the bindingPrefix is blank and
178             * not a form field
179             * </p>
180             * 
181             * @return String binding prefix to set
182             */
183            public String getFieldBindByNamePrefix() {
184                    return this.fieldBindByNamePrefix;
185            }
186    
187            /**
188             * Setter for the field binding prefix
189             * 
190             * @param fieldBindByNamePrefix
191             */
192            public void setFieldBindByNamePrefix(String fieldBindByNamePrefix) {
193                    this.fieldBindByNamePrefix = fieldBindByNamePrefix;
194            }
195    
196            /**
197             * Object binding path to set on each of the group's
198             * <code>InputField</code> instances
199             * 
200             * <p>
201             * When the attributes of the group belong to a object whose path is
202             * different from the default then this property can be given to set each of
203             * the attributes instead of setting the model path on each one. The object
204             * path can be overridden at the attribute level. The object path is set to
205             * the fieldBindingObjectPath during the initialize phase.
206             * </p>
207             * 
208             * @return String model path to set
209             * @see org.kuali.rice.krad.uif.component.BindingInfo#getBindingObjectPath()
210             */
211            public String getFieldBindingObjectPath() {
212                    return this.fieldBindingObjectPath;
213            }
214    
215            /**
216             * Setter for the field object binding path
217             * 
218             * @param fieldBindingObjectPath
219             */
220            public void setFieldBindingObjectPath(String fieldBindingObjectPath) {
221                    this.fieldBindingObjectPath = fieldBindingObjectPath;
222            }
223    
224            /**
225             * Disclosure widget that provides collapse/expand functionality for the
226             * group
227             * 
228             * @return Disclosure instance
229             */
230            public Disclosure getDisclosure() {
231                    return this.disclosure;
232            }
233    
234            /**
235             * Setter for the group's disclosure instance
236             * 
237             * @param disclosure
238             */
239            public void setDisclosure(Disclosure disclosure) {
240                    this.disclosure = disclosure;
241            }
242    
243        /**
244         * Scrollpane widget that provides scrolling functionality for the
245         * group
246         *
247         * @return Scrollpane instance
248         */
249        public Scrollpane getScrollpane() {
250            return this.scrollpane;
251        }
252    
253        /**
254         * Setter for the group's scrollpane instance
255         *
256         * @param scrollpane
257         */
258        public void setScrollpane(Scrollpane scrollpane) {
259            this.scrollpane = scrollpane;
260        }
261    
262        /**
263             * @see org.kuali.rice.krad.uif.container.ContainerBase#getItems()
264             */
265            @Override
266            public List<? extends Component> getItems() {
267                    return this.items;
268            }
269    
270            /**
271             * Setter for the Group's list of components
272             * 
273             * @param items
274             */
275            @Override
276            public void setItems(List<? extends Component> items) {
277                    this.items = items;
278            }
279    
280    }