001/** 002 * Copyright 2005-2015 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 java.util.LinkedHashSet; 019import java.util.Queue; 020import java.util.Set; 021 022import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 023import org.kuali.rice.krad.uif.UifConstants; 024import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle.LifecycleEvent; 025import org.kuali.rice.krad.uif.util.RecycleUtils; 026 027/** 028 * Lifecycle phase processing task for finalizing a component. 029 * 030 * <p> 031 * The finalize phase is the last phase before the view is rendered. Here final preparations can be 032 * made based on the updated view state. 033 * </p> 034 * 035 * <p> 036 * The finalize phase runs after the apply model phase and can be called multiple times for the 037 * view's lifecylce (however typically only once per request) 038 * </p> 039 * 040 * @author Kuali Rice Team (rice.collab@kuali.org) 041 */ 042public class FinalizeComponentPhase extends ViewLifecyclePhaseBase { 043 044 /** 045 * Lifecycle phase to render this component after finalization, if in-lifecycle rendering is 046 * enabled. 047 * 048 * @see ViewLifecycle#isRenderInLifecycle() 049 */ 050 private RenderComponentPhase renderPhase; 051 052 /** 053 * {@inheritDoc} 054 */ 055 @Override 056 public void recycle() { 057 super.recycle(); 058 renderPhase = null; 059 } 060 061 /** 062 * {@inheritDoc} 063 * 064 * @return UifConstants.ViewPhases.FINALIZE 065 */ 066 @Override 067 public String getViewPhase() { 068 return UifConstants.ViewPhases.FINALIZE; 069 } 070 071 /** 072 * {@inheritDoc} 073 * 074 * @return UifConstants.ViewStatus.MODEL_APPLIED 075 */ 076 @Override 077 public String getStartViewStatus() { 078 return UifConstants.ViewStatus.MODEL_APPLIED; 079 } 080 081 /** 082 * {@inheritDoc} 083 * 084 * @return UifConstants.ViewStatus.FINAL 085 */ 086 @Override 087 public String getEndViewStatus() { 088 return UifConstants.ViewStatus.FINAL; 089 } 090 091 /** 092 * {@inheritDoc} 093 * 094 * @return LifecycleEvent.LIFECYCLE_COMPLETE 095 */ 096 @Override 097 public LifecycleEvent getEventToNotify() { 098 return LifecycleEvent.LIFECYCLE_COMPLETE; 099 } 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}