View Javadoc
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.lifecycle;
17  
18  import java.util.List;
19  import java.util.Queue;
20  import java.util.Set;
21  
22  import org.kuali.rice.krad.uif.UifConstants;
23  import org.kuali.rice.krad.uif.component.Component;
24  import org.kuali.rice.krad.uif.freemarker.RenderComponentTask;
25  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle.LifecycleEvent;
26  import org.kuali.rice.krad.uif.util.LifecycleElement;
27  import org.kuali.rice.krad.uif.util.RecycleUtils;
28  
29  /**
30   * Lifecycle phase processing task for rendering a component.
31   *
32   * @author Kuali Rice Team (rice.collab@kuali.org)
33   * @see ViewLifecycle#isRenderInLifecycle()
34   */
35  public class RenderComponentPhase extends ViewLifecyclePhaseBase {
36  
37      private RenderComponentPhase renderParent;
38      private Set<String> pendingChildren;
39  
40      /**
41       * {@inheritDoc}
42       */
43      @Override
44      protected void recycle() {
45          super.recycle();
46          renderParent = null;
47          pendingChildren = null;
48      }
49  
50      /**
51       * Create a new lifecycle phase processing task for finalizing a component.
52       *
53       * @param element the component instance that should be updated
54       * @param model top level object containing the data
55       * @param path Path to the component relative to its parent component
56       * @param refreshPaths list of paths to run lifecycle on when executing a refresh lifecycle
57       * @param renderParent The parent component
58       * @param pendingChildren The number of child rendering phases to expect to be queued for
59       * processing before this phase
60       */
61      protected void prepare(LifecycleElement element, Object model, String path, List<String> refreshPaths,
62              Component parentComponent, RenderComponentPhase renderParent, Set<String> pendingChildren) {
63          super.prepare(element, model, path, refreshPaths, parentComponent, null);
64  
65          this.renderParent = renderParent;
66          this.pendingChildren = pendingChildren;
67      }
68  
69      /**
70       * {@inheritDoc}
71       *
72       * @return UifConstants.ViewPhases.RENDER
73       */
74      @Override
75      public String getViewPhase() {
76          return UifConstants.ViewPhases.RENDER;
77      }
78  
79      /**
80       * {@inheritDoc}
81       *
82       * @return UifConstants.ViewStatus.FINAL
83       */
84      @Override
85      public String getStartViewStatus() {
86          return UifConstants.ViewStatus.FINAL;
87      }
88  
89      /**
90       * {@inheritDoc}
91       *
92       * @return UifConstants.ViewStatus.RENDERED
93       */
94      @Override
95      public String getEndViewStatus() {
96          return UifConstants.ViewStatus.RENDERED;
97      }
98  
99      /**
100      * {@inheritDoc}
101      */
102     @Override
103     public LifecycleEvent getEventToNotify() {
104         return null;
105     }
106 
107     /**
108      * Verify that the all pending children have completed.
109      */
110     @Override
111     protected void verifyCompleted() {
112         if (pendingChildren != null) {
113             ViewLifecycle.reportIllegalState("Render phase is not complete, children are still pending "
114                     + pendingChildren + "\n" + this);
115         }
116     }
117 
118     /**
119      * Perform rendering on the given component.
120      *
121      * {@inheritDoc}
122      */
123     @Override
124     protected void initializePendingTasks(Queue<ViewLifecycleTask<?>> tasks) {
125         if (!(getElement() instanceof Component)) {
126             return;
127         }
128 
129         Component component = (Component) getElement();
130         if (!component.isRender() || component.getTemplate() == null) {
131             return;
132         }
133 
134         tasks.add(LifecycleTaskFactory.getTask(RenderComponentTask.class, this));
135     }
136 
137     /**
138      * {@inheritDoc}
139      */
140     @Override
141     protected void initializeSuccessors(Queue<ViewLifecyclePhase> successors) {
142         if (renderParent == null || renderParent.pendingChildren == null) {
143             trace(renderParent == null ? "no-parent" : "no-children");
144             return;
145         }
146 
147         synchronized (renderParent) {
148             // InitializeSuccessors is invoked right after processing.
149             // Once the last sibling is processed, then queue the parent phase as a successor.
150             if (!renderParent.pendingChildren.remove(getParentPath())) {
151                 ViewLifecycle.reportIllegalState("Render phase isn't a pending child\n"
152                         + this + "\nRender Parent: " + renderParent);
153             }
154 
155             trace("remove-child " + renderParent.getElement().getId() + " " +
156                     renderParent.getViewPath() + " " + getParentPath() + " "
157                     + renderParent.pendingChildren);
158 
159             if (renderParent.pendingChildren.isEmpty()) {
160                 successors.add(renderParent);
161                 renderParent.trace("pend-rend");
162                 
163                 Set<String> toRecycle = renderParent.pendingChildren;
164                 renderParent.pendingChildren = null;
165                 RecycleUtils.recycle(toRecycle);
166             }
167         }
168     }
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
174     protected ViewLifecyclePhase initializeSuccessor(LifecycleElement nestedElement, String nestedPath,
175             Component parent) {
176         return null;
177     }
178 
179 }