Source code: org/infohazard/maverick/view/DocumentViewFactory.java
1 /*
2 * $Id: DocumentViewFactory.java,v 1.7 2003/10/22 11:13:49 thusted Exp $
3 * $Source: /cvsroot/mav/maverick/src/java/org/infohazard/maverick/view/DocumentViewFactory.java,v $
4 */
5
6 package org.infohazard.maverick.view;
7
8 import javax.servlet.ServletConfig;
9
10 import org.infohazard.maverick.flow.ConfigException;
11 import org.infohazard.maverick.flow.View;
12 import org.infohazard.maverick.flow.ViewContext;
13 import org.infohazard.maverick.flow.ViewFactory;
14 import org.infohazard.maverick.util.XML;
15 import org.jdom.Element;
16
17 /**
18 * <p>
19 * Factory for building JSP, Velocity, and other resource-based views which
20 * place the model bean in one of the servlet attribute collections and
21 * use the RequestDispatcher to forward to the actual content.
22 * This is also used for static documents.
23 * </p>
24 * <p>
25 * This factory has certain options which can be defined when
26 * declaring the factory. The defaults are shown here:
27 * </p>
28 * <pre>
29 * <view-factory type="document" provider="org.infohazard.maverick.view.DocumentViewFactory">
30 * <default-bean-name value="model"/>
31 * </view-factory>
32 * </pre>
33 * <ul>
34 * <li>
35 * <b>default-bean-name</b> - If no "bean" attribute is specified
36 * for individual views, this is the key which will be
37 * used for placing the model in an attribute collection.
38 * </li>
39 * </ul>
40 * <p>
41 * The options for an individual view are like this:
42 * </p>
43 * <pre>
44 * <view type="document" path="blah.jsp" scope="request" bean="model"/>
45 * </pre>
46 * <p>
47 * Scope can be one of <code>request</code>, <code>session</code>,
48 * <code>application</code>. The default is <code>request</code>.
49 * </p>
50 * <p>
51 * The default model name is specified on the factory, or "model"
52 * if nothing is defined.
53 * </p>
54 * <p>
55 * Document views can have transforms by specifying a
56 * "<code>transform</code>" child element.
57 * </p>
58 */
59 public class DocumentViewFactory implements ViewFactory
60 {
61 /**
62 * The default attribute name for the "model" object ["model"].
63 */
64 protected static final String DEFAULT_DEFAULT_BEAN_NAME = "model";
65
66 /**
67 * The XML attribute name to set a default "model" object name
68 * ["default-bean-name"].
69 *
70 */
71 protected static final String ATTR_DEFAULT_BEAN_NAME = "default-bean-name";
72
73 /**
74 * <p>
75 * The XML attribute name to specify the name for the "model" object
76 * ["bean"].
77 * <p>
78 * <p>
79 * The default attribute setting would be <code>bean="model"</code>.
80 * </p>
81 */
82 protected static final String ATTR_BEAN_NAME = "bean";
83
84 /**
85 * <p>
86 * The XML attribute name to specify the scope in which to store the
87 * "model" object ["scope"].
88 * </p>
89 * <p>
90 * The default attribute setting would be <code>scope="request"</code>.
91 * </p>
92 */
93 protected static final String ATTR_SCOPE = "scope";
94
95 /**
96 * <p>
97 * The XML attribute value to specify "global" or "application" scope.
98 * ["application"].
99 * An "model" object set to this scope is available to the entire
100 * application.
101 * </p>
102 */
103 protected static final String SCOPE_APP = "application";
104
105 /**
106 * <p>
107 * The XML attribute value to specify "client" or "session" scope.
108 * ["session"].
109 * An "model" object set to this scope is available to every request made
110 * by the same client during this application session.
111 * </p>
112 */
113 protected static final String SCOPE_SESSION = "session";
114
115 /**
116 * <p>
117 * The XML attribute value to specify "thread" or "request" scope.
118 * ["request"].
119 * An "model" object set to this scope is available to only within the
120 * thread of the current request.
121 * </p>
122 */
123 protected static final String SCOPE_REQUEST = "request";
124
125 /**
126 * <p>
127 * Property to hold the default name of the "model" object for this
128 * factory instance ["model"].
129 * </p>
130 */
131 protected String defaultBeanName = DEFAULT_DEFAULT_BEAN_NAME;
132
133 /**
134 * <p>
135 * Initialize this factory instance by initializing the
136 * {@link #dispatchedViewFact} property and the {@link #defaultBeanName}
137 * property.
138 * </p>
139 * @param factoryNode Element
140 * @param servletCfg ServletConfig
141 * @throws ConfigException
142 */
143 public void init(Element factoryNode, ServletConfig servletCfg) throws
144 ConfigException
145 {
146 if (factoryNode != null)
147 {
148 String value = XML.getValue(factoryNode, ATTR_DEFAULT_BEAN_NAME);
149 if (value != null && value.length() > 0)
150 this.defaultBeanName = value;
151 }
152 }
153
154 /**
155 * @param viewNode Element
156 * @return View
157 * @throws ConfigException
158 * @see ViewFactory#createView(Element)
159 */
160 public View createView(Element viewNode) throws ConfigException
161 {
162 String beanName = XML.getValue(viewNode, ATTR_BEAN_NAME);
163 if (beanName == null)
164 beanName = this.defaultBeanName;
165
166 String scope = XML.getValue(viewNode, ATTR_SCOPE);
167
168 // Provide different implementations of setAttribute depending on scope
169 if (SCOPE_APP.equals(scope))
170 {
171 return new DocumentView(beanName) {
172 protected void setAttribute(ViewContext vctx) {
173 vctx.getServletContext().setAttribute(this.beanName, vctx.getModel());
174 }
175 };
176 }
177 else if (SCOPE_SESSION.equals(scope))
178 {
179 return new DocumentView(beanName) {
180 protected void setAttribute(ViewContext vctx) {
181 vctx.getRequest().getSession().setAttribute(this.beanName, vctx.getModel());
182 }
183 };
184 }
185 else if (SCOPE_REQUEST.equals(scope) || scope == null)
186 {
187 return new DocumentView(beanName) {
188 protected void setAttribute(ViewContext vctx) {
189 vctx.getRequest().setAttribute(this.beanName, vctx.getModel());
190 }
191 };
192 }
193 else
194 {
195 throw new ConfigException("Illegal scope specified: " + XML.toString(viewNode));
196 }
197 }
198 }