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.util;
017
018import java.io.Serializable;
019import java.util.Map;
020import java.util.Queue;
021
022import org.kuali.rice.krad.datadictionary.Copyable;
023import org.kuali.rice.krad.uif.component.Component;
024import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
025import org.kuali.rice.krad.uif.lifecycle.ViewLifecyclePhase;
026import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleTask;
027
028/**
029 * Interface to be implemented by objects that participates in the view lifecycle.
030 *
031 * @author Kuali Rice Team (rice.collab@kuali.org)
032 */
033public interface LifecycleElement extends Serializable, Copyable {
034
035    /**
036     * The unique id (within a given tree) for the element.
037     *
038     * <p>The id is used to identify an element instance within the tree, and
039     * will be used by renderers to set the HTML element id. This gives a way to find various elements
040     * for scripting. If the id is not given, a default will be generated by the framework.
041     * </p>
042     *
043     * @return A unique ID for this lifecycle element.
044     */
045    String getId();
046
047    /**
048     * Setter for the unique id (within a given tree) for the component
049     *
050     * @param id - string to set as the component id
051     */
052    void setId(String id);
053
054    /**
055     * A string suffix that should get applied to the id for all child components of the given element.
056     *
057     * <p>This is mainly used within the framework to keep ids unique. For instance, for components generated
058     * for collection lines, all the components within those should get a line suffix. The framework will set
059     * this property to be '_line0', '_line1', etc. Then when the apply model phase is run on the child components
060     * their ids will be updated with this suffix.</p>
061     *
062     * @return String id suffix for child components
063     * @see org.kuali.rice.krad.uif.lifecycle.model.SuffixIdFromContainerTask
064     */
065    String getContainerIdSuffix();
066
067    /**
068     * @see LifecycleElement#getContainerIdSuffix()
069     */
070    void setContainerIdSuffix(String containerIdSuffix);
071
072    /**
073     * Gets a property for referring to this component from the view, relative to the view, as
074     * assigned by the current or most recent lifecycle.
075     * 
076     * @return property path
077     */
078    String getViewPath();
079
080    /**
081     * Setter for {@link #getViewPath()}.
082     * 
083     * @param viewPath The property path.
084     */
085    void setViewPath(String viewPath);
086
087    /**
088     * Map of paths for this component that will be used to process a refresh (if necessary).
089     *
090     * @return map of refresh paths, key represents the lifecycle phase and the value is the path for
091     * the component at that phase
092     */
093    Map<String, String> getPhasePathMapping();
094
095    /**
096     * @see LifecycleElement#getPhasePathMapping()
097     */
098    void setPhasePathMapping(Map<String, String> phasePathMapping);
099    
100    /**
101     * Determine if this lifecycle element is mutable.
102     * 
103     * <p>
104     * Most lifecycle element are immutable, and all are immutable expect during initialization and
105     * the during the view lifecycle. Those that have been copied within the view lifecycle,
106     * however, may be modified during the same lifecycle.
107     * </p>
108     * @param legalBeforeConfiguration true if the current operation may be called before the
109     *        lifecycle element has been cached, for example while being initialized as part of a
110     *        Spring context.
111     * 
112     * @return True if the component is mutable.
113     */
114    boolean isMutable(boolean legalBeforeConfiguration);
115
116    /**
117     * Check for mutability on the element before modifying state.
118     *
119     * @param legalDuringInitialization True if the operation is legal during view initialization,
120     *        false if the operation is only allowed during the component lifecycle.
121     * @throws IllegalStateException If the component is not mutable and the lifecycle is operating
122     *         in strict mode.
123     * @see ViewLifecycle#isStrict()
124     */
125    void checkMutable(boolean legalDuringInitialization);
126
127    /**
128     * Get the view lifecycle processing status for this component.
129     * 
130     * @return The view lifecycle processing status for this component.
131     * @see org.kuali.rice.krad.uif.UifConstants.ViewStatus
132     */
133    String getViewStatus();
134
135    /**
136     * Sets the view status.
137     * 
138     * @param viewStatus view status
139     * @see #getViewStatus()
140     */
141    void setViewStatus(String viewStatus);
142
143    /**
144     * Indicates whether the component should be rendered in the UI
145     *
146     * <p>
147     * If set to false, the corresponding component template will not be invoked
148     * (therefore nothing will be rendered to the UI).
149     * </p>
150     *
151     * @return boolean true if the component should be rendered, false if it
152     *         should not be
153     */
154    boolean isRender();
155
156    /**
157     * Setter for the components render indicator
158     *
159     * @param render
160     */
161    void setRender(boolean render);
162
163    /**
164     * Indicates whether the component has been initialized.
165     *
166     * @return True if the component has been initialized, false if not.
167     */
168    boolean isInitialized();
169
170    /**
171     * Indicates whether the component has been updated from the model.
172     *
173     * @return True if the component has been updated, false if not.
174     */
175    boolean isModelApplied();
176
177    /**
178     * Indicates whether the component has been updated from the model and final
179     * updates made.
180     *
181     * @return True if the component has been updated, false if not.
182     */
183    boolean isFinal();
184
185    /**
186     * Receive notification that a lifecycle phase, and all successor phases, have been completed on
187     * this component.
188     * @param phase The completed view lifecycle phase
189     */
190    void notifyCompleted(ViewLifecyclePhase phase);
191
192    /**
193     * Context map for the lifecycle element.
194     *
195     * <p>Any el statements configured for the components properties (e.g. title="@{foo.property}") are evaluated
196     * using the el context map. This map will get populated with default objects like the model, view, and request
197     * from the {@code ViewHelperService}. Other components can push further objects into the context so that
198     * they are available for use with that component. For example, field instances that are part of a collection
199     * line as receive the current line instance</p>
200     *
201     * <p>Context map also provides objects to methods that are invoked for {@code GeneratedField} instances</p>
202     *
203     * <p>The Map key gives the name of the variable that can be used within expressions, and the Map value gives
204     * the object instance for which expressions containing the variable should evaluate against</p>
205     *
206     * <p>NOTE: Calling getContext().putAll() will skip updating any configured property replacers for the
207     * component. Instead you should call #pushAllToContextDeep</p>
208     *
209     * @return Map<String, Object> context
210     */
211    Map<String, Object> getContext();
212
213    /**
214     * @see LifecycleElement#getContext()
215     */
216    void setContext(Map<String, Object> context);
217
218    /**
219     * Places the given object into the context Map for the component with the given name
220     * 
221     * <p>
222     * Note this also will push context to property replacers configured on the component. To place
223     * multiple objects in the context, you should use #pushAllToContextDeep since that will call this
224     * method for each and update property replacers. Using {@link Component#getContext()}{@link
225     * Map#putAll(Map) .putAll()} will bypass property replacers.
226     * </p>
227     * 
228     * @param objectName - name the object should be exposed under in the context map
229     * @param object - object instance to place into context
230     */
231    void pushObjectToContext(String objectName, Object object);
232
233    /**
234     * Places each entry of the given Map into the context for the component
235     *
236     * <p>
237     * Note this will call #pushObjectToContextDeep for each entry which will update any configured property
238     * replacers as well. This should be used in place of getContext().putAll()
239     * </p>
240     *
241     * @param objects - Map<String, Object> objects to add to context, where the entry key will be the context key
242     * and the entry value will be the context value
243     */
244    void pushAllToContext(Map<String, Object> objects);
245
246    /**
247     * Initializes the component
248     *
249     * <p>
250     * Where components can set defaults and setup other necessary state. The initialize method
251     * should only be called once per component lifecycle and is invoked within the initialize phase
252     * of the view lifecylce.
253     * </p>
254     *
255     * @param model - object instance containing the view data
256     * @see org.kuali.rice.krad.uif.lifecycle.initialize.ComponentDefaultInitializeTask
257     * @deprecated Special processing within this method should be replaced by
258     *             {@link ViewLifecycleTask} and initialized by
259     *             {@link #initializePendingTasks(ViewLifecyclePhase, Queue)}.
260     */
261    @Deprecated
262    void performInitialization(Object model);
263
264    /**
265     * Called after the initialize phase to perform conditional logic based on the model data
266     *
267     * <p>
268     * Where components can perform conditional logic such as dynamically generating new fields or setting field state
269     * based on the given data
270     * </p>
271     *
272     * @param model - Top level object containing the data (could be the form or a
273     * top level business object, dto)
274     * @param parent parent lifecycle element
275     * @deprecated Special processing within this method should be replaced by
276     *             {@link ViewLifecycleTask} and initialized by
277     *             {@link #initializePendingTasks(ViewLifecyclePhase, Queue)}.
278     */
279    @Deprecated
280    void performApplyModel(Object model, LifecycleElement parent);
281
282    /**
283     * The last phase before the view is rendered
284     *
285     * <p>
286     * Here final preparations can be made based on the updated view state.
287     * </p>
288     *
289     * @param model - top level object containing the data
290     * @param parent - parent component
291     * @deprecated Special processing within this method should be replaced by
292     *             {@link ViewLifecycleTask} and initialized by
293     *             {@link #initializePendingTasks(ViewLifecyclePhase, Queue)}.
294     */
295    @Deprecated
296    void performFinalize(Object model, LifecycleElement parent);
297
298    /**
299     * Return true if the lifecycle should be skipped for this component.
300     *
301     * <p>Skipping the lifecycle means do not invoke the performInitialize, performApplyModel, and
302     * performFinalize methods of this component and its children.  This means that content built
303     * by those lifecycle tasks will not be processed or applied.
304     * Skipping the lifecycle on a component helps initial load/setup performance by only performing
305     * the full lifecycle when the component is requested on subsequent requests (ajax retrievals).</p>
306     *
307     * @return true if lifecycle should be skipped for this component
308     */
309    boolean skipLifecycle();
310
311}