1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.custom.savestate;
20
21 import javax.el.ValueExpression;
22 import javax.faces.component.StateHolder;
23 import javax.faces.component.UIParameter;
24 import javax.faces.context.FacesContext;
25
26 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
27
28 /**
29 * Provides the ability to store a model value inside the view's component tree.
30 * <p>
31 * JSF provides three scopes for managed beans and therefore all the model
32 * objects that the managed beans reference: request, session, application.
33 * However a common requirement is a way for a model object to have a scope
34 * that is tied to the duration of the current view; that is longer than the
35 * request scope but shorter than session scope.
36 * </p>
37 * <p>
38 * This component simply holds a reference to an arbitrary object (specified
39 * by the value property). Because this object is an ordinary component whose
40 * scope is the current view, the reference to the model automatically has that
41 * same scope.
42 * </p>
43 * <p>
44 * When the value is an EL expression, then after the view is restored the
45 * recreated target object is stored at the specified location.
46 * </p>
47 * <p>
48 * The object being saved must either:
49 * </p>
50 * <ul>
51 * <li>implement java.io.Serializable, or</li>
52 * <li>implement javax.faces.component.StateHolder and have a default
53 * constructor.</li>
54 * </ul>
55 * <p>
56 * Note that the saved object can be "chained" from view to view
57 * in order to extend its lifetime from a single view to a sequence
58 * of views if desired. A UISaveState component with an EL expression
59 * such as "#{someBean}" will save the object state after render, and
60 * restore it on postback. If navigation occurs to some other view
61 * and that view has a UISaveState component with the same EL expression
62 * then the object will simply be saved into the new view, thus extending
63 * its lifetime.
64 * </p>
65 *
66 * @JSFJspProperty name = "name" returnType = "java.lang.String" tagExcluded = "true"
67 * @author Manfred Geiler (latest modification by $Author: skitching $)
68 * @version $Revision: 705343 $ $Date: 2008-10-16 15:05:11 -0500 (Thu, 16 Oct 2008) $
69 */
70 @JSFComponent(
71 name = "t:saveState",
72 tagClass = "org.apache.myfaces.custom.savestate.SaveStateTag")
73 public class UISaveState extends UIParameter
74 {
75
76 static public final String COMPONENT_FAMILY =
77 "javax.faces.Parameter";
78 static public final String COMPONENT_TYPE =
79 "org.apache.myfaces.SaveState";
80
81 /**
82 * Construct an instance of the UISaveState.
83 */
84 public UISaveState()
85 {
86 setRendererType(null);
87 }
88
89 public Object saveState(FacesContext context)
90 {
91 Object values[] = new Object[3];
92 values[0] = super.saveState(context);
93 Object objectToSave = getValue();
94 if (objectToSave instanceof StateHolder)
95 {
96 values[1] = Boolean.TRUE;
97 values[2] = saveAttachedState(context, objectToSave);
98 }
99 else
100 {
101 values[1] = Boolean.FALSE;
102 values[2] = objectToSave;
103 }
104 return values;
105 }
106
107 public void restoreState(FacesContext context, Object state)
108 {
109 Object values[] = (Object[])state;
110 super.restoreState(context, values[0]);
111
112 Object savedObject;
113 Boolean storedObjectIsAStateHolder = (Boolean) values[1];
114 if ( Boolean.TRUE.equals( storedObjectIsAStateHolder ) )
115 {
116 savedObject = restoreAttachedState(context,values[2]);
117 }
118 else
119 {
120 savedObject = values[2];
121 }
122 ValueExpression vb = getValueExpression("value");
123 if (vb != null)
124 {
125 vb.setValue(context.getELContext(), savedObject);
126 }
127 }
128
129 @Override
130 public String getFamily()
131 {
132 return COMPONENT_FAMILY;
133 }
134 }