View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.container;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.krad.datadictionary.validator.ErrorReport;
20  import org.kuali.rice.krad.datadictionary.validator.RDValidator;
21  import org.kuali.rice.krad.datadictionary.validator.TracerToken;
22  import org.kuali.rice.krad.uif.component.Component;
23  import org.kuali.rice.krad.uif.component.DataBinding;
24  import org.kuali.rice.krad.uif.field.Field;
25  import org.kuali.rice.krad.uif.field.FieldGroup;
26  import org.kuali.rice.krad.uif.view.View;
27  import org.kuali.rice.krad.uif.widget.Scrollpane;
28  import org.kuali.rice.krad.uif.widget.Disclosure;
29  
30  import java.util.ArrayList;
31  import java.util.HashSet;
32  import java.util.List;
33  import java.util.Set;
34  
35  /**
36   * Container that holds a list of <code>Field</code> or other <code>Group</code>
37   * instances
38   * 
39   * <p>
40   * Groups can exist at different levels of the <code>View</code>, providing
41   * conceptual groupings such as the page, section, and group. In addition, other
42   * group types can be created to add behavior like collection support
43   * </p>
44   * 
45   * <p>
46   * <code>Group</code> implementation has properties for defaulting the binding
47   * information (such as the parent object path and a binding prefix) for the
48   * fields it contains. During the phase these properties (if given) are set on
49   * the fields contained in the <code>Group</code> that implement
50   * <code>DataBinding</code>, unless they have already been set on the field.
51   * </p>
52   * 
53   * @author Kuali Rice Team (rice.collab@kuali.org)
54   */
55  public class Group extends ContainerBase {
56  	private static final long serialVersionUID = 7953641325356535509L;
57  
58  	private String fieldBindByNamePrefix;
59  	private String fieldBindingObjectPath;
60  
61  	private Disclosure disclosure;
62      private Scrollpane scrollpane;
63  
64  	private List<? extends Component> items;
65  
66  	/**
67  	 * Default Constructor
68  	 */
69  	public Group() {
70  		items = new ArrayList<Component>();
71  	}
72  
73  	/**
74  	 * The following actions are performed:
75  	 * 
76  	 * <ul>
77  	 * <li>Sets the bindByNamePrefix if blank on any InputField and
78  	 * FieldGroup instances within the items List</li>
79  	 * </ul>
80  	 * 
81  	 * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object)
82  	 */
83      @Override
84      public void performInitialization(View view, Object model) {
85          super.performInitialization(view, model);
86  
87          for (Component component : getItems()) {
88              // append group's field bind by name prefix (if set) to each
89              // attribute field's binding prefix
90              if (component instanceof DataBinding) {
91                  DataBinding dataBinding = (DataBinding) component;
92  
93                  if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
94                      String bindByNamePrefixToSet = getFieldBindByNamePrefix();
95  
96                      if (StringUtils.isNotBlank(dataBinding.getBindingInfo().getBindByNamePrefix())) {
97                          bindByNamePrefixToSet += "." + dataBinding.getBindingInfo().getBindByNamePrefix();
98                      }
99                      dataBinding.getBindingInfo().setBindByNamePrefix(bindByNamePrefixToSet);
100                 }
101 
102                 if (StringUtils.isNotBlank(fieldBindingObjectPath) &&
103                         StringUtils.isBlank(dataBinding.getBindingInfo().getBindingObjectPath())) {
104                     dataBinding.getBindingInfo().setBindingObjectPath(fieldBindingObjectPath);
105                 }
106             }
107             // set on FieldGroup's group to recursively set AttributeFields
108             else if (component instanceof FieldGroup) {
109                 FieldGroup fieldGroup = (FieldGroup) component;
110 
111                 if (fieldGroup.getGroup() != null) {
112                     if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindByNamePrefix())) {
113                         fieldGroup.getGroup().setFieldBindByNamePrefix(fieldBindByNamePrefix);
114                     }
115                     if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindingObjectPath())) {
116                         fieldGroup.getGroup().setFieldBindingObjectPath(fieldBindingObjectPath);
117                     }
118                 }
119             } else if (component instanceof Group) {
120                 Group subGroup = (Group) component;
121                 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
122                     if (StringUtils.isNotBlank(subGroup.getFieldBindByNamePrefix())) {
123                         subGroup.setFieldBindByNamePrefix(
124                                 getFieldBindByNamePrefix() + "." + subGroup.getFieldBindByNamePrefix());
125                     } else {
126                         subGroup.setFieldBindByNamePrefix(getFieldBindByNamePrefix());
127                     }
128                 }
129                 if (StringUtils.isNotBlank(getFieldBindingObjectPath())) {
130                     if (StringUtils.isNotBlank(subGroup.getFieldBindingObjectPath())) {
131                         subGroup.setFieldBindingObjectPath(
132                                 getFieldBindingObjectPath() + "." + subGroup.getFieldBindingObjectPath());
133                     } else {
134                         subGroup.setFieldBindingObjectPath(getFieldBindingObjectPath());
135                     }
136                 }
137             }
138         }
139     }
140 
141 	/**
142 	 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
143 	 */
144 	@Override
145 	public List<Component> getComponentsForLifecycle() {
146 		List<Component> components = super.getComponentsForLifecycle();
147 
148 		components.add(disclosure);
149         components.add(scrollpane);
150 
151 		return components;
152 	}
153 
154 	/**
155 	 * @see org.kuali.rice.krad.uif.container.Container#getSupportedComponents()
156 	 */
157 	@Override
158 	public Set<Class<? extends Component>> getSupportedComponents() {
159 		Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
160 		supportedComponents.add(Field.class);
161 		supportedComponents.add(Group.class);
162 
163 		return supportedComponents;
164 	}
165 
166 	/**
167 	 * @see org.kuali.rice.krad.uif.component.Component#getComponentTypeName()
168 	 */
169 	@Override
170 	public String getComponentTypeName() {
171 		return "group";
172 	}
173 
174 	/**
175 	 * Binding prefix string to set on each of the groups <code>DataField</code> instances
176      *
177 	 * <p>
178 	 * As opposed to setting the bindingPrefix on each attribute field instance,
179 	 * it can be set here for the group. During initialize the string will then
180 	 * be set on each attribute field instance if the bindingPrefix is blank and
181 	 * not a form field
182 	 * </p>
183 	 * 
184 	 * @return String binding prefix to set
185 	 */
186 	public String getFieldBindByNamePrefix() {
187 		return this.fieldBindByNamePrefix;
188 	}
189 
190 	/**
191 	 * Setter for the field binding prefix
192 	 * 
193 	 * @param fieldBindByNamePrefix
194 	 */
195 	public void setFieldBindByNamePrefix(String fieldBindByNamePrefix) {
196 		this.fieldBindByNamePrefix = fieldBindByNamePrefix;
197 	}
198 
199 	/**
200 	 * Object binding path to set on each of the group's
201 	 * <code>InputField</code> instances
202 	 * 
203 	 * <p>
204 	 * When the attributes of the group belong to a object whose path is
205 	 * different from the default then this property can be given to set each of
206 	 * the attributes instead of setting the model path on each one. The object
207 	 * path can be overridden at the attribute level. The object path is set to
208 	 * the fieldBindingObjectPath during the initialize phase.
209 	 * </p>
210 	 * 
211 	 * @return String model path to set
212 	 * @see org.kuali.rice.krad.uif.component.BindingInfo#getBindingObjectPath()
213 	 */
214 	public String getFieldBindingObjectPath() {
215 		return this.fieldBindingObjectPath;
216 	}
217 
218 	/**
219 	 * Setter for the field object binding path
220 	 * 
221 	 * @param fieldBindingObjectPath
222 	 */
223 	public void setFieldBindingObjectPath(String fieldBindingObjectPath) {
224 		this.fieldBindingObjectPath = fieldBindingObjectPath;
225 	}
226 
227 	/**
228 	 * Disclosure widget that provides collapse/expand functionality for the
229 	 * group
230 	 * 
231 	 * @return Disclosure instance
232 	 */
233 	public Disclosure getDisclosure() {
234 		return this.disclosure;
235 	}
236 
237 	/**
238 	 * Setter for the group's disclosure instance
239 	 * 
240 	 * @param disclosure
241 	 */
242 	public void setDisclosure(Disclosure disclosure) {
243 		this.disclosure = disclosure;
244 	}
245 
246     /**
247      * Scrollpane widget that provides scrolling functionality for the
248      * group
249      *
250      * @return Scrollpane instance
251      */
252     public Scrollpane getScrollpane() {
253         return this.scrollpane;
254     }
255 
256     /**
257      * Setter for the group's scrollpane instance
258      *
259      * @param scrollpane
260      */
261     public void setScrollpane(Scrollpane scrollpane) {
262         this.scrollpane = scrollpane;
263     }
264 
265     /**
266 	 * @see org.kuali.rice.krad.uif.container.ContainerBase#getItems()
267 	 */
268 	@Override
269 	public List<? extends Component> getItems() {
270 		return this.items;
271 	}
272 
273 	/**
274 	 * Setter for the Group's list of components
275 	 * 
276 	 * @param items
277 	 */
278 	@Override
279 	public void setItems(List<? extends Component> items) {
280 		this.items = items;
281 	}
282 
283     /**
284      * @see org.kuali.rice.krad.uif.component.Component#completeValidation
285      */
286     @Override
287     public ArrayList<ErrorReport> completeValidation(TracerToken tracer){
288         ArrayList<ErrorReport> reports=new ArrayList<ErrorReport>();
289         tracer.addBean(this);
290 
291         // Checks that no invalid items are present
292         for(int i=0;i<getItems().size();i++){
293             if(getItems().get(i).getClass()==PageGroup.class || getItems().get(i).getClass()==NavigationGroup.class){
294                 ErrorReport error = ErrorReport.createError("Items in Group cannot be PageGroup or NaviagtionGroup",tracer);
295                 error.addCurrentValue("item("+i+").class ="+getItems().get(i).getClass());
296                 reports.add(error);
297             }
298         }
299 
300         // Checks that the layout manager is set
301         if(getLayoutManager()==null){
302             if(RDValidator.checkExpressions(this,"layoutManager")){
303                 ErrorReport error = ErrorReport.createError("LayoutManager must be set",tracer);
304                 error.addCurrentValue("layoutManager = "+getLayoutManager());
305                 reports.add(error);
306             }
307         }
308 
309         reports.addAll(super.completeValidation(tracer.getCopy()));
310 
311         return reports;
312     }
313 }