View Javadoc
1   /**
2    * Copyright 2005-2016 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.lifecycle;
17  
18  import java.util.LinkedHashSet;
19  import java.util.Queue;
20  import java.util.Set;
21  
22  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
23  import org.kuali.rice.krad.uif.UifConstants;
24  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle.LifecycleEvent;
25  import org.kuali.rice.krad.uif.util.RecycleUtils;
26  
27  /**
28   * Lifecycle phase processing task for finalizing a component.
29   *
30   * <p>
31   * The finalize phase is the last phase before the view is rendered. Here final preparations can be
32   * made based on the updated view state.
33   * </p>
34   *
35   * <p>
36   * The finalize phase runs after the apply model phase and can be called multiple times for the
37   * view's lifecylce (however typically only once per request)
38   * </p>
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  public class FinalizeComponentPhase extends ViewLifecyclePhaseBase {
43  
44      /**
45       * Lifecycle phase to render this component after finalization, if in-lifecycle rendering is
46       * enabled.
47       *
48       * @see ViewLifecycle#isRenderInLifecycle()
49       */
50      private RenderComponentPhase renderPhase;
51  
52      /**
53       * {@inheritDoc}
54       */
55      @Override
56      public void recycle() {
57          super.recycle();
58          renderPhase = null;
59      }
60  
61      /**
62       * {@inheritDoc}
63       *
64       * @return UifConstants.ViewPhases.FINALIZE
65       */
66      @Override
67      public String getViewPhase() {
68          return UifConstants.ViewPhases.FINALIZE;
69      }
70  
71      /**
72       * {@inheritDoc}
73       *
74       * @return UifConstants.ViewStatus.MODEL_APPLIED
75       */
76      @Override
77      public String getStartViewStatus() {
78          return UifConstants.ViewStatus.MODEL_APPLIED;
79      }
80  
81      /**
82       * {@inheritDoc}
83       *
84       * @return UifConstants.ViewStatus.FINAL
85       */
86      @Override
87      public String getEndViewStatus() {
88          return UifConstants.ViewStatus.FINAL;
89      }
90  
91      /**
92       * {@inheritDoc}
93       *
94       * @return LifecycleEvent.LIFECYCLE_COMPLETE
95       */
96      @Override
97      public LifecycleEvent getEventToNotify() {
98          return LifecycleEvent.LIFECYCLE_COMPLETE;
99      }
100 
101     /**
102      * Verify that the render phase has no pending children.
103      */
104     @Override
105     protected void verifyCompleted() {
106         super.verifyCompleted();
107 
108         if (renderPhase != null) {
109             renderPhase.verifyCompleted();
110         }
111     }
112 
113     /**
114      * {@inheritDoc}
115      */
116     @Override
117     protected void initializeSuccessors(Queue<ViewLifecyclePhase> successors) {
118         super.initializeSuccessors(successors);
119 
120         if (ViewLifecycle.isRenderInLifecycle()) {
121             RenderComponentPhase parentRenderPhase = null;
122 
123             ViewLifecyclePhase predecessor = getPredecessor();
124             if (predecessor instanceof FinalizeComponentPhase) {
125                 parentRenderPhase = ((FinalizeComponentPhase) predecessor).renderPhase;
126             }
127 
128             @SuppressWarnings("unchecked") Set<String> pendingChildren = RecycleUtils.getInstance(LinkedHashSet.class);
129             for (ViewLifecyclePhase successor : successors) {
130                 boolean skipSuccessor;
131                 if (successor instanceof ViewLifecyclePhaseBase) {
132                     skipSuccessor = ((ViewLifecyclePhaseBase) successor).shouldSkipLifecycle();
133                 } else {
134                     // TODO: consider moving shouldSkipLifecycle to public interface
135                     skipSuccessor = successor.getElement().skipLifecycle();
136                 }
137 
138                 // Don't queue successors that will be skipped.
139                 // Doing so would cause notification issues for the render phase.
140                 if (skipSuccessor) {
141                     continue;
142                 }
143 
144                 // Queue the successor, with strict validation that it hasn't already been queued
145                 if (!pendingChildren.add(successor.getParentPath())) {
146                     ViewLifecycle.reportIllegalState(
147                             "Successor is already pending " + pendingChildren + "\n" + successor + "\n" + this);
148                 }
149             }
150 
151             renderPhase = (RenderComponentPhase) KRADServiceLocatorWeb.getViewLifecyclePhaseBuilder().buildPhase(
152                     UifConstants.ViewPhases.RENDER, getElement(), getParent(), getParentPath(), getRefreshPaths());
153             renderPhase.prepareRenderPhase(parentRenderPhase, pendingChildren);
154 
155             trace("create-render " + getElement().getId() + " " + pendingChildren);
156         }
157 
158         if (successors.isEmpty() && renderPhase != null) {
159             successors.add(renderPhase);
160         }
161     }
162 
163 }