View Javadoc

1   /**
2    * Copyright 2005-2015 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.uif.UifConstants;
20  import org.kuali.rice.krad.uif.UifConstants.ViewStatus;
21  import org.kuali.rice.krad.uif.UifConstants.ViewType;
22  import org.kuali.rice.krad.uif.container.Container;
23  import org.kuali.rice.krad.uif.container.ContainerBase;
24  import org.kuali.rice.krad.uif.container.Group;
25  import org.kuali.rice.krad.uif.container.NavigationGroup;
26  import org.kuali.rice.krad.uif.container.PageGroup;
27  import org.kuali.rice.krad.uif.component.Component;
28  import org.kuali.rice.krad.uif.component.ReferenceCopy;
29  import org.kuali.rice.krad.uif.component.RequestParameter;
30  import org.kuali.rice.krad.uif.field.HeaderField;
31  import org.kuali.rice.krad.uif.field.LinkField;
32  import org.kuali.rice.krad.uif.layout.LayoutManager;
33  import org.kuali.rice.krad.uif.service.ViewHelperService;
34  import org.kuali.rice.krad.uif.util.BooleanMap;
35  import org.kuali.rice.krad.uif.util.ClientValidationUtils;
36  import org.kuali.rice.krad.uif.widget.BreadCrumbs;
37  import org.kuali.rice.krad.uif.widget.Growls;
38  import org.kuali.rice.krad.util.ObjectUtils;
39  import org.kuali.rice.krad.web.form.UifFormBase;
40  
41  import java.util.ArrayList;
42  import java.util.HashMap;
43  import java.util.HashSet;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.Set;
47  
48  /**
49   * Root of the component tree which encompasses a set of related
50   * <code>GroupContainer</code> instances tied together with a common page layout
51   * and navigation.
52   *
53   * <p>
54   * The <code>View</code> component ties together all the components and
55   * configuration of the User Interface for a piece of functionality. In Rice
56   * applications the view is typically associated with a <code>Document</code>
57   * instance.
58   * </p>
59   *
60   * <p>
61   * The view template lays out the common header, footer, and navigation for the
62   * related pages. In addition the view renders the HTML head element bringing in
63   * common script files and style sheets, along with optionally rendering a form
64   * element for pages that need to post data back to the server.
65   * </p>
66   *
67   * <p>
68   * Configuration of UIF features such as model validation is also done through
69   * the <code>View</code>
70   * </p>
71   *
72   * @author Kuali Rice Team (rice.collab@kuali.org)
73   */
74  public class View extends ContainerBase {
75      private static final long serialVersionUID = -1220009725554576953L;
76  
77      private String viewNamespaceCode;
78      private String viewName;
79      private ViewTheme theme;
80  
81      private int idSequence;
82  
83      // application
84      private HeaderField applicationHeader;
85      private Group applicationFooter;
86  
87      // Breadcrumbs
88      private BreadCrumbs breadcrumbs;
89      private String viewLabelFieldPropertyName;
90      private String appendOption;
91      private boolean breadcrumbsInApplicationHeader;
92  
93      // Growls support
94      private Growls growls;
95      private boolean growlMessagingEnabled;
96  
97      private String entryPageId;
98  
99      @RequestParameter
100     private String currentPageId;
101 
102     private NavigationGroup navigation;
103 
104     private Class<?> formClass;
105     private String defaultBindingObjectPath;
106     private Map<String, Class<?>> abstractTypeClasses;
107 
108     private List<String> additionalScriptFiles;
109     private List<String> additionalCssFiles;
110 
111     private ViewType viewTypeName;
112     private Class<? extends ViewHelperService> viewHelperServiceClassName;
113 
114     private String viewStatus;
115     private ViewIndex viewIndex;
116     private Map<String, String> viewRequestParameters;
117 
118     private ViewPresentationController presentationController;
119     private ViewAuthorizer authorizer;
120 
121     private BooleanMap actionFlags;
122     private BooleanMap editModes;
123 
124     private Map<String, String> expressionVariables;
125 
126     private boolean singlePageView;
127     private PageGroup page;
128 
129     private List<? extends Group> items;
130 
131     private LinkField viewMenuLink;
132     private String viewMenuGrouping;
133 
134     private boolean validateDirty;
135     private boolean translateCodes;
136     private String preLoadScript;
137     private Map<String, Object> clientSideState;
138 
139     private boolean supportsReadOnlyFieldsOverride;
140 
141     @RequestParameter
142     private boolean dialogMode;
143 
144     @ReferenceCopy
145     private ViewHelperService viewHelperService;
146 
147     public View() {
148         dialogMode = false;
149         singlePageView = false;
150         translateCodes = false;
151         viewTypeName = ViewType.DEFAULT;
152         viewStatus = UifConstants.ViewStatus.CREATED;
153         formClass = UifFormBase.class;
154         breadcrumbsInApplicationHeader = false;
155         supportsReadOnlyFieldsOverride = true;
156 
157         idSequence = 0;
158         this.viewIndex = new ViewIndex();
159 
160         additionalScriptFiles = new ArrayList<String>();
161         additionalCssFiles = new ArrayList<String>();
162         items = new ArrayList<Group>();
163         abstractTypeClasses = new HashMap<String, Class<?>>();
164         viewRequestParameters = new HashMap<String, String>();
165         expressionVariables = new HashMap<String, String>();
166         clientSideState = new HashMap<String, Object>();
167     }
168 
169     /**
170      * The following initialization is performed:
171      *
172      * <ul>
173      * <li>If a single paged view, set items in page group and put the page in
174      * the items list</li>
175      * </ul>
176      *
177      * @see org.kuali.rice.krad.uif.container.ContainerBase#performInitialization(View, java.lang.Object)
178      */
179     @SuppressWarnings("unchecked")
180     @Override
181     public void performInitialization(View view, Object model) {
182         super.performInitialization(view, model);
183 
184         // populate items on page for single paged view
185         if (singlePageView) {
186             if (page != null) {
187                 page.setItems(new ArrayList<Group>(items));
188 
189                 // reset the items list to include the one page
190                 items = new ArrayList<Group>();
191                 ((List<Group>) items).add(page);
192             } else {
193                 throw new RuntimeException("For single paged views the page Group must be set.");
194             }
195         }
196 
197         // make sure all the pages have ids before selecting the current page
198         for (Group group : this.getItems()) {
199             if (StringUtils.isBlank(group.getId())) {
200                 group.setId(view.getNextId());
201             }
202         }
203     }
204 
205     /**
206      * The following is performed:
207      *
208      * <ul>
209      * <li>Adds to its document ready script the setupValidator js function for setting
210      * up the validator for this view</li>
211      * </ul>
212      *
213      * @see org.kuali.rice.krad.uif.container.ContainerBase#performFinalize(View,
214      *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
215      */
216     @Override
217     public void performFinalize(View view, Object model, Component parent) {
218         super.performFinalize(view, model, parent);
219 
220         String prefixScript = "";
221         if (this.getOnDocumentReadyScript() != null) {
222             prefixScript = this.getPreLoadScript();
223         }
224 
225         String growlScript = "";
226         Growls gw = view.getGrowls();
227         if (!gw.getComponentOptions().isEmpty()) {
228             growlScript = "setGrowlDefaults(" + gw.getComponentOptionsJSString() + ");";
229         }
230 
231         this.setPreLoadScript(prefixScript + growlScript);
232 
233         prefixScript = "";
234         if (this.getOnDocumentReadyScript() != null) {
235             prefixScript = this.getOnDocumentReadyScript();
236         }
237 
238         this.setOnDocumentReadyScript(prefixScript + "jQuery.extend(jQuery.validator.messages, " +
239                 ClientValidationUtils.generateValidatorMessagesOption() + ");");
240     }
241 
242     /**
243      * Assigns an id to the component if one was not configured
244      *
245      * @param component - component instance to assign id to
246      */
247     public void assignComponentIds(Component component) {
248         if (component == null) {
249             return;
250         }
251         
252         Integer currentSequenceVal = idSequence;
253 
254         // assign ID if necessary
255         if (StringUtils.isBlank(component.getId())) {
256             component.setId(UifConstants.COMPONENT_ID_PREFIX + getNextId());
257         }
258 
259         // capture current sequence value for component refreshes
260         getViewIndex().addSequenceValueToSnapshot(component.getId(), currentSequenceVal);
261 
262         if (component instanceof Container) {
263             LayoutManager layoutManager = ((Container) component).getLayoutManager();
264             if ((layoutManager != null) && StringUtils.isBlank(layoutManager.getId())) {
265                 layoutManager.setId(UifConstants.COMPONENT_ID_PREFIX + getNextId());
266             }
267         }
268 
269         // check if component has already been initialized to prevent cyclic references
270         // TODO: move to VHS initialize
271         //        if (initializedComponentIds.contains(component.getId())) {
272         //            throw new RiceRuntimeException(
273         //                    "Circular reference or duplicate id found for component with id: " + component.getId());
274         //        }
275         //        initializedComponentIds.add(component.getId());
276 
277         // assign id to nested components
278         List<Component> allNested = new ArrayList<Component>(component.getComponentsForLifecycle());
279         allNested.addAll(component.getComponentPrototypes());
280         for (Component nestedComponent : allNested) {
281             assignComponentIds(nestedComponent);
282         }
283     }
284 
285     /**
286      * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
287      */
288     @Override
289     public List<Component> getComponentsForLifecycle() {
290         List<Component> components = super.getComponentsForLifecycle();
291 
292         components.add(applicationHeader);
293         components.add(applicationFooter);
294         components.add(navigation);
295         components.add(breadcrumbs);
296         components.add(growls);
297         components.add(viewMenuLink);
298 
299         // remove all pages that are not the current page
300         if (!singlePageView) {
301             for (Group group : this.getItems()) {
302                 if ((group instanceof PageGroup) && !StringUtils.equals(group.getId(), getCurrentPageId()) && components
303                         .contains(group)) {
304                     components.remove(group);
305                 }
306             }
307         }
308 
309         return components;
310     }
311 
312     /**
313      * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes()
314      */
315     @Override
316     public List<Component> getComponentPrototypes() {
317         List<Component> components = super.getComponentPrototypes();
318 
319         components.add(page);
320 
321         return components;
322     }
323 
324     /**
325      * @see org.kuali.rice.krad.uif.container.Container#getSupportedComponents()
326      */
327     @Override
328     public Set<Class<? extends Component>> getSupportedComponents() {
329         Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
330         supportedComponents.add(Group.class);
331 
332         return supportedComponents;
333     }
334 
335     /**
336      * @see org.kuali.rice.krad.uif.component.Component#getComponentTypeName()
337      */
338     @Override
339     public String getComponentTypeName() {
340         return "view";
341     }
342 
343     /**
344      * Iterates through the contained page items and returns the Page that
345      * matches the set current page id
346      *
347      * @return Page instance
348      */
349     public PageGroup getCurrentPage() {
350         for (Group pageGroup : this.getItems()) {
351             if (StringUtils.equals(pageGroup.getId(), getCurrentPageId()) && pageGroup instanceof PageGroup) {
352                 return (PageGroup) pageGroup;
353             }
354         }
355 
356         return null;
357     }
358 
359     /**
360      * Namespace code the view should be associated with
361      *
362      * <p>
363      * The namespace code is used within the framework in such places as permission checks and parameter
364      * retrieval
365      * </p>
366      *
367      * @return String namespace code
368      */
369     public String getViewNamespaceCode() {
370         return viewNamespaceCode;
371     }
372 
373     /**
374      * Setter for the view's namespace code
375      *
376      * @param viewNamespaceCode
377      */
378     public void setViewNamespaceCode(String viewNamespaceCode) {
379         this.viewNamespaceCode = viewNamespaceCode;
380     }
381 
382     /**
383      * View name provides an identifier for a view within a type. That is if a
384      * set of <code>View</code> instances have the same values for the
385      * properties that are used to retrieve them by their type, the name can be
386      * given to further qualify the view that should be retrieved.
387      * <p>
388      * A view type like the <code>LookupView</code> might have several views for
389      * the same object class, but one that is the 'default' lookup and another
390      * that is the 'advanced' lookup. Therefore the name on the first could be
391      * set to 'default', and likewise the name for the second 'advanced'.
392      * </p>
393      *
394      * @return String name of view
395      */
396     public String getViewName() {
397         return this.viewName;
398     }
399 
400     /**
401      * Setter for the view's name
402      *
403      * @param viewName
404      */
405     public void setViewName(String viewName) {
406         this.viewName = viewName;
407     }
408 
409     /**
410      * Header for the application containing the view
411      *
412      * <p>
413      * When deploying outside a portal, the application header and footer property can be configured to
414      * display a consistent header/footer across all views. Here application logos, menus, login controls
415      * and so on can be rendered.
416      * </p>
417      *
418      * @return HeaderField application header
419      */
420     public HeaderField getApplicationHeader() {
421         return applicationHeader;
422     }
423 
424     /**
425      * Setter for the application header
426      *
427      * @param applicationHeader
428      */
429     public void setApplicationHeader(HeaderField applicationHeader) {
430         this.applicationHeader = applicationHeader;
431     }
432 
433     /**
434      * Footer for the application containing the view
435      *
436      * <p>
437      * When deploying outside a portal, the application header and footer property can be configured to
438      * display a consistent header/footer across all views. Here such things as application links, copyrights
439      * and so on can be rendered.
440      * </p>
441      *
442      * @return Group application footer
443      */
444     public Group getApplicationFooter() {
445         return applicationFooter;
446     }
447 
448     /**
449      * Setter for the application footer
450      *
451      * @param applicationFooter
452      */
453     public void setApplicationFooter(Group applicationFooter) {
454         this.applicationFooter = applicationFooter;
455     }
456 
457     /**
458      * Current sequence value for id assignment
459      *
460      * @return int id sequence
461      */
462     public int getIdSequence() {
463         return idSequence;
464     }
465 
466     /**
467      * Setter for the current id sequence value
468      *
469      * @param idSequence
470      */
471     public void setIdSequence(int idSequence) {
472         this.idSequence = idSequence;
473     }
474 
475     /**
476      * Returns the next unique id available for components within the view instance
477      *
478      * @return String next id available
479      */
480     public String getNextId() {
481         idSequence += 1;
482         return Integer.toString(idSequence);
483     }
484 
485     /**
486      * Specifies what page should be rendered by default. This is the page that
487      * will be rendered when the <code>View</code> is first rendered or when the
488      * current page is not set
489      *
490      * @return String id of the page to render by default
491      */
492     public String getEntryPageId() {
493         return this.entryPageId;
494     }
495 
496     /**
497      * Setter for default Page id
498      *
499      * @param entryPageId
500      */
501     public void setEntryPageId(String entryPageId) {
502         this.entryPageId = entryPageId;
503     }
504 
505     /**
506      * The id for the page within the view that should be displayed in the UI.
507      * Other pages of the view will not be rendered
508      *
509      * <p>
510      * If current page id is not set, it is set to the configured entry page or first item in list id
511      * </p>
512      *
513      * @return String id of the page that should be displayed
514      */
515     public String getCurrentPageId() {
516         // default current page if not set
517         if (StringUtils.isBlank(currentPageId)) {
518             if (StringUtils.isNotBlank(entryPageId)) {
519                 currentPageId = entryPageId;
520             } else if ((getItems() != null) && !getItems().isEmpty()) {
521                 Group firstPageGroup = getItems().get(0);
522                 currentPageId = firstPageGroup.getId();
523             }
524         }
525 
526         return this.currentPageId;
527     }
528 
529     /**
530      * Setter for the page id to display
531      *
532      * @param currentPageId
533      */
534     public void setCurrentPageId(String currentPageId) {
535         this.currentPageId = currentPageId;
536     }
537 
538     /**
539      * <code>NavigationGroup</code> instance for the <code>View</code>
540      * <p>
541      * Provides configuration necessary to render the navigation. This includes
542      * navigation items in addition to configuration for the navigation
543      * renderer.
544      * </p>
545      *
546      * @return NavigationGroup
547      */
548     public NavigationGroup getNavigation() {
549         return this.navigation;
550     }
551 
552     /**
553      * Setter for the View's <code>NavigationGroup</code>
554      *
555      * @param navigation
556      */
557     public void setNavigation(NavigationGroup navigation) {
558         this.navigation = navigation;
559     }
560 
561     /**
562      * Class of the Form that should be used with the <code>View</code>
563      * instance. The form is the top level object for all the view's data and is
564      * used to present and accept data in the user interface. All form classes
565      * should extend UifFormBase
566      *
567      * @return Class<?> class for the view's form
568      * @see org.kuali.rice.krad.web.form.UifFormBase
569      */
570     public Class<?> getFormClass() {
571         return this.formClass;
572     }
573 
574     /**
575      * Setter for the form class
576      *
577      * @param formClass
578      */
579     public void setFormClass(Class<?> formClass) {
580         this.formClass = formClass;
581     }
582 
583     /**
584      * For <code>View</code> types that work primarily with one nested object of
585      * the form (for instance document, or bo) the default binding object path
586      * can be set for each of the views <code>DataBinding</code> components. If
587      * the component does not set its own binding object path it will inherit
588      * the default
589      *
590      * @return String binding path to the object from the form
591      */
592     public String getDefaultBindingObjectPath() {
593         return this.defaultBindingObjectPath;
594     }
595 
596     /**
597      * Setter for the default binding object path to use for the view
598      *
599      * @param defaultBindingObjectPath
600      */
601     public void setDefaultBindingObjectPath(String defaultBindingObjectPath) {
602         this.defaultBindingObjectPath = defaultBindingObjectPath;
603     }
604 
605     /**
606      * Configures the concrete classes that will be used for properties in the
607      * form object graph that have an abstract or interface type
608      *
609      * <p>
610      * For properties that have an abstract or interface type, it is not
611      * possible to perform operations like getting/settings property values and
612      * getting information from the dictionary. When these properties are
613      * encountered in the object graph, this <code>Map</code> will be consulted
614      * to determine the concrete type to use.
615      * </p>
616      *
617      * <p>
618      * e.g. Suppose we have a property document.accountingLine.accountNumber and
619      * the accountingLine property on the document instance has an interface
620      * type 'AccountingLine'. We can then put an entry into this map with key
621      * 'document.accountingLine', and value
622      * 'org.kuali.rice.sampleapp.TravelAccountingLine'. When getting the
623      * property type or an entry from the dictionary for accountNumber, the
624      * TravelAccountingLine class will be used.
625      * </p>
626      *
627      * @return Map<String, Class> of class implementations keyed by path
628      */
629     public Map<String, Class<?>> getAbstractTypeClasses() {
630         return this.abstractTypeClasses;
631     }
632 
633     /**
634      * Setter for the Map of class implementations keyed by path
635      *
636      * @param abstractTypeClasses
637      */
638     public void setAbstractTypeClasses(Map<String, Class<?>> abstractTypeClasses) {
639         this.abstractTypeClasses = abstractTypeClasses;
640     }
641 
642     /**
643      * Declares additional script files that should be included with the
644      * <code>View</code>. These files are brought into the HTML page along with
645      * common script files configured for the Rice application. Each entry
646      * contain the path to the CSS file, either a relative path, path from web
647      * root, or full URI
648      * <p>
649      * e.g. '/krad/scripts/myScript.js', '../scripts/myScript.js',
650      * 'http://my.edu/web/myScript.js'
651      * </p>
652      *
653      * @return List<String> script file locations
654      */
655     public List<String> getAdditionalScriptFiles() {
656         return this.additionalScriptFiles;
657     }
658 
659     /**
660      * Setter for the List of additional script files to included with the
661      * <code>View</code>
662      *
663      * @param additionalScriptFiles
664      */
665     public void setAdditionalScriptFiles(List<String> additionalScriptFiles) {
666         this.additionalScriptFiles = additionalScriptFiles;
667     }
668 
669     /**
670      * Declares additional CSS files that should be included with the
671      * <code>View</code>. These files are brought into the HTML page along with
672      * common CSS files configured for the Rice application. Each entry should
673      * contain the path to the CSS file, either a relative path, path from web
674      * root, or full URI
675      * <p>
676      * e.g. '/krad/css/stacked-view.css', '../css/stacked-view.css',
677      * 'http://my.edu/web/stacked-view.css'
678      * </p>
679      *
680      * @return List<String> CSS file locations
681      */
682     public List<String> getAdditionalCssFiles() {
683         return this.additionalCssFiles;
684     }
685 
686     /**
687      * Setter for the List of additional CSS files to included with the
688      * <code>View</code>
689      *
690      * @param additionalCssFiles
691      */
692     public void setAdditionalCssFiles(List<String> additionalCssFiles) {
693         this.additionalCssFiles = additionalCssFiles;
694     }
695 
696     public boolean isDialogMode() {
697         return this.dialogMode;
698     }
699 
700     public void setDialogMode(boolean dialogMode) {
701         this.dialogMode = dialogMode;
702     }
703 
704     /**
705      * View type name the view is associated with the view instance
706      *
707      * <p>
708      * Views that share common features and functionality can be grouped by the
709      * view type. Usually view types extend the <code>View</code> class to
710      * provide additional configuration and to set defaults. View types can also
711      * implement the <code>ViewTypeService</code> to add special indexing and
712      * retrieval of views.
713      * </p>
714      *
715      * @return String view type name for the view
716      */
717     public ViewType getViewTypeName() {
718         return this.viewTypeName;
719     }
720 
721     /**
722      * Setter for the view's type name
723      *
724      * @param viewTypeName
725      */
726     public void setViewTypeName(ViewType viewTypeName) {
727         this.viewTypeName = viewTypeName;
728     }
729 
730     /**
731      * Class name of the <code>ViewHelperService</code> that handles the various
732      * phases of the Views lifecycle
733      *
734      * @return Class for the spring bean
735      * @see org.kuali.rice.krad.uif.service.ViewHelperService
736      */
737     public Class<? extends ViewHelperService> getViewHelperServiceClassName() {
738         return this.viewHelperServiceClassName;
739     }
740 
741     /**
742      * Setter for the <code>ViewHelperService</code> class name
743      *
744      * @param viewHelperServiceClassName
745      */
746     public void setViewHelperServiceClassName(Class<? extends ViewHelperService> viewHelperServiceClassName) {
747         this.viewHelperServiceClassName = viewHelperServiceClassName;
748     }
749 
750     /**
751      * Creates the <code>ViewHelperService</code> associated with the View
752      *
753      * @return ViewHelperService instance
754      */
755     public ViewHelperService getViewHelperService() {
756         if (this.viewHelperService == null) {
757             viewHelperService = ObjectUtils.newInstance(viewHelperServiceClassName);
758         }
759 
760         return viewHelperService;
761     }
762 
763     /**
764      * Invoked to produce a ViewIndex of the current view's components
765      */
766     public void index() {
767         if (this.viewIndex == null) {
768             this.viewIndex = new ViewIndex();
769         }
770         this.viewIndex.index(this);
771     }
772 
773     /**
774      * Holds field indexes of the <code>View</code> instance for retrieval
775      *
776      * @return ViewIndex instance
777      */
778     public ViewIndex getViewIndex() {
779         return this.viewIndex;
780     }
781 
782     /**
783      * Map of parameters from the request that set view options, used to rebuild
784      * the view on each post
785      * <p>
786      * Views can be configured by parameters. These might impact which parts of
787      * the view are rendered or how the view behaves. Generally these would get
788      * passed in when a new view is requested (by request parameters). These
789      * will be used to initially populate the view properties. In addition, on a
790      * post the view will be rebuilt and properties reset again by the allow
791      * request parameters.
792      * </p>
793      * <p>
794      * Example parameter would be for MaintenaceView whether a New, Edit, or
795      * Copy was requested (maintenance mode)
796      * </p>
797      *
798      * @return
799      */
800     public Map<String, String> getViewRequestParameters() {
801         return this.viewRequestParameters;
802     }
803 
804     /**
805      * Setter for the view's request parameters map
806      *
807      * @param viewRequestParameters
808      */
809     public void setViewRequestParameters(Map<String, String> viewRequestParameters) {
810         this.viewRequestParameters = viewRequestParameters;
811     }
812 
813     /**
814      * PresentationController that should be used for the <code>View</code> instance
815      *
816      * <p>
817      * The presentation controller is consulted to determine component (group,
818      * field) state such as required, read-only, and hidden. The presentation
819      * controller does not take into account user permissions. The presentation
820      * controller can also output action flags and edit modes that will be set
821      * onto the view instance and can be referred to by conditional expressions
822      * </p>
823      *
824      * @return PresentationController
825      */
826     public ViewPresentationController getPresentationController() {
827         return this.presentationController;
828     }
829 
830     /**
831      * Setter for the view's presentation controller
832      *
833      * @param presentationController
834      */
835     public void setPresentationController(ViewPresentationController presentationController) {
836         this.presentationController = presentationController;
837     }
838 
839     /**
840      * Setter for the view's presentation controller by class
841      *
842      * @param presentationControllerClass
843      */
844     public void setPresentationControllerClass(
845             Class<? extends ViewPresentationController> presentationControllerClass) {
846         this.presentationController = ObjectUtils.newInstance(presentationControllerClass);
847     }
848 
849     /**
850      * Authorizer that should be used for the <code>View</code> instance
851      *
852      * <p>
853      * The authorizer class is consulted to determine component (group, field)
854      * state such as required, read-only, and hidden based on the users
855      * permissions. It typically communicates with the Kuali Identity Management
856      * system to determine roles and permissions. It is used with the
857      * presentation controller and dictionary conditional logic to determine the
858      * final component state. The authorizer can also output action flags and
859      * edit modes that will be set onto the view instance and can be referred to
860      * by conditional expressions
861      * </p>
862      *
863      * @return Authorizer
864      */
865     public ViewAuthorizer getAuthorizer() {
866         return this.authorizer;
867     }
868 
869     /**
870      * Setter for the view's authorizer
871      *
872      * @param authorizer
873      */
874     public void setAuthorizer(ViewAuthorizer authorizer) {
875         this.authorizer = authorizer;
876     }
877 
878     /**
879      * Setter for the view's authorizer by class
880      *
881      * @param authorizerClass
882      */
883     public void setAuthorizerClass(Class<? extends ViewAuthorizer> authorizerClass) {
884         this.authorizer = ObjectUtils.newInstance(authorizerClass);
885     }
886 
887     /**
888      * Map of strings that flag what actions can be taken in the UI
889      * <p>
890      * These can be used in conditional expressions in the dictionary or by
891      * other UI logic
892      * </p>
893      *
894      * @return BooleanMap action flags
895      */
896     public BooleanMap getActionFlags() {
897         return this.actionFlags;
898     }
899 
900     /**
901      * Setter for the action flags Map
902      *
903      * @param actionFlags
904      */
905     public void setActionFlags(BooleanMap actionFlags) {
906         this.actionFlags = actionFlags;
907     }
908 
909     /**
910      * Map of edit modes that enabled for the view
911      * <p>
912      * These can be used in conditional expressions in the dictionary or by
913      * other UI logic
914      * </p>
915      *
916      * @return BooleanMap edit modes
917      */
918     public BooleanMap getEditModes() {
919         return this.editModes;
920     }
921 
922     /**
923      * Setter for the edit modes Map
924      *
925      * @param editModes
926      */
927     public void setEditModes(BooleanMap editModes) {
928         this.editModes = editModes;
929     }
930 
931     /**
932      * Map that contains expressions to evaluate and make available as variables
933      * for conditional expressions within the view
934      * <p>
935      * Each Map entry contains one expression variables, where the map key gives
936      * the name for the variable, and the map value gives the variable
937      * expression. The variables expressions will be evaluated before
938      * conditional logic is run and made available as variables for other
939      * conditional expressions. Variable expressions can be based on the model
940      * and any object contained in the view's context
941      * </p>
942      *
943      * @return Map<String, String> variable expressions
944      */
945     public Map<String, String> getExpressionVariables() {
946         return this.expressionVariables;
947     }
948 
949     /**
950      * Setter for the view's map of variable expressions
951      *
952      * @param expressionVariables
953      */
954     public void setExpressionVariables(Map<String, String> expressionVariables) {
955         this.expressionVariables = expressionVariables;
956     }
957 
958     /**
959      * Indicates whether the <code>View</code> only has a single page
960      * <code>Group</code> or contains multiple page <code>Group</code>
961      * instances. In the case of a single page it is assumed the group's items
962      * list contains the section groups for the page, and the page itself is
963      * given by the page property ({@link #getPage()}. This is for convenience
964      * of configuration and also can drive other configuration like styling.
965      *
966      * @return boolean true if the view only contains one page group, false if
967      *         it contains multple pages
968      */
969     public boolean isSinglePageView() {
970         return this.singlePageView;
971     }
972 
973     /**
974      * Setter for the single page indicator
975      *
976      * @param singlePageView
977      */
978     public void setSinglePageView(boolean singlePageView) {
979         this.singlePageView = singlePageView;
980     }
981 
982     /**
983      * For single paged views ({@link #isSinglePageView()}, gives the page
984      * <code>Group</code> the view should render. The actual items for the page
985      * is taken from the group's items list ({@link #getItems()}, and set onto
986      * the give page group. This is for convenience of configuration.
987      *
988      * @return Group page group for single page views
989      */
990     public PageGroup getPage() {
991         return this.page;
992     }
993 
994     /**
995      * Setter for the page group for single page views
996      *
997      * @param page
998      */
999     public void setPage(PageGroup page) {
1000         this.page = page;
1001     }
1002 
1003     /**
1004      * @see org.kuali.rice.krad.uif.container.ContainerBase#getItems()
1005      */
1006     @Override
1007     public List<? extends Group> getItems() {
1008         return this.items;
1009     }
1010 
1011     /**
1012      * Setter for the view's <code>Group</code> instances
1013      *
1014      * @param items
1015      */
1016     @Override
1017     public void setItems(List<? extends Component> items) {
1018         // TODO: fix this generic issue
1019         this.items = (List<? extends Group>) items;
1020     }
1021 
1022     /**
1023      * Provides configuration for displaying a link to the view from an
1024      * application menu
1025      *
1026      * @return LinkField view link field
1027      */
1028     public LinkField getViewMenuLink() {
1029         return this.viewMenuLink;
1030     }
1031 
1032     /**
1033      * Setter for the views link field
1034      *
1035      * @param viewMenuLink
1036      */
1037     public void setViewMenuLink(LinkField viewMenuLink) {
1038         this.viewMenuLink = viewMenuLink;
1039     }
1040 
1041     /**
1042      * Provides a grouping string for the view to group its menu link (within a
1043      * portal for instance)
1044      *
1045      * @return String menu grouping
1046      */
1047     public String getViewMenuGrouping() {
1048         return this.viewMenuGrouping;
1049     }
1050 
1051     /**
1052      * Setter for the views menu grouping
1053      *
1054      * @param viewMenuGrouping
1055      */
1056     public void setViewMenuGrouping(String viewMenuGrouping) {
1057         this.viewMenuGrouping = viewMenuGrouping;
1058     }
1059 
1060     /**
1061      * Indicates what lifecycle phase the View instance is in
1062      * <p>
1063      * The view lifecycle begins with the CREATED status. In this status a new
1064      * instance of the view has been retrieved from the dictionary, but no
1065      * further processing has been done. After the initialize phase has been run
1066      * the status changes to INITIALIZED. After the model has been applied and
1067      * the view is ready for render the status changes to FINAL
1068      * </p>
1069      *
1070      * @return String view status
1071      * @see org.kuali.rice.krad.uif.UifConstants.ViewStatus
1072      */
1073     public String getViewStatus() {
1074         return this.viewStatus;
1075     }
1076 
1077     /**
1078      * Setter for the view status
1079      *
1080      * @param viewStatus
1081      */
1082     public void setViewStatus(String viewStatus) {
1083         this.viewStatus = viewStatus;
1084     }
1085 
1086     /**
1087      * Indicates whether the view has been initialized
1088      *
1089      * @return boolean true if the view has been initialized, false if not
1090      */
1091     public boolean isInitialized() {
1092         return StringUtils.equals(viewStatus, ViewStatus.INITIALIZED) ||
1093                 StringUtils.equals(viewStatus, ViewStatus.FINAL);
1094     }
1095 
1096     /**
1097      * Indicates whether the view has been updated from the model and final
1098      * updates made
1099      *
1100      * @return boolean true if the view has been updated, false if not
1101      */
1102     public boolean isFinal() {
1103         return StringUtils.equals(viewStatus, ViewStatus.FINAL);
1104     }
1105 
1106     /**
1107      * onSubmit script configured on the <code>View</code> gets placed on the
1108      * form element
1109      *
1110      * @see org.kuali.rice.krad.uif.component.ComponentBase#getSupportsOnSubmit()
1111      */
1112     @Override
1113     public boolean getSupportsOnSubmit() {
1114         return true;
1115     }
1116 
1117     /**
1118      * onLoad script configured on the <code>View</code> gets placed in a load
1119      * call
1120      *
1121      * @see org.kuali.rice.krad.uif.component.ComponentBase#getSupportsOnLoad()
1122      */
1123     @Override
1124     public boolean getSupportsOnLoad() {
1125         return true;
1126     }
1127 
1128     /**
1129      * onDocumentReady script configured on the <code>View</code> gets placed in
1130      * a document ready jQuery block
1131      *
1132      * @see org.kuali.rice.krad.uif.component.ComponentBase#getSupportsOnLoad()
1133      */
1134     @Override
1135     public boolean getSupportsOnDocumentReady() {
1136         return true;
1137     }
1138 
1139     /**
1140      * Breadcrumb widget used for displaying homeward path and history
1141      *
1142      * @return the breadcrumbs
1143      */
1144     public BreadCrumbs getBreadcrumbs() {
1145         return this.breadcrumbs;
1146     }
1147 
1148     /**
1149      * @param breadcrumbs the breadcrumbs to set
1150      */
1151     public void setBreadcrumbs(BreadCrumbs breadcrumbs) {
1152         this.breadcrumbs = breadcrumbs;
1153     }
1154 
1155     /**
1156      * Indicates whether the breadcrumbs are rendered in the application header and should not
1157      * be rendered as part of the view template
1158      *
1159      * <p>
1160      * For layout purposes it is sometimes necessary to render the breadcrumbs in the application header. This flag
1161      * indicates that is being done and therefore should not be rendered in the view template.
1162      * </p>
1163      *
1164      * @return boolean true if breadcrumbs are rendered in the application header, false if not and they should be
1165      *         rendered with the view
1166      */
1167     public boolean isBreadcrumbsInApplicationHeader() {
1168         return breadcrumbsInApplicationHeader;
1169     }
1170 
1171     /**
1172      * Setter for the breadcrumbs in application header indicator
1173      *
1174      * @param breadcrumbsInApplicationHeader
1175      */
1176     public void setBreadcrumbsInApplicationHeader(boolean breadcrumbsInApplicationHeader) {
1177         this.breadcrumbsInApplicationHeader = breadcrumbsInApplicationHeader;
1178     }
1179 
1180     /**
1181      * Growls widget which sets up global settings for the growls used in this
1182      * view and its pages
1183      *
1184      * @return the growls
1185      */
1186     public Growls getGrowls() {
1187         return this.growls;
1188     }
1189 
1190     /**
1191      * @param growls the growls to set
1192      */
1193     public void setGrowls(Growls growls) {
1194         this.growls = growls;
1195     }
1196 
1197     /**
1198      * Growls use the messages contained in the message map. If enabled, info
1199      * messages in their entirety will be displayed in growls, for warning and
1200      * error messages a growl message will notify the user that these messages
1201      * exist on the page. If this setting is disabled, it is recommended that
1202      * infoMessage display be enabled for the page ErrorsField bean in order to
1203      * display relevant information to the user. Note: the growl scripts are
1204      * built out in the PageGroup class.
1205      *
1206      * @return the growlMessagingEnabled
1207      */
1208     public boolean isGrowlMessagingEnabled() {
1209         return this.growlMessagingEnabled;
1210     }
1211 
1212     /**
1213      * @param growlMessagingEnabled the growlMessagingEnabled to set
1214      */
1215     public void setGrowlMessagingEnabled(boolean growlMessagingEnabled) {
1216         this.growlMessagingEnabled = growlMessagingEnabled;
1217     }
1218 
1219     /**
1220      * Indicates whether the form should be validated for dirtyness
1221      *
1222      * <p>
1223      * For FormView, it's necessary to validate when the user tries to navigate out of the form. If set, all the
1224      * InputFields will be validated on refresh, navigate, cancel or close Action or on form
1225      * unload and if dirty, displays a message and user can decide whether to continue with
1226      * the action or stay on the form. For lookup and inquiry, it's not needed to validate.
1227      * </p>
1228      *
1229      * @return true if dirty validation is set
1230      */
1231     public boolean isValidateDirty() {
1232         return this.validateDirty;
1233     }
1234 
1235     /**
1236      * Setter for dirty validation.
1237      */
1238     public void setValidateDirty(boolean validateDirty) {
1239         this.validateDirty = validateDirty;
1240     }
1241 
1242     /**
1243      * Indicates whether the Name of the Code should be displayed when a property is of type <code>KualiCode</code>
1244      *
1245      * @param translateCodes - indicates whether <code>KualiCode</code>'s name should be included
1246      */
1247     public void setTranslateCodes(boolean translateCodes) {
1248         this.translateCodes = translateCodes;
1249     }
1250 
1251     /**
1252      * Returns whether the current view supports displaying <code>KualiCode</code>'s name as additional display value
1253      *
1254      * @return true if the current view supports
1255      */
1256     public boolean isTranslateCodes() {
1257         return translateCodes;
1258     }
1259 
1260     /**
1261      * The property name to be used to determine what will be used in the
1262      * breadcrumb title of this view
1263      *
1264      * <p>
1265      * The title can be determined from a combination of this and viewLabelFieldbindingInfo: If only
1266      * viewLabelFieldPropertyName is set, the title we be determined against the
1267      * defaultBindingObjectPath. If only viewLabelFieldbindingInfo is set it
1268      * must provide information about what object(bindToForm or explicit) and
1269      * path to use. If both viewLabelFieldbindingInfo and viewLabelFieldPropertyName are set,
1270      * the bindingInfo will be used with a
1271      * the viewLabelFieldPropertyName as its bindingPath. If neither are set,
1272      * the default title attribute from the dataObject's metadata (determined by the
1273      * defaultBindingObjectPath's object) will be used.
1274      * </p>
1275      *
1276      * @return String property name whose value should be displayed in view label
1277      */
1278     public String getViewLabelFieldPropertyName() {
1279         return this.viewLabelFieldPropertyName;
1280     }
1281 
1282     /**
1283      * Setter for the view label property name
1284      *
1285      * @param viewLabelFieldPropertyName the viewLabelFieldPropertyName to set
1286      */
1287     public void setViewLabelFieldPropertyName(String viewLabelFieldPropertyName) {
1288         this.viewLabelFieldPropertyName = viewLabelFieldPropertyName;
1289     }
1290 
1291     /**
1292      * The option to use when appending the view label on the breadcrumb title.
1293      * Available options: 'dash', 'parenthesis', and 'replace'(don't append -
1294      * simply replace the title). MUST be set for the viewLabelField to be used
1295      * in the breadcrumb, if not set no appendage will be added.
1296      *
1297      * @return the appendOption
1298      */
1299     public String getAppendOption() {
1300         return this.appendOption;
1301     }
1302 
1303     /**
1304      * Setter for the append option
1305      *
1306      * @param appendOption the appendOption to set
1307      */
1308     public void setAppendOption(String appendOption) {
1309         this.appendOption = appendOption;
1310     }
1311 
1312     /**
1313      * Map of key name/value pairs that will be exposed on the client with JavaScript
1314      *
1315      * <p>
1316      * Any state contained in the Map will be in addition to general state added by the
1317      * <code>ViewHelperService</code> and also state generated from the component properties
1318      * annotated with <code>ClientSideState</code>. If this map does contain a key that is
1319      * the same as the generated state, it will override the generated, with the exception
1320      * of keys that refer to component ids and have a nested map as value, which will be merged
1321      * </p>
1322      *
1323      * @return Map<String, Object> contains key name/value pairs to expose on client
1324      */
1325     public Map<String, Object> getClientSideState() {
1326         return clientSideState;
1327     }
1328 
1329     /**
1330      * Setter for the client side state map
1331      *
1332      * @param clientSideState
1333      */
1334     public void setClientSideState(Map<String, Object> clientSideState) {
1335         this.clientSideState = clientSideState;
1336     }
1337 
1338     /**
1339      * Adds a variable name/value pair to the client side state map associated with the given
1340      * component id
1341      *
1342      * @param componentId - id of the component the state is associated with
1343      * @param variableName - name to expose the state as
1344      * @param value - initial value for the variable on the client
1345      */
1346     public void addToClientSideState(String componentId, String variableName, Object value) {
1347         Map<String, Object> componentClientState = new HashMap<String, Object>();
1348 
1349         // find any existing client state for component
1350         if (clientSideState.containsKey(componentId)) {
1351             Object clientState = clientSideState.get(componentId);
1352             if ((clientState != null) && (clientState instanceof Map)) {
1353                 componentClientState = (Map<String, Object>) clientState;
1354             } else {
1355                 throw new IllegalArgumentException("Client side state for component: " + componentId + " is not a Map");
1356             }
1357         }
1358 
1359         // add variables to component state and reinsert into view's client state
1360         componentClientState.put(variableName, value);
1361         clientSideState.put(componentId, componentClientState);
1362     }
1363 
1364     /**
1365      * Indicates whether the view allows read only fields to be specified on the request URL which will
1366      * override the view setting
1367      *
1368      * <p>
1369      * If enabled, the readOnlyFields request parameter can be sent to indicate fields that should be set read only
1370      * </p>
1371      *
1372      * @return boolean true if read only request overrides are allowed, false if not
1373      */
1374     public boolean isSupportsReadOnlyFieldsOverride() {
1375         return supportsReadOnlyFieldsOverride;
1376     }
1377 
1378     /**
1379      * Setter for the the read only field override indicator
1380      *
1381      * @param supportsReadOnlyFieldsOverride
1382      */
1383     public void setSupportsReadOnlyFieldsOverride(boolean supportsReadOnlyFieldsOverride) {
1384         this.supportsReadOnlyFieldsOverride = supportsReadOnlyFieldsOverride;
1385     }
1386 
1387     /**
1388      * Script that is executed at the beginning of page load (before any other script)
1389      *
1390      * <p>
1391      * Many used to set server variables client side
1392      * </p>
1393      *
1394      * @return String pre load script
1395      */
1396     public String getPreLoadScript() {
1397         return preLoadScript;
1398     }
1399 
1400     /**
1401      * Setter for the pre load script
1402      *
1403      * @param preLoadScript
1404      */
1405     public void setPreLoadScript(String preLoadScript) {
1406         this.preLoadScript = preLoadScript;
1407     }
1408 
1409     /**
1410      * The theme which contains stylesheets for this view
1411      * @return
1412      */
1413     public ViewTheme getTheme() {
1414         return theme;
1415     }
1416 
1417     /**
1418      * Setter for The theme which contains stylesheets for this view
1419      * @return
1420      */
1421     public void setTheme(ViewTheme theme) {
1422         this.theme = theme;
1423     }
1424 
1425 }