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 java.util.List;
019import java.util.Map;
020
021import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
022import org.kuali.rice.krad.uif.UifConstants;
023import org.kuali.rice.krad.uif.container.PageGroup;
024import org.kuali.rice.krad.uif.service.ViewHelperService;
025import org.kuali.rice.krad.uif.util.BooleanMap;
026import org.kuali.rice.krad.uif.util.ProcessLogger;
027import org.kuali.rice.krad.uif.view.View;
028import org.kuali.rice.krad.uif.view.ViewModel;
029import org.kuali.rice.krad.web.form.UifFormBase;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033/**
034 * Perform the lifecycle process for the view or a component.
035 *
036 * @author Kuali Rice Team (rice.collab@kuali.org)
037 */
038public class ViewLifecycleBuild implements Runnable {
039    private static final Logger LOG = LoggerFactory.getLogger(ViewLifecycleBuild.class);
040
041    private final Map<String, String> parameters;
042    private final Map<String, List<String>> refreshPathMappings;
043
044    /**
045     * Constructor.
046     *
047     * @param parameters Map of key values pairs that provide configuration for the view, this is generally comes from
048     * the request and can be the request parameter Map itself. Any parameters not valid for the View will be
049     * filtered out
050     * @param refreshPathMappings
051     */
052    public ViewLifecycleBuild(Map<String, String> parameters, Map<String, List<String>> refreshPathMappings) {
053        this.parameters = parameters;
054        this.refreshPathMappings = refreshPathMappings;
055    }
056
057    /**
058     * Runs the three lifecycle phases and performs post finalize processing.
059     */
060    @Override
061    public void run() {
062        View view = ViewLifecycle.getView();
063
064        ProcessLogger.trace("begin-view-lifecycle:" + view.getId());
065
066        populateViewRequestParameters();
067
068        runInitializePhase();
069
070        runApplyModelPhase();
071
072        runFinalizePhase();
073
074        // remove view so default values are only applied once
075        ((ViewModel) ViewLifecycle.getModel()).setApplyDefaultValues(false);
076
077        // build script for generating growl messages
078        String growlScript = ViewLifecycle.getHelper().buildGrowlScript();
079        ((ViewModel) ViewLifecycle.getModel()).setGrowlScript(growlScript);
080
081        // on component refreshes regenerate server message content for page
082        if (ViewLifecycle.isRefreshLifecycle()) {
083            PageGroup page = view.getCurrentPage();
084            page.getValidationMessages().generateMessages(view, ViewLifecycle.getModel(), page);
085        }
086
087        LifecycleRefreshPathBuilder.processLifecycleElements();
088
089        ViewLifecycle.getViewPostMetadata().cleanAfterLifecycle();
090
091        ProcessLogger.trace("finalize:" + view.getId());
092    }
093
094    /**
095     * Invokes the view helper to populate view attributes from request parameters, then makes a back up of the
096     * view request parameters on the form.
097     */
098    protected void populateViewRequestParameters() {
099        View view = ViewLifecycle.getView();
100        ViewHelperService helper = ViewLifecycle.getHelper();
101        UifFormBase model = (UifFormBase) ViewLifecycle.getModel();
102
103        // populate view from request parameters. In case of refresh, the parameters will be stored on the
104        // form from the initial build
105        Map<String, String> parametersToPopulate = parameters;
106        if (ViewLifecycle.isRefreshLifecycle()) {
107            parametersToPopulate = model.getViewRequestParameters();
108        }
109
110        helper.populateViewFromRequestParameters(parametersToPopulate);
111
112        // backup view request parameters on form for refreshes
113        model.setViewRequestParameters(view.getViewRequestParameters());
114    }
115
116    /**
117     * Runs the initialize lifecycle phase.
118     *
119     * <p>First the view helper is invoked to perform any custom processing, then the processor is invoked
120     * to perform any tasks for this phase.</p>
121     */
122    protected void runInitializePhase() {
123        ViewLifecycleProcessor processor = ViewLifecycle.getProcessor();
124
125        List<String> refreshPaths = null;
126        if (refreshPathMappings != null) {
127            refreshPaths = refreshPathMappings.get(UifConstants.ViewPhases.INITIALIZE);
128        }
129
130        ViewLifecyclePhase phase = KRADServiceLocatorWeb.getViewLifecyclePhaseBuilder().buildPhase(
131                ViewLifecycle.getView(), UifConstants.ViewPhases.INITIALIZE, refreshPaths);
132
133        View view = ViewLifecycle.getView();
134        ViewHelperService helper = ViewLifecycle.getHelper();
135        UifFormBase model = (UifFormBase) ViewLifecycle.getModel();
136
137        ViewLifecycle.getExpressionEvaluator().initializeEvaluationContext(model);
138
139        if (LOG.isInfoEnabled()) {
140            LOG.info("performing initialize phase for view: " + view.getId());
141        }
142
143        helper.performCustomViewInitialization(model);
144
145        processor.performPhase(phase);
146
147        ProcessLogger.trace("initialize:" + view.getId());
148    }
149
150    /**
151     * Runs the apply model lifecycle phase.
152     *
153     * <p>Default values are applied and context is setup for expression evaluation. Then the processor is invoked
154     * to perform any tasks for this phase. </p>
155     */
156    protected void runApplyModelPhase() {
157        ViewLifecycleProcessor processor = ViewLifecycle.getProcessor();
158
159        List<String> refreshPaths = null;
160        if (refreshPathMappings != null) {
161            refreshPaths = refreshPathMappings.get(UifConstants.ViewPhases.APPLY_MODEL);
162        }
163
164        ViewLifecyclePhase phase = KRADServiceLocatorWeb.getViewLifecyclePhaseBuilder().buildPhase(
165                ViewLifecycle.getView(), UifConstants.ViewPhases.APPLY_MODEL, refreshPaths);
166
167        View view = ViewLifecycle.getView();
168        ViewHelperService helper = ViewLifecycle.getHelper();
169        UifFormBase model = (UifFormBase) ViewLifecycle.getModel();
170
171        if (LOG.isInfoEnabled()) {
172            LOG.info("performing apply model phase for view: " + view.getId());
173        }
174
175        // apply default values if view in list
176
177        if(model.isApplyDefaultValues()) {
178            helper.applyDefaultValues(view);
179
180            //ensure default values are only set once
181            model.setApplyDefaultValues(false);
182        }
183
184        // get action flag and edit modes from authorizer/presentation controller, or set from the form backup
185        if (model.isEvaluateFlagsAndModes()) {
186            helper.retrieveEditModesAndActionFlags();
187
188            // backup maps
189            model.setActionFlags(view.getActionFlags());
190            model.setEditModes(view.getEditModes());
191
192            model.setEvaluateFlagsAndModes(false);
193        } else {
194            view.setActionFlags(model.getActionFlags());
195            view.setEditModes(model.getEditModes());
196        }
197
198        // set view context for conditional expressions
199        helper.setViewContext();
200
201        processor.performPhase(phase);
202
203        ProcessLogger.trace("apply-model:" + view.getId());
204    }
205
206    /**
207     * Runs the finalize lifecycle phase.
208     *
209     * <p>Processor is invoked to perform any tasks for this phase.</p>
210     */
211    protected void runFinalizePhase() {
212        ViewLifecycleProcessor processor = ViewLifecycle.getProcessor();
213
214        List<String> refreshPaths = null;
215        if (refreshPathMappings != null) {
216            refreshPaths = refreshPathMappings.get(UifConstants.ViewPhases.FINALIZE);
217        }
218
219        ViewLifecyclePhase phase = KRADServiceLocatorWeb.getViewLifecyclePhaseBuilder().buildPhase(
220                ViewLifecycle.getView(), UifConstants.ViewPhases.FINALIZE, refreshPaths);
221
222        View view = ViewLifecycle.getView();
223        if (LOG.isInfoEnabled()) {
224            LOG.info("performing finalize phase for view: " + view.getId());
225        }
226
227        processor.performPhase(phase);
228    }
229
230}