1 /**
2 * Copyright 2005-2014 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.view;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.datadictionary.DataDictionary;
20 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
21 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
22 import org.kuali.rice.krad.datadictionary.parse.BeanTags;
23 import org.kuali.rice.krad.datadictionary.state.StateMapping;
24 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
25 import org.kuali.rice.krad.datadictionary.validator.Validator;
26 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
27 import org.kuali.rice.krad.uif.UifConstants;
28 import org.kuali.rice.krad.uif.UifConstants.ViewStatus;
29 import org.kuali.rice.krad.uif.UifConstants.ViewType;
30 import org.kuali.rice.krad.uif.component.Component;
31 import org.kuali.rice.krad.uif.component.ReferenceCopy;
32 import org.kuali.rice.krad.uif.component.RequestParameter;
33 import org.kuali.rice.krad.uif.container.Container;
34 import org.kuali.rice.krad.uif.container.ContainerBase;
35 import org.kuali.rice.krad.uif.container.Group;
36 import org.kuali.rice.krad.uif.container.NavigationGroup;
37 import org.kuali.rice.krad.uif.container.PageGroup;
38 import org.kuali.rice.krad.uif.element.Header;
39 import org.kuali.rice.krad.uif.element.Link;
40 import org.kuali.rice.krad.uif.layout.LayoutManager;
41 import org.kuali.rice.krad.uif.service.ViewHelperService;
42 import org.kuali.rice.krad.uif.util.BooleanMap;
43 import org.kuali.rice.krad.uif.util.ClientValidationUtils;
44 import org.kuali.rice.krad.uif.widget.BlockUI;
45 import org.kuali.rice.krad.uif.widget.BreadCrumbs;
46 import org.kuali.rice.krad.uif.widget.Growls;
47 import org.kuali.rice.krad.util.ObjectUtils;
48 import org.kuali.rice.krad.web.form.UifFormBase;
49
50 import java.util.ArrayList;
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.Set;
56
57 /**
58 * Root of the component tree which encompasses a set of related
59 * <code>GroupContainer</code> instances tied together with a common page layout
60 * and navigation.
61 *
62 * <p>
63 * The <code>View</code> component ties together all the components and
64 * configuration of the User Interface for a piece of functionality. In Rice
65 * applications the view is typically associated with a <code>Document</code>
66 * instance.
67 * </p>
68 *
69 * <p>
70 * The view template lays out the common header, footer, and navigation for the
71 * related pages. In addition the view renders the HTML head element bringing in
72 * common script files and style sheets, along with optionally rendering a form
73 * element for pages that need to post data back to the server.
74 * </p>
75 *
76 * <p>
77 * Configuration of UIF features such as model validation is also done through
78 * the <code>View</code>
79 * </p>
80 *
81 * @author Kuali Rice Team (rice.collab@kuali.org)
82 */
83 @BeanTags({@BeanTag(name = "view-bean", parent = "Uif-View"), @BeanTag(name = "view-knsTheme-bean", parent = "Uif-View-KnsTheme")
84 })
85 public class View extends ContainerBase {
86 private static final long serialVersionUID = -1220009725554576953L;
87
88 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(View.class);
89
90 private String namespaceCode;
91 private String viewName;
92 private ViewTheme theme;
93
94 private int idSequence;
95
96 private String stateObjectBindingPath;
97 private StateMapping stateMapping;
98
99 // application
100 private Header applicationHeader;
101 private Group applicationFooter;
102
103 // Breadcrumbs
104 private BreadCrumbs breadcrumbs;
105 private String breadcrumbTitlePropertyName;
106 private String breadcrumbTitleDisplayOption;
107
108 private boolean renderBreadcrumbsInView;
109
110 // Growls support
111 private Growls growls;
112 private boolean growlMessagingEnabled;
113
114 private BlockUI refreshBlockUI;
115 private BlockUI navigationBlockUI;
116
117 private String entryPageId;
118
119 @RequestParameter
120 private String currentPageId;
121
122 private Group navigation;
123
124 private Class<?> formClass;
125 private String defaultBindingObjectPath;
126 private Map<String, Class<?>> objectPathToConcreteClassMapping;
127
128 private List<String> additionalScriptFiles;
129 private List<String> additionalCssFiles;
130
131 private ViewType viewTypeName;
132
133 private String viewStatus;
134 private ViewIndex viewIndex;
135 private Map<String, String> viewRequestParameters;
136
137 private boolean persistFormToSession;
138
139 private ViewPresentationController presentationController;
140 private ViewAuthorizer authorizer;
141
142 private BooleanMap actionFlags;
143 private BooleanMap editModes;
144
145 private Map<String, String> expressionVariables;
146
147 private boolean singlePageView;
148 private boolean mergeWithPageItems;
149 private PageGroup page;
150
151 private List<? extends Group> items;
152 private List<? extends Group> dialogs;
153
154 private Link viewMenuLink;
155 private String viewMenuGroupName;
156
157 private boolean applyDirtyCheck;
158 private boolean translateCodesOnReadOnlyDisplay;
159 private boolean supportsRequestOverrideOfReadOnlyFields;
160
161 private String preLoadScript;
162
163 private int preloadPoolSize;
164
165 private List<String> viewTemplates;
166
167 private Class<? extends ViewHelperService> viewHelperServiceClass;
168
169 @ReferenceCopy
170 private ViewHelperService viewHelperService;
171
172 public View() {
173 singlePageView = false;
174 mergeWithPageItems = true;
175 translateCodesOnReadOnlyDisplay = false;
176 viewTypeName = ViewType.DEFAULT;
177 viewStatus = UifConstants.ViewStatus.CREATED;
178 formClass = UifFormBase.class;
179 renderBreadcrumbsInView = true;
180 supportsRequestOverrideOfReadOnlyFields = true;
181 persistFormToSession = true;
182
183 idSequence = 0;
184 this.viewIndex = new ViewIndex();
185 preloadPoolSize = 0;
186
187 additionalScriptFiles = new ArrayList<String>();
188 additionalCssFiles = new ArrayList<String>();
189 items = new ArrayList<Group>();
190 objectPathToConcreteClassMapping = new HashMap<String, Class<?>>();
191 viewRequestParameters = new HashMap<String, String>();
192 expressionVariables = new HashMap<String, String>();
193
194 dialogs = new ArrayList<Group>();
195 viewTemplates = new ArrayList<String>();
196 }
197
198 /**
199 * The following initialization is performed:
200 *
201 * <ul>
202 * <li>If a single paged view, set items in page group and put the page in
203 * the items list</li>
204 * </ul>
205 *
206 * @see org.kuali.rice.krad.uif.container.ContainerBase#performInitialization(View, java.lang.Object)
207 */
208 @SuppressWarnings("unchecked")
209 @Override
210 public void performInitialization(View view, Object model) {
211 super.performInitialization(view, model);
212
213 // populate items on page for single paged view
214 if (singlePageView) {
215 if (page != null) {
216 // remove default sections of page when requested
217 if (!mergeWithPageItems) {
218 page.setItems(new ArrayList<Group>());
219 }
220
221 view.assignComponentIds(page);
222
223 // add the items configured on the view to the page items, and set as the
224 // new page items
225 List<Component> newItems = (List<Component>) page.getItems();
226 newItems.addAll(items);
227 page.setItems(newItems);
228
229 // reset the items list to include the one page
230 items = new ArrayList<Group>();
231 ((List<Group>) items).add(page);
232 } else {
233 throw new RuntimeException("For single paged views the page Group must be set.");
234 }
235 }
236
237 // make sure all the pages have ids before selecting the current page
238 for (Group group : this.getItems()) {
239 if (StringUtils.isBlank(group.getId())) {
240 group.setId(view.getNextId());
241 }
242 }
243 }
244
245 /**
246 * The following updates are done here:
247 *
248 * <ul>
249 * <li>Invoke expression evaluation on view theme</li>
250 * </ul>
251 */
252 public void performApplyModel(View view, Object model, Component parent) {
253 super.performApplyModel(view, model, parent);
254
255 if (theme != null) {
256 KRADServiceLocatorWeb.getExpressionEvaluatorService().evaluateExpressionsOnConfigurable(view, theme, model,
257 getContext());
258 }
259 }
260
261 /**
262 * The following is performed:
263 *
264 * <ul>
265 * <li>Adds to its document ready script the setupValidator js function for setting
266 * up the validator for this view</li>
267 * </ul>
268 *
269 * @see org.kuali.rice.krad.uif.container.ContainerBase#performFinalize(View,
270 * java.lang.Object, org.kuali.rice.krad.uif.component.Component)
271 */
272 @Override
273 public void performFinalize(View view, Object model, Component parent) {
274 super.performFinalize(view, model, parent);
275
276 String preLoadScript = "";
277 if (this.getPreLoadScript() != null) {
278 preLoadScript = this.getPreLoadScript();
279 }
280
281 // Retrieve Growl and BlockUI settings
282 Growls gw = view.getGrowls();
283 if (!gw.getTemplateOptions().isEmpty()) {
284 preLoadScript += "setGrowlDefaults(" + gw.getTemplateOptionsJSString() + ");";
285 }
286
287 BlockUI navBlockUI = view.getNavigationBlockUI();
288 if (!navBlockUI.getTemplateOptions().isEmpty()) {
289 preLoadScript += "setBlockUIDefaults("
290 + navBlockUI.getTemplateOptionsJSString()
291 + ", '"
292 + UifConstants.BLOCKUI_NAVOPTS
293 + "');";
294 }
295
296 BlockUI refBlockUI = view.getRefreshBlockUI();
297 if (!refBlockUI.getTemplateOptions().isEmpty()) {
298 preLoadScript += "setBlockUIDefaults("
299 + refBlockUI.getTemplateOptionsJSString()
300 + ", '"
301 + UifConstants.BLOCKUI_REFRESHOPTS
302 + "');";
303 }
304
305 this.setPreLoadScript(preLoadScript);
306
307 String onReadyScript = "";
308 if (this.getOnDocumentReadyScript() != null) {
309 onReadyScript = this.getOnDocumentReadyScript();
310 }
311
312 this.setOnDocumentReadyScript(onReadyScript + "jQuery.extend(jQuery.validator.messages, " +
313 ClientValidationUtils.generateValidatorMessagesOption() + ");");
314 }
315
316 /**
317 * Assigns an id to the component if one was not configured
318 *
319 * @param component - component instance to assign id to
320 */
321 public void assignComponentIds(Component component) {
322 if (component == null) {
323 return;
324 }
325
326 Integer currentSequenceVal = idSequence;
327
328 // assign ID if necessary
329 if (StringUtils.isBlank(component.getId())) {
330 component.setId(UifConstants.COMPONENT_ID_PREFIX + getNextId());
331 }
332
333 // capture current sequence value for component refreshes
334 getViewIndex().addSequenceValueToSnapshot(component.getId(), currentSequenceVal);
335
336 if (component instanceof Container) {
337 LayoutManager layoutManager = ((Container) component).getLayoutManager();
338 if (layoutManager != null) {
339 if (StringUtils.isBlank(layoutManager.getId())) {
340 layoutManager.setId(UifConstants.COMPONENT_ID_PREFIX + getNextId());
341 }
342 }
343 }
344
345 // assign id to nested components
346 List<Component> allNested = new ArrayList<Component>(component.getComponentsForLifecycle());
347 allNested.addAll(component.getComponentPrototypes());
348 for (Component nestedComponent : allNested) {
349 assignComponentIds(nestedComponent);
350 }
351 }
352
353 /**
354 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
355 */
356 @Override
357 public List<Component> getComponentsForLifecycle() {
358 List<Component> components = new ArrayList<Component>();
359
360 components.add(applicationHeader);
361 components.add(applicationFooter);
362 components.add(navigation);
363 components.add(breadcrumbs);
364 components.add(growls);
365 components.addAll(dialogs);
366 components.add(viewMenuLink);
367 components.add(navigationBlockUI);
368 components.add(refreshBlockUI);
369
370 // Note super items should be added after navigation and other view components so
371 // conflicting ids between nav and page do not occur on page navigation via ajax
372 components.addAll(super.getComponentsForLifecycle());
373
374 // remove all pages that are not the current page
375 if (!singlePageView) {
376 for (Group group : this.getItems()) {
377 if ((group instanceof PageGroup) && !StringUtils.equals(group.getId(), getCurrentPageId()) && components
378 .contains(group)) {
379 components.remove(group);
380 }
381 }
382 }
383
384 return components;
385 }
386
387 /**
388 * @see org.kuali.rice.krad.uif.container.Container#getSupportedComponents()
389 */
390 @Override
391 public Set<Class<? extends Component>> getSupportedComponents() {
392 Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
393 supportedComponents.add(Group.class);
394
395 return supportedComponents;
396 }
397
398 /**
399 * @see org.kuali.rice.krad.uif.component.Component#getComponentTypeName()
400 */
401 @Override
402 public String getComponentTypeName() {
403 return "view";
404 }
405
406 /**
407 * Iterates through the contained page items and returns the Page that
408 * matches the set current page id
409 *
410 * @return Page instance
411 */
412 public PageGroup getCurrentPage() {
413 for (Group pageGroup : this.getItems()) {
414 if (StringUtils.equals(pageGroup.getId(), getCurrentPageId()) && pageGroup instanceof PageGroup) {
415 return (PageGroup) pageGroup;
416 }
417 }
418
419 return null;
420 }
421
422 /**
423 * Override sort method to prevent sorting in the case of a single page view, since the items
424 * will get pushed into the configured page and sorted through the page
425 */
426 @Override
427 protected void sortItems(View view, Object model) {
428 if (!singlePageView) {
429 super.sortItems(view, model);
430 }
431 }
432
433 /**
434 * Namespace code the view should be associated with
435 *
436 * <p>
437 * The namespace code is used within the framework in such places as permission checks and parameter
438 * retrieval
439 * </p>
440 *
441 * @return String namespace code
442 */
443 @BeanTagAttribute(name = "namespaceCode")
444 public String getNamespaceCode() {
445 return namespaceCode;
446 }
447
448 /**
449 * Setter for the view's namespace code
450 *
451 * @param namespaceCode
452 */
453 public void setNamespaceCode(String namespaceCode) {
454 this.namespaceCode = namespaceCode;
455 }
456
457 /**
458 * View name provides an identifier for a view within a type. That is if a
459 * set of <code>View</code> instances have the same values for the
460 * properties that are used to retrieve them by their type, the name can be
461 * given to further qualify the view that should be retrieved.
462 * <p>
463 * A view type like the <code>LookupView</code> might have several views for
464 * the same object class, but one that is the 'default' lookup and another
465 * that is the 'advanced' lookup. Therefore the name on the first could be
466 * set to 'default', and likewise the name for the second 'advanced'.
467 * </p>
468 *
469 * @return String name of view
470 */
471 @BeanTagAttribute(name = "viewName")
472 public String getViewName() {
473 return this.viewName;
474 }
475
476 /**
477 * Setter for the view's name
478 *
479 * @param viewName
480 */
481 public void setViewName(String viewName) {
482 this.viewName = viewName;
483 }
484
485 /**
486 * Header for the application containing the view
487 *
488 * <p>
489 * When deploying outside a portal, the application header and footer property can be configured to
490 * display a consistent header/footer across all views. Here application logos, menus, login controls
491 * and so on can be rendered.
492 * </p>
493 *
494 * @return HeaderField application header
495 */
496 @BeanTagAttribute(name = "applicationHeader", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
497 public Header getApplicationHeader() {
498 return applicationHeader;
499 }
500
501 /**
502 * Setter for the application header
503 *
504 * @param applicationHeader
505 */
506 public void setApplicationHeader(Header applicationHeader) {
507 this.applicationHeader = applicationHeader;
508 }
509
510 /**
511 * Footer for the application containing the view
512 *
513 * <p>
514 * When deploying outside a portal, the application header and footer property can be configured to
515 * display a consistent header/footer across all views. Here such things as application links, copyrights
516 * and so on can be rendered.
517 * </p>
518 *
519 * @return Group application footer
520 */
521 @BeanTagAttribute(name = "applicationFooter", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
522 public Group getApplicationFooter() {
523 return applicationFooter;
524 }
525
526 /**
527 * Setter for the application footer
528 *
529 * @param applicationFooter
530 */
531 public void setApplicationFooter(Group applicationFooter) {
532 this.applicationFooter = applicationFooter;
533 }
534
535 /**
536 * Current sequence value for id assignment
537 *
538 * @return int id sequence
539 */
540 public int getIdSequence() {
541 return idSequence;
542 }
543
544 /**
545 * Setter for the current id sequence value
546 *
547 * @param idSequence
548 */
549 public void setIdSequence(int idSequence) {
550 this.idSequence = idSequence;
551 }
552
553 /**
554 * Returns the next unique id available for components within the view instance
555 *
556 * @return String next id available
557 */
558 public String getNextId() {
559 idSequence += 1;
560 return Integer.toString(idSequence);
561 }
562
563 /**
564 * Specifies what page should be rendered by default. This is the page that
565 * will be rendered when the <code>View</code> is first rendered or when the
566 * current page is not set
567 *
568 * @return String id of the page to render by default
569 */
570 @BeanTagAttribute(name = "entryPageId")
571 public String getEntryPageId() {
572 return this.entryPageId;
573 }
574
575 /**
576 * Setter for default Page id
577 *
578 * @param entryPageId
579 */
580 public void setEntryPageId(String entryPageId) {
581 this.entryPageId = entryPageId;
582 }
583
584 /**
585 * The id for the page within the view that should be displayed in the UI.
586 * Other pages of the view will not be rendered
587 *
588 * <p>
589 * If current page id is not set, it is set to the configured entry page or first item in list id
590 * </p>
591 *
592 * @return String id of the page that should be displayed
593 */
594 public String getCurrentPageId() {
595 // default current page if not set
596 if (StringUtils.isBlank(currentPageId)) {
597 if (StringUtils.isNotBlank(entryPageId)) {
598 currentPageId = entryPageId;
599 } else if ((getItems() != null) && !getItems().isEmpty()) {
600 Group firstPageGroup = getItems().get(0);
601 currentPageId = firstPageGroup.getId();
602 }
603 }
604
605 return this.currentPageId;
606 }
607
608 /**
609 * Setter for the page id to display
610 *
611 * @param currentPageId
612 */
613 public void setCurrentPageId(String currentPageId) {
614 this.currentPageId = currentPageId;
615 }
616
617 /**
618 * <code>NavigationGroup</code> instance for the <code>View</code>
619 * <p>
620 * Provides configuration necessary to render the navigation. This includes
621 * navigation items in addition to configuration for the navigation
622 * renderer.
623 * </p>
624 *
625 * @return NavigationGroup
626 */
627 @BeanTagAttribute(name = "navigation", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
628 public Group getNavigation() {
629 return this.navigation;
630 }
631
632 /**
633 * Setter for the View's <code>NavigationGroup</code>
634 *
635 * @param navigation
636 */
637 public void setNavigation(Group navigation) {
638 this.navigation = navigation;
639 }
640
641 /**
642 * Class of the Form that should be used with the <code>View</code>
643 * instance. The form is the top level object for all the view's data and is
644 * used to present and accept data in the user interface. All form classes
645 * should extend UifFormBase
646 *
647 * @return Class<?> class for the view's form
648 * @see org.kuali.rice.krad.web.form.UifFormBase
649 */
650 @BeanTagAttribute(name = "formClass")
651 public Class<?> getFormClass() {
652 return this.formClass;
653 }
654
655 /**
656 * Setter for the form class
657 *
658 * @param formClass
659 */
660 public void setFormClass(Class<?> formClass) {
661 this.formClass = formClass;
662 }
663
664 /**
665 * For <code>View</code> types that work primarily with one nested object of
666 * the form (for instance document, or bo) the default binding object path
667 * can be set for each of the views <code>DataBinding</code> components. If
668 * the component does not set its own binding object path it will inherit
669 * the default
670 *
671 * @return String binding path to the object from the form
672 */
673 @BeanTagAttribute(name = "defaultObjectPath")
674 public String getDefaultBindingObjectPath() {
675 return this.defaultBindingObjectPath;
676 }
677
678 /**
679 * Setter for the default binding object path to use for the view
680 *
681 * @param defaultBindingObjectPath
682 */
683 public void setDefaultBindingObjectPath(String defaultBindingObjectPath) {
684 this.defaultBindingObjectPath = defaultBindingObjectPath;
685 }
686
687 /**
688 * Configures the concrete classes that will be used for properties in the
689 * form object graph that have an abstract or interface type
690 *
691 * <p>
692 * For properties that have an abstract or interface type, it is not
693 * possible to perform operations like getting/settings property values and
694 * getting information from the dictionary. When these properties are
695 * encountered in the object graph, this <code>Map</code> will be consulted
696 * to determine the concrete type to use.
697 * </p>
698 *
699 * <p>
700 * e.g. Suppose we have a property document.accountingLine.accountNumber and
701 * the accountingLine property on the document instance has an interface
702 * type 'AccountingLine'. We can then put an entry into this map with key
703 * 'document.accountingLine', and value
704 * 'org.kuali.rice.sampleapp.TravelAccountingLine'. When getting the
705 * property type or an entry from the dictionary for accountNumber, the
706 * TravelAccountingLine class will be used.
707 * </p>
708 *
709 * @return Map<String, Class> of class implementations keyed by path
710 */
711 @BeanTagAttribute(name = "objectPathConcreteClassMapping", type = BeanTagAttribute.AttributeType.MAPVALUE)
712 public Map<String, Class<?>> getObjectPathToConcreteClassMapping() {
713 return this.objectPathToConcreteClassMapping;
714 }
715
716 /**
717 * Setter for the Map of class implementations keyed by path
718 *
719 * @param objectPathToConcreteClassMapping
720 */
721 public void setObjectPathToConcreteClassMapping(Map<String, Class<?>> objectPathToConcreteClassMapping) {
722 this.objectPathToConcreteClassMapping = objectPathToConcreteClassMapping;
723 }
724
725 /**
726 * Declares additional script files that should be included with the
727 * <code>View</code>. These files are brought into the HTML page along with
728 * common script files configured for the Rice application. Each entry
729 * contain the path to the CSS file, either a relative path, path from web
730 * root, or full URI
731 * <p>
732 * e.g. '/krad/scripts/myScript.js', '../scripts/myScript.js',
733 * 'http://my.edu/web/myScript.js'
734 * </p>
735 *
736 * @return List<String> script file locations
737 */
738 @BeanTagAttribute(name = "additionalScriptFiles", type = BeanTagAttribute.AttributeType.LISTVALUE)
739 public List<String> getAdditionalScriptFiles() {
740 return this.additionalScriptFiles;
741 }
742
743 /**
744 * Setter for the List of additional script files to included with the
745 * <code>View</code>
746 *
747 * @param additionalScriptFiles
748 */
749 public void setAdditionalScriptFiles(List<String> additionalScriptFiles) {
750 this.additionalScriptFiles = additionalScriptFiles;
751 }
752
753 /**
754 * Declares additional CSS files that should be included with the
755 * <code>View</code>. These files are brought into the HTML page along with
756 * common CSS files configured for the Rice application. Each entry should
757 * contain the path to the CSS file, either a relative path, path from web
758 * root, or full URI
759 * <p>
760 * e.g. '/krad/css/stacked-view.css', '../css/stacked-view.css',
761 * 'http://my.edu/web/stacked-view.css'
762 * </p>
763 *
764 * @return List<String> CSS file locations
765 */
766 @BeanTagAttribute(name = "additionalCssFiles", type = BeanTagAttribute.AttributeType.LISTVALUE)
767 public List<String> getAdditionalCssFiles() {
768 return this.additionalCssFiles;
769 }
770
771 /**
772 * Setter for the List of additional CSS files to included with the
773 * <code>View</code>
774 *
775 * @param additionalCssFiles
776 */
777 public void setAdditionalCssFiles(List<String> additionalCssFiles) {
778 this.additionalCssFiles = additionalCssFiles;
779 }
780
781 /**
782 * Specifies the size of the pool that will contain pre-loaded views
783 *
784 * <p>
785 * The spring loading of some views can take a few seconds which hurts performance. The framework supports
786 * pre-loading of view instances so they are available right away when a request is made. This property configures
787 * how many view instances will be pre-loaded. A value of 0 (the default) means no view instances will be
788 * pre-loaded
789 * </p>
790 *
791 * @return int number of view instances to pre-load
792 */
793 @BeanTagAttribute(name = "preloadPoolSize")
794 public int getPreloadPoolSize() {
795 return preloadPoolSize;
796 }
797
798 /**
799 * Setter for the preloaded view pool size
800 *
801 * @param preloadPoolSize
802 */
803 public void setPreloadPoolSize(int preloadPoolSize) {
804 this.preloadPoolSize = preloadPoolSize;
805 }
806
807 /**
808 * List of templates that are used to render the view
809 *
810 * <p>
811 * This list will be populated by unique template names as the components of the view are being processed.
812 * Additional templates can be added in the view configuration if desired. At the beginning of the the view
813 * rendering, each template in the list will then be included or processed by the template language
814 * </p>
815 *
816 * <p>
817 * Note the user of this depends on the template language being used for rendering. Some languages might require
818 * including the template for each component instance (for example JSP templates). While others might simply
819 * include markup that is then available for rendering each component instance (for example FreeMarker which has
820 * a macro for each component that the template defines)
821 * </p>
822 *
823 * @return List<String> list of template names that should be included for rendering the view
824 */
825 public List<String> getViewTemplates() {
826 return viewTemplates;
827 }
828
829 /**
830 * Setter for the the list of template names that should be included to render the view
831 *
832 * @param viewTemplates
833 */
834 public void setViewTemplates(List<String> viewTemplates) {
835 this.viewTemplates = viewTemplates;
836 }
837
838 /**
839 * View type name the view is associated with the view instance
840 *
841 * <p>
842 * Views that share common features and functionality can be grouped by the
843 * view type. Usually view types extend the <code>View</code> class to
844 * provide additional configuration and to set defaults. View types can also
845 * implement the <code>ViewTypeService</code> to add special indexing and
846 * retrieval of views.
847 * </p>
848 *
849 * @return String view type name for the view
850 */
851 @BeanTagAttribute(name = "viewTypeName", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
852 public ViewType getViewTypeName() {
853 return this.viewTypeName;
854 }
855
856 /**
857 * Setter for the view's type name
858 *
859 * @param viewTypeName
860 */
861 public void setViewTypeName(ViewType viewTypeName) {
862 this.viewTypeName = viewTypeName;
863 }
864
865 /**
866 * Class name of the <code>ViewHelperService</code> that handles the various
867 * phases of the Views lifecycle
868 *
869 * @return Class for the spring bean
870 * @see org.kuali.rice.krad.uif.service.ViewHelperService
871 */
872 @BeanTagAttribute(name = "viewHelperServiceClass")
873 public Class<? extends ViewHelperService> getViewHelperServiceClass() {
874 return this.viewHelperServiceClass;
875 }
876
877 /**
878 * Setter for the <code>ViewHelperService</code> class name
879 *
880 * @param viewHelperServiceClass
881 */
882 public void setViewHelperServiceClass(Class<? extends ViewHelperService> viewHelperServiceClass) {
883 this.viewHelperServiceClass = viewHelperServiceClass;
884 }
885
886 /**
887 * Creates the <code>ViewHelperService</code> associated with the View
888 *
889 * @return ViewHelperService instance
890 */
891 @BeanTagAttribute(name = "viewHelperService", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
892 public ViewHelperService getViewHelperService() {
893 if ((this.viewHelperService == null) && (this.viewHelperServiceClass != null)) {
894 viewHelperService = ObjectUtils.newInstance(viewHelperServiceClass);
895 }
896
897 return viewHelperService;
898 }
899
900 /**
901 * Invoked to produce a ViewIndex of the current view's components
902 */
903 public void index() {
904 if (this.viewIndex == null) {
905 this.viewIndex = new ViewIndex();
906 }
907 this.viewIndex.index(this);
908 }
909
910 /**
911 * Holds field indexes of the <code>View</code> instance for retrieval
912 *
913 * @return ViewIndex instance
914 */
915 @BeanTagAttribute(name = "viewIndex", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
916 public ViewIndex getViewIndex() {
917 return this.viewIndex;
918 }
919
920 /**
921 * Map of parameters from the request that set view options, used to rebuild
922 * the view on each post
923 * <p>
924 * Views can be configured by parameters. These might impact which parts of
925 * the view are rendered or how the view behaves. Generally these would get
926 * passed in when a new view is requested (by request parameters). These
927 * will be used to initially populate the view properties. In addition, on a
928 * post the view will be rebuilt and properties reset again by the allow
929 * request parameters.
930 * </p>
931 * <p>
932 * Example parameter would be for MaintenaceView whether a New, Edit, or
933 * Copy was requested (maintenance mode)
934 * </p>
935 *
936 * @return
937 */
938 public Map<String, String> getViewRequestParameters() {
939 return this.viewRequestParameters;
940 }
941
942 /**
943 * Setter for the view's request parameters map
944 *
945 * @param viewRequestParameters
946 */
947 public void setViewRequestParameters(Map<String, String> viewRequestParameters) {
948 this.viewRequestParameters = viewRequestParameters;
949 }
950
951 /**
952 * Indicates whether the form (model) associated with the view should be stored in the user session
953 *
954 * <p>
955 * The form class (or model) is used to hold the data that backs the view along with the built view object. Storing
956 * the form instance in session allows many things:
957 *
958 * <ul>
959 * <li>Data does not need to be rebuilt for each server request (for example a collection)</li>
960 * <li>Data that does not need to go to the user can remain on the form, reducing the size of the response and
961 * improving security</li>
962 * <li>Data can be keep around in a 'pre-save' state. When requested by the user changes can then be persisted to
963 * the database</li>
964 * <li>Certain information about the view that was rendered, such as input fields, collection paths, and refresh
965 * components can be kept on the form to support UI interaction</li>
966 * </ul>
967 *
968 * Setting this flag to false will prevent the form from being kept in session and as a result will limit what can
969 * be done by the framework. In almost all cases this is not recommended.
970 * </p>
971 *
972 * <p>
973 * Note all forms will be cleared when the user session expires (based on the rice configuration). In addition, the
974 * framework enables clear points on certain actions to remove the form when it is no longer needed
975 * </p>
976 *
977 * @return boolean true if the form should be stored in the user session, false if only request based
978 */
979 @BeanTagAttribute(name = "persistFormToSession")
980 public boolean isPersistFormToSession() {
981 return persistFormToSession;
982 }
983
984 /**
985 * Setter for the persist form to session indicator
986 *
987 * @param persistFormToSession
988 */
989 public void setPersistFormToSession(boolean persistFormToSession) {
990 this.persistFormToSession = persistFormToSession;
991 }
992
993 /**
994 * PresentationController that should be used for the <code>View</code> instance
995 *
996 * <p>
997 * The presentation controller is consulted to determine component (group,
998 * field) state such as required, read-only, and hidden. The presentation
999 * controller does not take into account user permissions. The presentation
1000 * controller can also output action flags and edit modes that will be set
1001 * onto the view instance and can be referred to by conditional expressions
1002 * </p>
1003 *
1004 * @return PresentationController
1005 */
1006 @BeanTagAttribute(name = "presentationController", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1007 public ViewPresentationController getPresentationController() {
1008 return this.presentationController;
1009 }
1010
1011 /**
1012 * Setter for the view's presentation controller
1013 *
1014 * @param presentationController
1015 */
1016 public void setPresentationController(ViewPresentationController presentationController) {
1017 this.presentationController = presentationController;
1018 }
1019
1020 /**
1021 * Setter for the view's presentation controller by class
1022 *
1023 * @param presentationControllerClass
1024 */
1025 public void setPresentationControllerClass(
1026 Class<? extends ViewPresentationController> presentationControllerClass) {
1027 this.presentationController = ObjectUtils.newInstance(presentationControllerClass);
1028 }
1029
1030 /**
1031 * Authorizer that should be used for the <code>View</code> instance
1032 *
1033 * <p>
1034 * The authorizer class is consulted to determine component (group, field)
1035 * state such as required, read-only, and hidden based on the users
1036 * permissions. It typically communicates with the Kuali Identity Management
1037 * system to determine roles and permissions. It is used with the
1038 * presentation controller and dictionary conditional logic to determine the
1039 * final component state. The authorizer can also output action flags and
1040 * edit modes that will be set onto the view instance and can be referred to
1041 * by conditional expressions
1042 * </p>
1043 *
1044 * @return Authorizer
1045 */
1046 @BeanTagAttribute(name = "authorizer", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1047 public ViewAuthorizer getAuthorizer() {
1048 return this.authorizer;
1049 }
1050
1051 /**
1052 * Setter for the view's authorizer
1053 *
1054 * @param authorizer
1055 */
1056 public void setAuthorizer(ViewAuthorizer authorizer) {
1057 this.authorizer = authorizer;
1058 }
1059
1060 /**
1061 * Setter for the view's authorizer by class
1062 *
1063 * @param authorizerClass
1064 */
1065 public void setAuthorizerClass(Class<? extends ViewAuthorizer> authorizerClass) {
1066 this.authorizer = ObjectUtils.newInstance(authorizerClass);
1067 }
1068
1069 /**
1070 * Map of strings that flag what actions can be taken in the UI
1071 * <p>
1072 * These can be used in conditional expressions in the dictionary or by
1073 * other UI logic
1074 * </p>
1075 *
1076 * @return BooleanMap action flags
1077 */
1078 @BeanTagAttribute(name = "actionFlags", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1079 public BooleanMap getActionFlags() {
1080 return this.actionFlags;
1081 }
1082
1083 /**
1084 * Setter for the action flags Map
1085 *
1086 * @param actionFlags
1087 */
1088 public void setActionFlags(BooleanMap actionFlags) {
1089 this.actionFlags = actionFlags;
1090 }
1091
1092 /**
1093 * Map of edit modes that enabled for the view
1094 * <p>
1095 * These can be used in conditional expressions in the dictionary or by
1096 * other UI logic
1097 * </p>
1098 *
1099 * @return BooleanMap edit modes
1100 */
1101 @BeanTagAttribute(name = "editModes", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1102 public BooleanMap getEditModes() {
1103 return this.editModes;
1104 }
1105
1106 /**
1107 * Setter for the edit modes Map
1108 *
1109 * @param editModes
1110 */
1111 public void setEditModes(BooleanMap editModes) {
1112 this.editModes = editModes;
1113 }
1114
1115 /**
1116 * Map that contains expressions to evaluate and make available as variables
1117 * for conditional expressions within the view
1118 * <p>
1119 * Each Map entry contains one expression variables, where the map key gives
1120 * the name for the variable, and the map value gives the variable
1121 * expression. The variables expressions will be evaluated before
1122 * conditional logic is run and made available as variables for other
1123 * conditional expressions. Variable expressions can be based on the model
1124 * and any object contained in the view's context
1125 * </p>
1126 *
1127 * @return Map<String, String> variable expressions
1128 */
1129 @BeanTagAttribute(name = "expressionVariables", type = BeanTagAttribute.AttributeType.MAPVALUE)
1130 public Map<String, String> getExpressionVariables() {
1131 return this.expressionVariables;
1132 }
1133
1134 /**
1135 * Setter for the view's map of variable expressions
1136 *
1137 * @param expressionVariables
1138 */
1139 public void setExpressionVariables(Map<String, String> expressionVariables) {
1140 this.expressionVariables = expressionVariables;
1141 }
1142
1143 /**
1144 * Indicates whether the <code>View</code> only has a single page
1145 * <code>Group</code> or contains multiple page <code>Group</code>
1146 * instances. In the case of a single page it is assumed the group's items
1147 * list contains the section groups for the page, and the page itself is
1148 * given by the page property ({@link #getPage()}. This is for convenience
1149 * of configuration and also can drive other configuration like styling.
1150 *
1151 * @return boolean true if the view only contains one page group, false if
1152 * it contains multple pages
1153 */
1154 @BeanTagAttribute(name = "singlePageView")
1155 public boolean isSinglePageView() {
1156 return this.singlePageView;
1157 }
1158
1159 /**
1160 * Setter for the single page indicator
1161 *
1162 * @param singlePageView
1163 */
1164 public void setSinglePageView(boolean singlePageView) {
1165 this.singlePageView = singlePageView;
1166 }
1167
1168 /**
1169 * Indicates whether the default sections specified in the page items list
1170 * should be included for this view. This only applies to single paged views.
1171 *
1172 * @return boolean true if the view should contain the default sections
1173 * specified in the page
1174 */
1175 public boolean isMergeWithPageItems() {
1176 return mergeWithPageItems;
1177 }
1178
1179 /**
1180 * Setter for the include page default sections indicator
1181 *
1182 * @param mergeWithPageItems
1183 */
1184 public void setMergeWithPageItems(boolean mergeWithPageItems) {
1185 this.mergeWithPageItems = mergeWithPageItems;
1186 }
1187
1188 /**
1189 * For single paged views ({@link #isSinglePageView()}, gives the page
1190 * <code>Group</code> the view should render. The actual items for the page
1191 * is taken from the group's items list ({@link #getItems()}, and set onto
1192 * the give page group. This is for convenience of configuration.
1193 *
1194 * @return Group page group for single page views
1195 */
1196 @BeanTagAttribute(name = "page", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1197 public PageGroup getPage() {
1198 return this.page;
1199 }
1200
1201 /**
1202 * Setter for the page group for single page views
1203 *
1204 * @param page
1205 */
1206 public void setPage(PageGroup page) {
1207 this.page = page;
1208 }
1209
1210 /**
1211 * @see org.kuali.rice.krad.uif.container.ContainerBase#getItems()
1212 */
1213 @Override
1214 @BeanTagAttribute(name = "items", type = BeanTagAttribute.AttributeType.LISTBEAN)
1215 public List<? extends Group> getItems() {
1216 return this.items;
1217 }
1218
1219 /**
1220 * Setter for the view's <code>Group</code> instances
1221 *
1222 * @param items
1223 */
1224 @Override
1225 public void setItems(List<? extends Component> items) {
1226 // TODO: fix this generic issue
1227 this.items = (List<? extends Group>) items;
1228 }
1229
1230 /**
1231 * Provide a list of dialog groups associated with this view
1232 *
1233 * @return List of dialog Groups
1234 */
1235 @BeanTagAttribute(name = "dialogs", type = BeanTagAttribute.AttributeType.LISTBEAN)
1236 public List<? extends Group> getDialogs() {
1237 return dialogs;
1238 }
1239
1240 /**
1241 * Sets the list of dialog groups for this view
1242 *
1243 * @param dialogs - List of dialog groups
1244 */
1245 public void setDialogs(List<? extends Group> dialogs) {
1246 this.dialogs = dialogs;
1247 }
1248
1249 /**
1250 * Provides configuration for displaying a link to the view from an
1251 * application menu
1252 *
1253 * @return Link view link field
1254 */
1255 @BeanTagAttribute(name = "viewMenuLink", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1256 public Link getViewMenuLink() {
1257 return this.viewMenuLink;
1258 }
1259
1260 /**
1261 * Setter for the views link field
1262 *
1263 * @param viewMenuLink
1264 */
1265 public void setViewMenuLink(Link viewMenuLink) {
1266 this.viewMenuLink = viewMenuLink;
1267 }
1268
1269 /**
1270 * Provides a grouping string for the view to group its menu link (within a
1271 * portal for instance)
1272 *
1273 * @return String menu grouping
1274 */
1275 @BeanTagAttribute(name = "viewMenuGroupName")
1276 public String getViewMenuGroupName() {
1277 return this.viewMenuGroupName;
1278 }
1279
1280 /**
1281 * Setter for the views menu grouping
1282 *
1283 * @param viewMenuGroupName
1284 */
1285 public void setViewMenuGroupName(String viewMenuGroupName) {
1286 this.viewMenuGroupName = viewMenuGroupName;
1287 }
1288
1289 /**
1290 * Indicates what lifecycle phase the View instance is in
1291 * <p>
1292 * The view lifecycle begins with the CREATED status. In this status a new
1293 * instance of the view has been retrieved from the dictionary, but no
1294 * further processing has been done. After the initialize phase has been run
1295 * the status changes to INITIALIZED. After the model has been applied and
1296 * the view is ready for render the status changes to FINAL
1297 * </p>
1298 *
1299 * @return String view status
1300 * @see org.kuali.rice.krad.uif.UifConstants.ViewStatus
1301 */
1302 public String getViewStatus() {
1303 return this.viewStatus;
1304 }
1305
1306 /**
1307 * Setter for the view status
1308 *
1309 * @param viewStatus
1310 */
1311 public void setViewStatus(String viewStatus) {
1312 this.viewStatus = viewStatus;
1313 }
1314
1315 /**
1316 * Indicates whether the view has been initialized
1317 *
1318 * @return boolean true if the view has been initialized, false if not
1319 */
1320 public boolean isInitialized() {
1321 return StringUtils.equals(viewStatus, ViewStatus.INITIALIZED) || StringUtils.equals(viewStatus,
1322 ViewStatus.FINAL);
1323 }
1324
1325 /**
1326 * Indicates whether the view has been updated from the model and final
1327 * updates made
1328 *
1329 * @return boolean true if the view has been updated, false if not
1330 */
1331 public boolean isFinal() {
1332 return StringUtils.equals(viewStatus, ViewStatus.FINAL);
1333 }
1334
1335 /**
1336 * Breadcrumb widget used for displaying homeward path and history
1337 *
1338 * @return the breadcrumbs
1339 */
1340 @BeanTagAttribute(name = "breadcrumbs", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1341 public BreadCrumbs getBreadcrumbs() {
1342 return this.breadcrumbs;
1343 }
1344
1345 /**
1346 * @param breadcrumbs the breadcrumbs to set
1347 */
1348 public void setBreadcrumbs(BreadCrumbs breadcrumbs) {
1349 this.breadcrumbs = breadcrumbs;
1350 }
1351
1352 /**
1353 * Indicates whether the breadcrumbs should be rendered in the view or if they have been rendered in
1354 * the application header
1355 *
1356 * <p>
1357 * For layout purposes it is sometimes necessary to render the breadcrumbs in the application header. This flag
1358 * indicates that is being done (by setting to false) and therefore should not be rendered in the view template.
1359 * </p>
1360 *
1361 * @return boolean true if breadcrumbs should be rendered in the view, false if not (are rendered in the
1362 * application header)
1363 */
1364 @BeanTagAttribute(name = "renderBreadcrumbsInView")
1365 public boolean isRenderBreadcrumbsInView() {
1366 return renderBreadcrumbsInView;
1367 }
1368
1369 /**
1370 * Setter for the render breadcrumbs in view indicator
1371 *
1372 * @param renderBreadcrumbsInView
1373 */
1374 public void setRenderBreadcrumbsInView(boolean renderBreadcrumbsInView) {
1375 this.renderBreadcrumbsInView = renderBreadcrumbsInView;
1376 }
1377
1378 /**
1379 * Growls widget which sets up global settings for the growls used in this
1380 * view and its pages
1381 *
1382 * @return the growls
1383 */
1384 @BeanTagAttribute(name = "growls", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1385 public Growls getGrowls() {
1386 return this.growls;
1387 }
1388
1389 /**
1390 * @param growls the growls to set
1391 */
1392 public void setGrowls(Growls growls) {
1393 this.growls = growls;
1394 }
1395
1396 /**
1397 * Set the refresh BlockUI used with single element blocking
1398 * (such as ajax based element loading/updates)
1399 *
1400 * @param refreshBlockUI
1401 */
1402 public void setRefreshBlockUI(BlockUI refreshBlockUI) {
1403 this.refreshBlockUI = refreshBlockUI;
1404 }
1405
1406 /**
1407 * @return BlockUI returns the refresh block object
1408 */
1409 @BeanTagAttribute(name = "refreshBlockUI", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1410 public BlockUI getRefreshBlockUI() {
1411 return refreshBlockUI;
1412 }
1413
1414 /**
1415 * Set the navigation BlockUI used with single page blocking
1416 * (such as full page loading/saving)
1417 *
1418 * @param navigationBlockUI
1419 */
1420 public void setNavigationBlockUI(BlockUI navigationBlockUI) {
1421 this.navigationBlockUI = navigationBlockUI;
1422 }
1423
1424 /**
1425 * @return BlockUI returns the navigation block object
1426 */
1427 @BeanTagAttribute(name = "navigationBlockUI", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1428 public BlockUI getNavigationBlockUI() {
1429 return navigationBlockUI;
1430 }
1431
1432 /**
1433 * whether to use growls to show messages - info, warning and error
1434 *
1435 * <p>Growls use the messages contained in the message map. If enabled, info
1436 * messages in their entirety will be displayed in growls, for warning and
1437 * error messages a growl message will notify the user that these messages
1438 * exist on the page.</p>
1439 *
1440 * <p> If this setting is disabled, it is recommended that
1441 * infoMessage display be enabled for the page ValidationMessages bean in order to
1442 * display relevant information to the user. Note: the growl scripts are
1443 * built out in the PageGroup class.</p>
1444 *
1445 * @return the growlMessagingEnabled
1446 */
1447 @BeanTagAttribute(name = "growlMessagingEnabled")
1448 public boolean isGrowlMessagingEnabled() {
1449 return this.growlMessagingEnabled;
1450 }
1451
1452 /**
1453 * enable or disable showing of messages using growls
1454 *
1455 * @param growlMessagingEnabled the growlMessagingEnabled to set
1456 */
1457 public void setGrowlMessagingEnabled(boolean growlMessagingEnabled) {
1458 this.growlMessagingEnabled = growlMessagingEnabled;
1459 }
1460
1461 /**
1462 * Indicates whether the form should be validated for dirtyness
1463 *
1464 * <p>
1465 * For FormView, it's necessary to validate when the user tries to navigate out of the form. If set, all the
1466 * InputFields will be validated on refresh, navigate, cancel or close Action or on form
1467 * unload and if dirty, displays a message and user can decide whether to continue with
1468 * the action or stay on the form. For lookup and inquiry, it's not needed to validate.
1469 * </p>
1470 *
1471 * @return true if dirty validation is set
1472 */
1473 @BeanTagAttribute(name = "applyDirtyCheck")
1474 public boolean isApplyDirtyCheck() {
1475 return this.applyDirtyCheck;
1476 }
1477
1478 /**
1479 * Setter for dirty validation.
1480 */
1481 public void setApplyDirtyCheck(boolean applyDirtyCheck) {
1482 this.applyDirtyCheck = applyDirtyCheck;
1483 }
1484
1485 /**
1486 * Indicates whether the Name of the Code should be displayed when a property is of type <code>KualiCode</code>
1487 *
1488 * @param translateCodesOnReadOnlyDisplay - indicates whether <code>KualiCode</code>'s name should be included
1489 */
1490 public void setTranslateCodesOnReadOnlyDisplay(boolean translateCodesOnReadOnlyDisplay) {
1491 this.translateCodesOnReadOnlyDisplay = translateCodesOnReadOnlyDisplay;
1492 }
1493
1494 /**
1495 * Returns whether the current view supports displaying <code>KualiCode</code>'s name as additional display value
1496 *
1497 * @return true if the current view supports
1498 */
1499 @BeanTagAttribute(name = "translateCodesOnReadOnlyDisplay")
1500 public boolean isTranslateCodesOnReadOnlyDisplay() {
1501 return translateCodesOnReadOnlyDisplay;
1502 }
1503
1504 /**
1505 * The property name to be used to determine what will be used in the
1506 * breadcrumb title of this view
1507 *
1508 * <p>
1509 * The title can be determined from a combination of this and viewLabelFieldbindingInfo: If only
1510 * viewLabelFieldPropertyName is set, the title we be determined against the
1511 * defaultBindingObjectPath. If only viewLabelFieldbindingInfo is set it
1512 * must provide information about what object(bindToForm or explicit) and
1513 * path to use. If both viewLabelFieldbindingInfo and viewLabelFieldPropertyName are set,
1514 * the bindingInfo will be used with a
1515 * the viewLabelFieldPropertyName as its bindingPath. If neither are set,
1516 * the default title attribute from the dataObject's metadata (determined by the
1517 * defaultBindingObjectPath's object) will be used.
1518 * </p>
1519 *
1520 * @return String property name whose value should be displayed in view label
1521 */
1522 @BeanTagAttribute(name = "breadcrumbTitlePropertyName")
1523 public String getBreadcrumbTitlePropertyName() {
1524 return this.breadcrumbTitlePropertyName;
1525 }
1526
1527 /**
1528 * Setter for the view label property name
1529 *
1530 * @param breadcrumbTitlePropertyName the viewLabelFieldPropertyName to set
1531 */
1532 public void setBreadcrumbTitlePropertyName(String breadcrumbTitlePropertyName) {
1533 this.breadcrumbTitlePropertyName = breadcrumbTitlePropertyName;
1534 }
1535
1536 /**
1537 * The option to use when appending the view label on the breadcrumb title.
1538 * Available options: 'dash', 'parenthesis', and 'replace'(don't append -
1539 * simply replace the title). MUST be set for the viewLabelField to be used
1540 * in the breadcrumb, if not set no appendage will be added.
1541 *
1542 * @return the appendOption
1543 */
1544 @BeanTagAttribute(name = "breadcrumbTitleDisplayOption")
1545 public String getBreadcrumbTitleDisplayOption() {
1546 return this.breadcrumbTitleDisplayOption;
1547 }
1548
1549 /**
1550 * Setter for the append option
1551 *
1552 * @param breadcrumbTitleDisplayOption the appendOption to set
1553 */
1554 public void setBreadcrumbTitleDisplayOption(String breadcrumbTitleDisplayOption) {
1555 this.breadcrumbTitleDisplayOption = breadcrumbTitleDisplayOption;
1556 }
1557
1558 /**
1559 * Indicates whether the view allows read only fields to be specified on the request URL which will
1560 * override the view setting
1561 *
1562 * <p>
1563 * If enabled, the readOnlyFields request parameter can be sent to indicate fields that should be set read only
1564 * </p>
1565 *
1566 * @return boolean true if read only request overrides are allowed, false if not
1567 */
1568 @BeanTagAttribute(name = "supportsRequestOverrideOfReadOnlyFields")
1569 public boolean isSupportsRequestOverrideOfReadOnlyFields() {
1570 return supportsRequestOverrideOfReadOnlyFields;
1571 }
1572
1573 /**
1574 * Setter for the the read only field override indicator
1575 *
1576 * @param supportsRequestOverrideOfReadOnlyFields
1577 */
1578 public void setSupportsRequestOverrideOfReadOnlyFields(boolean supportsRequestOverrideOfReadOnlyFields) {
1579 this.supportsRequestOverrideOfReadOnlyFields = supportsRequestOverrideOfReadOnlyFields;
1580 }
1581
1582 /**
1583 * Script that is executed at the beginning of page load (before any other script)
1584 *
1585 * <p>
1586 * Many used to set server variables client side
1587 * </p>
1588 *
1589 * @return String pre load script
1590 */
1591 @BeanTagAttribute(name = "preLoadScript")
1592 public String getPreLoadScript() {
1593 return preLoadScript;
1594 }
1595
1596 /**
1597 * Setter for the pre load script
1598 *
1599 * @param preLoadScript
1600 */
1601 public void setPreLoadScript(String preLoadScript) {
1602 this.preLoadScript = preLoadScript;
1603 }
1604
1605 /**
1606 * The theme which contains stylesheets for this view
1607 *
1608 * @return ViewTheme
1609 */
1610 @BeanTagAttribute(name = "theme", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1611 public ViewTheme getTheme() {
1612 return theme;
1613 }
1614
1615 /**
1616 * Setter for The theme which contains stylesheets for this view
1617 *
1618 * @return
1619 */
1620 public void setTheme(ViewTheme theme) {
1621 this.theme = theme;
1622 }
1623
1624 /**
1625 * The stateObject's binding path, this will be used along with the StateMapping's statePropertyName to
1626 * determine what field in the model state information is stored in for this view. Used during View validation.
1627 *
1628 * @return stateObjectBindingPath path to the object storing state information
1629 */
1630 @BeanTagAttribute(name = "stateObjectBindingPath")
1631 public String getStateObjectBindingPath() {
1632 return stateObjectBindingPath;
1633 }
1634
1635 /**
1636 * The stateObject's binding path, this will be used along with the StateMapping's statePropertyName to
1637 * determine what field in the model state information is stored in for this view. Used during View validation.
1638 *
1639 * @param stateObjectBindingPath
1640 */
1641 public void setStateObjectBindingPath(String stateObjectBindingPath) {
1642 this.stateObjectBindingPath = stateObjectBindingPath;
1643 }
1644
1645 /**
1646 * Gets the stateMapping.
1647 *
1648 * <p>The state mapping object is used to determine the state information for a view,
1649 * it must include an ordered list of states, and where to find the state information for the view.
1650 * A stateMapping must be set for state based validation to occur. When stateMapping information is
1651 * not included, the view's model is considered stateless and all constraints will apply regardless of their
1652 * state information or replacements (ie, they will function as they did in version 2.1).</p>
1653 *
1654 * @return StateMapping information needed for state based validation, if null no state based validation
1655 * functionality
1656 * will exist and configured constraints will apply regardless of state
1657 * @since 2.2
1658 */
1659 @BeanTagAttribute(name = "stateMapping", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1660 public StateMapping getStateMapping() {
1661 return stateMapping;
1662 }
1663
1664 /**
1665 * Set the stateMapping
1666 *
1667 * @param stateMapping
1668 */
1669 public void setStateMapping(StateMapping stateMapping) {
1670 this.stateMapping = stateMapping;
1671 }
1672
1673 /**
1674 * @see org.kuali.rice.krad.uif.component.Component#completeValidation
1675 */
1676 @Override
1677 public void completeValidation(ValidationTrace tracer) {
1678 tracer.addBean(this);
1679
1680 // Check for the presence of a valid item with an not-null EntryPageId
1681 boolean validPageId = false;
1682 if (getEntryPageId() != null) {
1683 for (int i = 0; i < getItems().size(); i++) {
1684 if (getEntryPageId().compareTo(getItems().get(i).getId()) == 0) {
1685 validPageId = true;
1686 }
1687 }
1688 } else {
1689 validPageId = true;
1690 }
1691 if (!validPageId) {
1692 String currentValues[] = {"entryPageId = " + getEntryPageId()};
1693 tracer.createError("Items must contain an item with a matching id to entryPageId", currentValues);
1694 }
1695
1696 // Check to insure the view as not already been set
1697 if (tracer.getValidationStage() == ValidationTrace.START_UP) {
1698 if (getViewStatus().compareTo(UifConstants.ViewStatus.CREATED) != 0) {
1699 String currentValues[] = {"viewStatus = " + getViewStatus()};
1700 tracer.createError("ViewStatus should not be set", currentValues);
1701 }
1702 }
1703
1704 // Check to insure the binding object path is a valid property
1705 boolean validDefaultBindingObjectPath = false;
1706 if (getDefaultBindingObjectPath() == null) {
1707 validDefaultBindingObjectPath = true;
1708 } else if (DataDictionary.isPropertyOf(getFormClass(), getDefaultBindingObjectPath())) {
1709 validDefaultBindingObjectPath = true;
1710 }
1711 if (!validDefaultBindingObjectPath) {
1712 String currentValues[] =
1713 {"formClass = " + getFormClass(), "defaultBindingPath = " + getDefaultBindingObjectPath()};
1714 tracer.createError("DefaultBingdingObjectPath must be a valid property of the formClass", currentValues);
1715 }
1716
1717 // Check to insure the page is set if the view is a single page
1718 if (isSinglePageView()) {
1719 if (getPage() == null) {
1720 String currentValues[] = {"singlePageView = " + isSinglePageView(), "page = " + getPage()};
1721 tracer.createError("Page must be set if singlePageView is true", currentValues);
1722 }
1723 for (int i = 0; i < getItems().size(); i++) {
1724 if (getItems().get(i).getClass() == PageGroup.class) {
1725 String currentValues[] =
1726 {"singlePageView = " + isSinglePageView(), "items(" + i + ") = " + getItems().get(i)
1727 .getClass()};
1728 tracer.createError("Items cannot be pageGroups if singlePageView is true", currentValues);
1729 }
1730 }
1731 }
1732
1733 // Checks to insure the Growls are set if growl messaging is enabled
1734 if (isGrowlMessagingEnabled() == true && getGrowls() == null) {
1735 if (Validator.checkExpressions(this, "growls")) {
1736 String currentValues[] =
1737 {"growlMessagingEnabled = " + isGrowlMessagingEnabled(), "growls = " + getGrowls()};
1738 tracer.createError("Growls cannot be null if Growl Messaging is enabled", currentValues);
1739 }
1740 }
1741
1742 // Checks that there are items present if the view is not a single page
1743 if (!isSinglePageView()) {
1744 if (getItems().size() == 0) {
1745 String currentValues[] =
1746 {"singlePageView = " + isSinglePageView(), "items.size = " + getItems().size()};
1747 tracer.createWarning("Items cannot be empty if singlePageView is false", currentValues);
1748 } else {
1749 for (int i = 0; i < getItems().size(); i++) {
1750 if (getItems().get(i).getClass() != PageGroup.class) {
1751 String currentValues[] =
1752 {"singlePageView = " + isSinglePageView(), "items(" + i + ") = " + getItems().get(i)
1753 .getClass()};
1754 tracer.createError("Items must be pageGroups if singlePageView is false", currentValues);
1755 }
1756 }
1757 }
1758 }
1759 super.completeValidation(tracer.getCopy());
1760 }
1761
1762 }