View Javadoc

1   /**
2    * Copyright 2005-2011 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.uif.component.Component;
20  import org.kuali.rice.krad.uif.component.ComponentBase;
21  import org.kuali.rice.krad.uif.field.InputField;
22  import org.kuali.rice.krad.uif.field.ErrorsField;
23  import org.kuali.rice.krad.uif.field.HeaderField;
24  import org.kuali.rice.krad.uif.field.MessageField;
25  import org.kuali.rice.krad.uif.layout.LayoutManager;
26  import org.kuali.rice.krad.uif.util.ComponentUtils;
27  import org.kuali.rice.krad.uif.view.View;
28  import org.kuali.rice.krad.uif.widget.Help;
29  
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  /**
34   * Base <code>Container</code> implementation which container implementations
35   * can extend
36   * 
37   * <p>
38   * Provides properties for the basic <code>Container</code> functionality in
39   * addition to default implementation of the lifecycle methods including some
40   * setup of the header, items list, and layout manager
41   * </p>
42   * 
43   * @author Kuali Rice Team (rice.collab@kuali.org)
44   */
45  public abstract class ContainerBase extends ComponentBase implements Container {
46  	private static final long serialVersionUID = -4182226230601746657L;
47  
48  	private int itemOrderingSequence;
49  
50  	private String additionalMessageKeys;
51  	private ErrorsField errorsField;
52  
53  	private Help help;
54  	private LayoutManager layoutManager;
55  
56  	private HeaderField header;
57  	private Group footer;
58  
59  	private String instructionalText;
60  	private MessageField instructionalMessageField;
61  
62  	private boolean fieldContainer;
63  
64  	/**
65  	 * Default Constructor
66  	 */
67  	public ContainerBase() {
68  		itemOrderingSequence = 1;
69  	}
70  
71  	/**
72  	 * The following initialization is performed:
73  	 * 
74  	 * <ul>
75  	 * <li>Sorts the containers list of components</li>
76  	 * <li>Initializes LayoutManager</li>
77  	 * </ul>
78  	 * 
79  	 * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object)
80  	 */
81  	@SuppressWarnings("unchecked")
82  	@Override
83  	public void performInitialization(View view, Object model) {
84  		super.performInitialization(view, model);
85  
86  		// sort items list by the order property
87  		List<? extends Component> sortedItems = (List<? extends Component>) ComponentUtils.sort(getItems(),
88  				itemOrderingSequence);
89  		setItems(sortedItems);
90  
91  		if (layoutManager != null) {
92  			layoutManager.performInitialization(view, model, this);
93  		}
94  	}
95  
96  	/**
97  	 * @see org.kuali.rice.krad.uif.component.ComponentBase#performApplyModel(org.kuali.rice.krad.uif.view.View,
98  	 *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
99  	 */
100 	@Override
101 	public void performApplyModel(View view, Object model, Component parent) {
102 		super.performApplyModel(view, model, parent);
103 
104 		if (layoutManager != null) {
105 			layoutManager.performApplyModel(view, model, this);
106 		}
107 	}
108 
109 	/**
110 	 * The following finalization is performed:
111 	 * 
112 	 * <ul>
113 	 * <li>Sets the headerText of the header Group if it is blank</li>
114 	 * <li>Set the messageText of the summary MessageField if it is blank</li>
115 	 * <li>Finalizes LayoutManager</li>
116 	 * </ul>
117 	 * 
118 	 * @see org.kuali.rice.krad.uif.component.ComponentBase#performFinalize(org.kuali.rice.krad.uif.view.View,
119 	 *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
120 	 */
121 	@Override
122 	public void performFinalize(View view, Object model, Component parent) {
123 		super.performFinalize(view, model, parent);
124 
125 		// if header title not given, use the container title
126 		if (header != null && StringUtils.isBlank(header.getHeaderText())) {
127 			header.setHeaderText(this.getTitle());
128 		}
129 
130 		// setup summary message field if necessary
131 		if (instructionalMessageField != null && StringUtils.isBlank(instructionalMessageField.getMessageText())) {
132 			instructionalMessageField.setMessageText(instructionalText);
133 		}
134 
135 		if (layoutManager != null) {
136 			layoutManager.performFinalize(view, model, this);
137 		}
138 	}
139 
140 	/**
141 	 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
142 	 */
143 	@Override
144 	public List<Component> getComponentsForLifecycle() {
145 		List<Component> components = super.getComponentsForLifecycle();
146 
147 		components.add(header);
148 		components.add(footer);
149 		components.add(errorsField);
150 		components.add(help);
151 		components.add(instructionalMessageField);
152 
153 		for (Component component : getItems()) {
154 			components.add(component);
155 		}
156 
157 		if (layoutManager != null) {
158 			components.addAll(layoutManager.getComponentsForLifecycle());
159 		}
160 
161 		return components;
162 	}
163 
164     /**
165      * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes()
166      */
167     @Override
168     public List<Component> getComponentPrototypes() {
169         List<Component> components = super.getComponentPrototypes();
170 
171         if (layoutManager != null) {
172             components.addAll(layoutManager.getComponentPrototypes());
173         }
174 
175         return components;
176     }
177 
178 	/**
179 	 * Additional keys that should be matching on when gathering errors or other
180 	 * messages for the <code>Container</code>
181 	 * 
182 	 * <p>
183 	 * Messages associated with the container will be displayed with the
184 	 * container grouping in the user interface. Typically, these are a result
185 	 * of problems with the containers fields or some other business logic
186 	 * associated with the containers information. The framework will by default
187 	 * include all the error keys for fields in the container, and also an
188 	 * errors associated with the containers id. Keys given here will be matched
189 	 * in addition to those defaults.
190 	 * </p>
191 	 * 
192 	 * <p>
193 	 * Multple keys can be given using the comma delimiter, the * wildcard is
194 	 * also allowed in the message key
195 	 * </p>
196 	 * 
197 	 * @return String additional message key string
198 	 */
199 	public String getAdditionalMessageKeys() {
200 		return this.additionalMessageKeys;
201 	}
202 
203 	/**
204 	 * Setter for the components additional message key string
205 	 * 
206 	 * @param additionalMessageKeys
207 	 */
208 	public void setAdditionalMessageKeys(String additionalMessageKeys) {
209 		this.additionalMessageKeys = additionalMessageKeys;
210 	}
211 
212 	/**
213 	 * @see org.kuali.rice.krad.uif.container.Container#getErrorsField()
214 	 */
215 	@Override
216 	public ErrorsField getErrorsField() {
217 		return this.errorsField;
218 	}
219 
220 	/**
221 	 * @see org.kuali.rice.krad.uif.container.Container#setErrorsField(org.kuali.rice.krad.uif.field.ErrorsField)
222 	 */
223 	@Override
224 	public void setErrorsField(ErrorsField errorsField) {
225 		this.errorsField = errorsField;
226 	}
227 
228 	/**
229 	 * @see org.kuali.rice.krad.uif.container.Container#getHelp()
230 	 */
231 	@Override
232 	public Help getHelp() {
233 		return this.help;
234 	}
235 
236 	/**
237 	 * @see org.kuali.rice.krad.uif.container.Container#setHelp(org.kuali.rice.krad.uif.widget.Help)
238 	 */
239 	@Override
240 	public void setHelp(Help help) {
241 		this.help = help;
242 	}
243 
244 	/**
245 	 * @see org.kuali.rice.krad.uif.container.Container#getItems()
246 	 */
247 	@Override
248 	public abstract List<? extends Component> getItems();
249 
250 	/**
251 	 * Setter for the containers list of components
252 	 * 
253 	 * @param items
254 	 */
255 	public abstract void setItems(List<? extends Component> items);
256 
257 	/**
258 	 * For <code>Component</code> instances in the container's items list that
259 	 * do not have an order set, a default order number will be assigned using
260 	 * this property. The first component found in the list without an order
261 	 * will be assigned the configured initial value, and incremented by one for
262 	 * each component (without an order) found afterwards
263 	 * 
264 	 * @return int order sequence
265 	 */
266 	public int getItemOrderingSequence() {
267 		return this.itemOrderingSequence;
268 	}
269 
270 	/**
271 	 * Setter for the container's item ordering sequence number (initial value)
272 	 * 
273 	 * @param itemOrderingSequence
274 	 */
275 	public void setItemOrderingSequence(int itemOrderingSequence) {
276 		this.itemOrderingSequence = itemOrderingSequence;
277 	}
278 
279 	/**
280 	 * @see org.kuali.rice.krad.uif.container.Container#getLayoutManager()
281 	 */
282 	@Override
283 	public LayoutManager getLayoutManager() {
284 		return this.layoutManager;
285 	}
286 
287 	/**
288 	 * @see org.kuali.rice.krad.uif.container.Container#setLayoutManager(org.kuali.rice.krad.uif.layout.LayoutManager)
289 	 */
290 	@Override
291 	public void setLayoutManager(LayoutManager layoutManager) {
292 		this.layoutManager = layoutManager;
293 	}
294 
295 	/**
296 	 * @see org.kuali.rice.krad.uif.container.Container#getHeader()
297 	 */
298 	@Override
299 	public HeaderField getHeader() {
300 		return this.header;
301 	}
302 
303 	/**
304 	 * @see org.kuali.rice.krad.uif.container.Container#setHeader(org.kuali.rice.krad.uif.field.HeaderField)
305 	 */
306 	@Override
307 	public void setHeader(HeaderField header) {
308 		this.header = header;
309 	}
310 
311 	/**
312 	 * @see org.kuali.rice.krad.uif.container.Container#getFooter()
313 	 */
314 	@Override
315 	public Group getFooter() {
316 		return this.footer;
317 	}
318 
319 	/**
320 	 * @see org.kuali.rice.krad.uif.container.Container#setFooter(org.kuali.rice.krad.uif.container.Group)
321 	 */
322 	@Override
323 	public void setFooter(Group footer) {
324 		this.footer = footer;
325 	}
326 
327 	/**
328 	 * Convenience setter for configuration to turn rendering of the header
329 	 * on/off
330 	 * 
331 	 * <p>
332 	 * For nested groups (like Field Groups) it is often necessary to only show
333 	 * the container body (the contained components). This method allows the
334 	 * header to not be displayed
335 	 * </p>
336 	 * 
337 	 * @param renderHeader
338 	 */
339 	public void setRenderHeader(boolean renderHeader) {
340 		if (header != null) {
341 			header.setRender(renderHeader);
342 		}
343 	}
344 
345 	/**
346 	 * Convenience setter for configuration to turn rendering of the footer
347 	 * on/off
348 	 * 
349 	 * <p>
350 	 * For nested groups it is often necessary to only show the container body
351 	 * (the contained components). This method allows the footer to not be
352 	 * displayed
353 	 * </p>
354 	 * 
355 	 * @param renderFooter
356 	 */
357 	public void setRenderFooter(boolean renderFooter) {
358 		if (footer != null) {
359 			footer.setRender(renderFooter);
360 		}
361 	}
362 
363     /**
364      * Text explaining how complete the group inputs, including things like what values should be selected
365      * in certain cases, what fields should be completed and so on (instructions)
366      *
367      * @return String instructional message
368      */
369 	public String getInstructionalText() {
370 		return this.instructionalText;
371 	}
372 
373     /**
374      * Setter for the instructional message
375      *
376      * @param instructionalText
377      */
378 	public void setInstructionalText(String instructionalText) {
379 		this.instructionalText = instructionalText;
380 	}
381 
382     /**
383      * Message field that displays instructional text
384      *
385      * <p>
386      * This message field can be configured to for adjusting how the instructional text will display. Generally
387      * the styleClasses property will be of most interest
388      * </p>
389      *
390      * @return MessageField instructional message field
391      */
392 	public MessageField getInstructionalMessageField() {
393 		return this.instructionalMessageField;
394 	}
395 
396     /**
397      * Setter for the instructional text message field
398      *
399      * <p>
400      * Note this is the setter for the field that will render the instructional text. The actual text can be
401      * set on the field but can also be set using {@link #setInstructionalText(String)}
402      * </p>
403      *
404      * @param instructionalMessageField
405      */
406 	public void setInstructionalMessageField(MessageField instructionalMessageField) {
407 		this.instructionalMessageField = instructionalMessageField;
408 	}
409 
410 	/**
411 	 * Gets only the data fields that are nested in this container.  This is a subset of
412 	 * what getComponentsForLifecycle() returns
413 	 * 
414 	 * @return
415 	 */
416 	public List<InputField> getInputFields(){
417 		List<InputField> inputFields = new ArrayList<InputField>();
418 		for(Component c: this.getComponentsForLifecycle()){
419 			if(c instanceof InputField){
420 				inputFields.add((InputField)c);
421 			}
422 		}
423 		return inputFields;
424 		
425 	}
426 
427 	/**
428 	 * This property is true if the container is used to display a group of fields that is visually a single
429 	 * field.
430 	 * @return the fieldContainer
431 	 */
432 	public boolean isFieldContainer() {
433 		return this.fieldContainer;
434 	}
435 
436 	/**
437 	 * @param fieldContainer the fieldContainer to set
438 	 */
439 	public void setFieldContainer(boolean fieldContainer) {
440 		this.fieldContainer = fieldContainer;
441 	}
442 
443 }