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 static org.kuali.rice.krad.uif.UifConstants.ViewPhases.APPLY_MODEL;
19  import static org.kuali.rice.krad.uif.UifConstants.ViewPhases.FINALIZE;
20  import static org.kuali.rice.krad.uif.UifConstants.ViewPhases.INITIALIZE;
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.finalize.AddFocusAndJumpDataAttributesTask;
26  import org.kuali.rice.krad.uif.lifecycle.finalize.AddViewTemplatesTask;
27  import org.kuali.rice.krad.uif.lifecycle.finalize.ComponentDefaultFinalizeTask;
28  import org.kuali.rice.krad.uif.lifecycle.finalize.FinalizeViewTask;
29  import org.kuali.rice.krad.uif.lifecycle.finalize.HelperCustomFinalizeTask;
30  import org.kuali.rice.krad.uif.lifecycle.finalize.InvokeFinalizerTask;
31  import org.kuali.rice.krad.uif.lifecycle.finalize.RegisterPropertyEditorTask;
32  import org.kuali.rice.krad.uif.lifecycle.finalize.SetReadOnlyOnDataBindingTask;
33  import org.kuali.rice.krad.uif.lifecycle.initialize.AssignIdsTask;
34  import org.kuali.rice.krad.uif.lifecycle.initialize.ComponentDefaultInitializeTask;
35  import org.kuali.rice.krad.uif.lifecycle.initialize.HelperCustomInitializeTask;
36  import org.kuali.rice.krad.uif.lifecycle.initialize.InitializeContainerFromHelperTask;
37  import org.kuali.rice.krad.uif.lifecycle.initialize.InitializeDataFieldFromDictionaryTask;
38  import org.kuali.rice.krad.uif.lifecycle.initialize.PopulateComponentFromExpressionGraphTask;
39  import org.kuali.rice.krad.uif.lifecycle.initialize.PopulatePathTask;
40  import org.kuali.rice.krad.uif.lifecycle.initialize.PopulateReplacersAndModifiersFromExpressionGraphTask;
41  import org.kuali.rice.krad.uif.lifecycle.initialize.PrepareForCacheTask;
42  import org.kuali.rice.krad.uif.lifecycle.initialize.ProcessRemoteFieldsHolderTask;
43  import org.kuali.rice.krad.uif.lifecycle.initialize.SortContainerTask;
44  import org.kuali.rice.krad.uif.lifecycle.model.AfterEvaluateExpressionTask;
45  import org.kuali.rice.krad.uif.lifecycle.model.ApplyAuthAndPresentationLogicTask;
46  import org.kuali.rice.krad.uif.lifecycle.model.ComponentDefaultApplyModelTask;
47  import org.kuali.rice.krad.uif.lifecycle.model.EvaluateExpressionsTask;
48  import org.kuali.rice.krad.uif.lifecycle.model.HelperCustomApplyModelTask;
49  import org.kuali.rice.krad.uif.lifecycle.model.PopulateComponentContextTask;
50  import org.kuali.rice.krad.uif.lifecycle.model.RefreshStateModifyTask;
51  import org.kuali.rice.krad.uif.lifecycle.model.SuffixIdFromContainerTask;
52  import org.kuali.rice.krad.uif.lifecycle.model.SyncClientSideStateTask;
53  import org.kuali.rice.krad.uif.util.CopyUtils;
54  import org.kuali.rice.krad.uif.util.LifecycleElement;
55  import org.kuali.rice.krad.uif.util.RecycleUtils;
56  import org.kuali.rice.krad.uif.view.View;
57  
58  import java.util.ArrayList;
59  import java.util.List;
60  import java.util.Set;
61  
62  /**
63   * Default phase builder implementation.
64   *
65   * @author Kuali Rice Team (rice.collab@kuali.org)
66   */
67  public class ViewLifecyclePhaseBuilderBase implements ViewLifecyclePhaseBuilder {
68  
69      /**
70       * {@inheritDoc}
71       */
72      @Override
73      public ViewLifecyclePhase buildPhase(View view, String viewPhase, List<String> refreshPaths) {
74          return buildPhase(viewPhase, view, null, "", refreshPaths);
75      }
76  
77      /**
78       * {@inheritDoc}
79       */
80      @Override
81      public ViewLifecyclePhase buildPhase(String viewPhase, LifecycleElement element, Component parent,
82              String parentPath, List<String> refreshPaths) {
83          ViewLifecyclePhase phase = getPhaseInstance(viewPhase);
84          phase.prepare(element, parent, parentPath, refreshPaths);
85  
86          return finishBuildPhase(phase);
87      }
88  
89      /**
90       * Determines if the previous phases have been run for the given element and if not backs up
91       * until it finds the first phase we need to run.
92       *
93       * @param phase phase being requested
94       * @return phase that should be run
95       */
96      protected ViewLifecyclePhase finishBuildPhase(ViewLifecyclePhase phase) {
97          String previousViewPhase = getPreviousViewPhase(phase);
98  
99          while (previousViewPhase != null) {
100             ViewLifecyclePhase prevPhase = getPhaseInstance(previousViewPhase);
101             prevPhase.prepare(phase.getElement(), phase.getParent(), phase.getParentPath(), phase.getRefreshPaths());
102 
103             prevPhase.setNextPhase(phase);
104             phase = prevPhase;
105 
106             previousViewPhase = getPreviousViewPhase(phase);
107         }
108 
109         return phase;
110     }
111 
112     /**
113      * Return the previous view phase, for automatic phase spawning.
114      *
115      * @return phase view phase
116      */
117     protected static String getPreviousViewPhase(ViewLifecyclePhase phase) {
118         String viewPhase = phase.getViewPhase();
119         if (FINALIZE.equals(viewPhase) && !phase.getElement().isModelApplied()) {
120             return APPLY_MODEL;
121         }
122 
123         if (APPLY_MODEL.equals(viewPhase) && !phase.getElement().isInitialized()) {
124             return INITIALIZE;
125         }
126 
127         return null;
128     }
129 
130     /**
131      * Build a phase instance for processing the given view phase.
132      *
133      * @param viewPhase name of the view phase to return
134      * @return phase instance
135      */
136     protected ViewLifecyclePhase getPhaseInstance(String viewPhase) {
137         ViewLifecyclePhase phase = RecycleUtils.getRecycledInstance(viewPhase, ViewLifecyclePhase.class);
138 
139         if (phase != null) {
140             return phase;
141         }
142 
143         if (UifConstants.ViewPhases.PRE_PROCESS.equals(viewPhase)) {
144             phase = buildPreProcessPhase();
145         } else if (UifConstants.ViewPhases.INITIALIZE.equals(viewPhase)) {
146             phase = buildInitializePhase();
147         } else if (UifConstants.ViewPhases.APPLY_MODEL.equals(viewPhase)) {
148             phase = buildApplyModelPhase();
149         } else if (UifConstants.ViewPhases.FINALIZE.equals(viewPhase)) {
150             phase = buildFinalizePhase();
151         } else if (UifConstants.ViewPhases.RENDER.equals(viewPhase)) {
152             phase = buildRenderPhase();
153         }
154 
155         if (phase == null) {
156             throw new RuntimeException("Cannnot create phase instance for view phase name: " + viewPhase);
157         }
158 
159         return phase;
160     }
161 
162     /**
163      * Creates an instance of the {@link PreProcessElementPhase} phase with configured tasks.
164      *
165      * @return view lifecycle phase instance
166      */
167     protected ViewLifecyclePhase buildPreProcessPhase() {
168         PreProcessElementPhase phase = new PreProcessElementPhase();
169 
170         List<ViewLifecycleTask<?>> tasks = new ArrayList<ViewLifecycleTask<?>>();
171 
172         tasks.add(new AssignIdsTask());
173         tasks.add(new PopulatePathTask());
174         tasks.add(new SortContainerTask());
175         tasks.add(new PrepareForCacheTask());
176 
177         phase.setTasks(tasks);
178         phase.setSkipLifecycleTasks(new ArrayList<ViewLifecycleTask<?>>());
179 
180         return phase;
181     }
182 
183     /**
184      * Creates an instance of the {@link InitializeComponentPhase} phase with configured tasks.
185      *
186      * @return view lifecycle phase instance
187      */
188     protected ViewLifecyclePhase buildInitializePhase() {
189         InitializeComponentPhase phase = new InitializeComponentPhase();
190 
191         List<ViewLifecycleTask<?>> tasks = new ArrayList<ViewLifecycleTask<?>>();
192 
193         tasks.add(new AssignIdsTask());
194         tasks.add(new PopulatePathTask());
195         tasks.add(new PopulateComponentFromExpressionGraphTask());
196         tasks.add(new ComponentDefaultInitializeTask());
197         tasks.add(new InitializeDataFieldFromDictionaryTask());
198         tasks.add(new PopulateReplacersAndModifiersFromExpressionGraphTask());
199         tasks.add(new InitializeContainerFromHelperTask());
200         tasks.add(new ProcessRemoteFieldsHolderTask());
201         tasks.add(new InitializeDataFieldFromDictionaryTask());
202         tasks.add(new RunComponentModifiersTask());
203         tasks.add(new HelperCustomInitializeTask());
204 
205         phase.setTasks(tasks);
206 
207         List<ViewLifecycleTask<?>> skipLifecycleTasks = new ArrayList<ViewLifecycleTask<?>>();
208 
209         skipLifecycleTasks.add(new AssignIdsTask());
210 
211         phase.setSkipLifecycleTasks(skipLifecycleTasks);
212 
213         return phase;
214     }
215 
216     /**
217      * Creates an instance of the {@link ApplyModelComponentPhase} phase with configured tasks.
218      *
219      * @return view lifecycle phase instance
220      */
221     protected ViewLifecyclePhase buildApplyModelPhase() {
222         ApplyModelComponentPhase phase = new ApplyModelComponentPhase();
223 
224         List<ViewLifecycleTask<?>> tasks = new ArrayList<ViewLifecycleTask<?>>();
225 
226         tasks.add(new SuffixIdFromContainerTask());
227         tasks.add(new PopulateComponentContextTask());
228         tasks.add(new EvaluateExpressionsTask());
229         tasks.add(new AfterEvaluateExpressionTask());
230         tasks.add(new SyncClientSideStateTask());
231         tasks.add(new ApplyAuthAndPresentationLogicTask());
232         tasks.add(new RefreshStateModifyTask());
233         tasks.add(new ComponentDefaultApplyModelTask());
234         tasks.add(new RunComponentModifiersTask());
235         tasks.add(new HelperCustomApplyModelTask());
236         tasks.add(new SetReadOnlyOnDataBindingTask());
237 
238         phase.setTasks(tasks);
239 
240         List<ViewLifecycleTask<?>> skipLifecycleTasks = new ArrayList<ViewLifecycleTask<?>>();
241 
242         skipLifecycleTasks.add(new SuffixIdFromContainerTask());
243 
244         phase.setSkipLifecycleTasks(skipLifecycleTasks);
245 
246         return phase;
247     }
248 
249     /**
250      * Creates an instance of the {@link FinalizeComponentPhase} phase with configured tasks.
251      *
252      * @return view lifecycle phase instance
253      */
254     protected ViewLifecyclePhase buildFinalizePhase() {
255         FinalizeComponentPhase phase = new FinalizeComponentPhase();
256 
257         List<ViewLifecycleTask<?>> tasks = new ArrayList<ViewLifecycleTask<?>>();
258 
259         tasks.add(new InvokeFinalizerTask());
260         tasks.add(new ComponentDefaultFinalizeTask());
261         tasks.add(new AddViewTemplatesTask());
262         tasks.add(new FinalizeViewTask());
263         tasks.add(new RunComponentModifiersTask());
264         tasks.add(new HelperCustomFinalizeTask());
265         tasks.add(new RegisterPropertyEditorTask());
266         tasks.add(new AddFocusAndJumpDataAttributesTask());
267 
268         phase.setTasks(tasks);
269         phase.setSkipLifecycleTasks(new ArrayList<ViewLifecycleTask<?>>());
270 
271         return phase;
272     }
273 
274     /**
275      * Creates an instance of the {@link RenderComponentPhase} phase with configured tasks.
276      *
277      * @return view lifecycle phase instance
278      */
279     protected ViewLifecyclePhase buildRenderPhase() {
280         RenderComponentPhase phase = new RenderComponentPhase();
281 
282         List<ViewLifecycleTask<?>> tasks = new ArrayList<ViewLifecycleTask<?>>();
283 
284         tasks.add(new RenderComponentTask());
285 
286         phase.setTasks(tasks);
287         phase.setSkipLifecycleTasks(new ArrayList<ViewLifecycleTask<?>>());
288 
289         return phase;
290     }
291 }