001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.uif.lifecycle; 017 018import static org.kuali.rice.krad.uif.UifConstants.ViewPhases.APPLY_MODEL; 019import static org.kuali.rice.krad.uif.UifConstants.ViewPhases.FINALIZE; 020import static org.kuali.rice.krad.uif.UifConstants.ViewPhases.INITIALIZE; 021 022import org.kuali.rice.krad.uif.UifConstants; 023import org.kuali.rice.krad.uif.component.Component; 024import org.kuali.rice.krad.uif.freemarker.RenderComponentTask; 025import org.kuali.rice.krad.uif.lifecycle.finalize.AddFocusAndJumpDataAttributesTask; 026import org.kuali.rice.krad.uif.lifecycle.finalize.AddViewTemplatesTask; 027import org.kuali.rice.krad.uif.lifecycle.finalize.ComponentDefaultFinalizeTask; 028import org.kuali.rice.krad.uif.lifecycle.finalize.FinalizeViewTask; 029import org.kuali.rice.krad.uif.lifecycle.finalize.HelperCustomFinalizeTask; 030import org.kuali.rice.krad.uif.lifecycle.finalize.InvokeFinalizerTask; 031import org.kuali.rice.krad.uif.lifecycle.finalize.RegisterPropertyEditorTask; 032import org.kuali.rice.krad.uif.lifecycle.finalize.SetReadOnlyOnDataBindingTask; 033import org.kuali.rice.krad.uif.lifecycle.initialize.AssignIdsTask; 034import org.kuali.rice.krad.uif.lifecycle.initialize.ComponentDefaultInitializeTask; 035import org.kuali.rice.krad.uif.lifecycle.initialize.HelperCustomInitializeTask; 036import org.kuali.rice.krad.uif.lifecycle.initialize.InitializeContainerFromHelperTask; 037import org.kuali.rice.krad.uif.lifecycle.initialize.InitializeDataFieldFromDictionaryTask; 038import org.kuali.rice.krad.uif.lifecycle.initialize.PopulateComponentFromExpressionGraphTask; 039import org.kuali.rice.krad.uif.lifecycle.initialize.PopulatePathTask; 040import org.kuali.rice.krad.uif.lifecycle.initialize.PopulateReplacersAndModifiersFromExpressionGraphTask; 041import org.kuali.rice.krad.uif.lifecycle.initialize.PrepareForCacheTask; 042import org.kuali.rice.krad.uif.lifecycle.initialize.ProcessRemoteFieldsHolderTask; 043import org.kuali.rice.krad.uif.lifecycle.initialize.SortContainerTask; 044import org.kuali.rice.krad.uif.lifecycle.model.AfterEvaluateExpressionTask; 045import org.kuali.rice.krad.uif.lifecycle.model.ApplyAuthAndPresentationLogicTask; 046import org.kuali.rice.krad.uif.lifecycle.model.ComponentDefaultApplyModelTask; 047import org.kuali.rice.krad.uif.lifecycle.model.EvaluateExpressionsTask; 048import org.kuali.rice.krad.uif.lifecycle.model.HelperCustomApplyModelTask; 049import org.kuali.rice.krad.uif.lifecycle.model.PopulateComponentContextTask; 050import org.kuali.rice.krad.uif.lifecycle.model.RefreshStateModifyTask; 051import org.kuali.rice.krad.uif.lifecycle.model.SuffixIdFromContainerTask; 052import org.kuali.rice.krad.uif.lifecycle.model.SyncClientSideStateTask; 053import org.kuali.rice.krad.uif.util.CopyUtils; 054import org.kuali.rice.krad.uif.util.LifecycleElement; 055import org.kuali.rice.krad.uif.util.RecycleUtils; 056import org.kuali.rice.krad.uif.view.View; 057 058import java.util.ArrayList; 059import java.util.List; 060import java.util.Set; 061 062/** 063 * Default phase builder implementation. 064 * 065 * @author Kuali Rice Team (rice.collab@kuali.org) 066 */ 067public class ViewLifecyclePhaseBuilderBase implements ViewLifecyclePhaseBuilder { 068 069 /** 070 * {@inheritDoc} 071 */ 072 @Override 073 public ViewLifecyclePhase buildPhase(View view, String viewPhase, List<String> refreshPaths) { 074 return buildPhase(viewPhase, view, null, "", refreshPaths); 075 } 076 077 /** 078 * {@inheritDoc} 079 */ 080 @Override 081 public ViewLifecyclePhase buildPhase(String viewPhase, LifecycleElement element, Component parent, 082 String parentPath, List<String> refreshPaths) { 083 ViewLifecyclePhase phase = getPhaseInstance(viewPhase); 084 phase.prepare(element, parent, parentPath, refreshPaths); 085 086 return finishBuildPhase(phase); 087 } 088 089 /** 090 * Determines if the previous phases have been run for the given element and if not backs up 091 * until it finds the first phase we need to run. 092 * 093 * @param phase phase being requested 094 * @return phase that should be run 095 */ 096 protected ViewLifecyclePhase finishBuildPhase(ViewLifecyclePhase phase) { 097 String previousViewPhase = getPreviousViewPhase(phase); 098 099 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}