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 }