001: package simpleorm.simplewebapp.core;
002:
003: import simpleorm.simplewebapp.core.WMenuParentGlobal;
004: import simpleorm.simplewebapp.core.WMenuItemGlobal;
005:
006: import java.util.LinkedHashMap;
007: import java.util.Collections;
008: import java.util.Map;
009:
010: /**
011: * One-to-one delegate of WPage contains all of a page's doevents, top level fields, groups, menus etc..<p>
012: * <p/>
013: * Fields belong to fieldGroups, which belong to a WPage/WebBean.
014: * It is a simple flat, two level non-recursive structure that is manual to interpret in JSTL templates.<p>
015: * <p/>
016: */
017: public class WPageStructure {
018:
019: WPage page;
020:
021: /**
022: * Used by menus to check accessibility as menu objects are static, not per page.
023: */
024: static ThreadLocal<WPage> pageThreadLocal = new ThreadLocal();
025:
026: LinkedHashMap<String, WPagelet> pagelets = new LinkedHashMap(3);
027: WPagelet currentPagelet = null;
028:
029: /**
030: * The WMenuItemGlobal within menu that represents this page instance.
031: * Used as the source of truth for page name, page url etc.
032: * Normally set by WServlet -- see WMenuAbstractGlobal.
033: * <p/>
034: * WARNING, this is a reference to the Global menu entry, do not modify.
035: */
036: WMenuItemGlobal pageItem;
037:
038: /**
039: * Where to redirect to after this form.
040: * Normally set to WPagelet.potentialRedirectUrl if form was successfully processed.
041: * This is now set manually by GenericCrud etc.
042: */
043: String actualRedirectUrl;
044:
045: /** Suppress the rendering of the page, ie allow the servlet to directly output the result.
046: * Used for file downloads.
047: */
048: boolean suppressRender = false;
049:
050: /**
051: * The button bar, mainly for CRUD forms.
052: */
053: WButtonBar buttonBar = new WButtonBar();
054:
055: /** True if multipart, ie file upload, which changes the parameters to the HTML FORM tag. */
056: boolean isMultipart = false;
057:
058: public WPageStructure(WPage wPage) {
059: this .page = wPage;
060: pageThreadLocal.set(wPage);
061: }
062:
063: public Map<String, WPagelet> getPagelets() {
064: return Collections.unmodifiableMap(pagelets);
065: }
066:
067: public WButton addNewButton(String nameValue, WPagelet pagelet) {
068: WButton button = new WButton(nameValue, pagelet);
069: buttonBar.putButton(button);
070: return button;
071: }
072:
073: /**
074: * Returns the current pagelet as set by WPageletTag, or the only one if there is one.
075: * Exception if ambiguous.
076: */
077: public WPagelet getCurrentPagelet() {
078: WPagelet ret = null;
079: if (currentPagelet != null)
080: ret = currentPagelet;
081: else if (pagelets.size() == 1)
082: ret = pagelets.values().iterator().next();
083: else
084: throw new WException(
085: "Ambiguous Current Pagelet, use WPagelet tag to speify");
086: return ret;
087: }
088:
089: /**
090: * Gets the current pagelet, cast to a WPageletList, exception if not.
091: */
092: public WPageletList getCurrentPageletList() {
093: if (!(getCurrentPagelet() instanceof WPageletList))
094: throw new WException("Current Pagelet is not a WPagelList "
095: + getCurrentPagelet());
096: return (WPageletList) getCurrentPagelet();
097: }
098:
099: public WPagelet getPagelet(String name) {
100: return pagelets.get(name);
101: }
102:
103: static public WPage getThreadPage() {
104: return pageThreadLocal.get();
105: }
106:
107: /**
108: * The main set of menus, normally static and global.
109: */
110: public WMenuParentGlobal getMenus() {
111: return WGlobalState.dirtyGetGlobalState().getMenus();
112: }
113:
114: ///////// Events /////////////////////
115:
116: /**
117: * The main entry point for processing a form.
118: * Called by WServlet or explicitly by test cases.
119: * Fires the various events and deals with WValidationExceptions
120: */
121: public void doMain() throws Exception {
122: page.logger.info("\n\n=========== "
123: + this .getClass().getSimpleName() + " =============");
124: page.onInitialize();
125: for (WPagelet p1 : pagelets.values())
126: p1.onInitialize();
127:
128: retrieveParameters(); // into field.text, but not validated or converted to field.value
129:
130: for (WPagelet p1 : pagelets.values()) {
131: try {
132: p1.onPreValidate();
133: p1.validateFields(); // Catches all WValidationExceptions
134: if (!p1.isErroneous()) {
135: p1.onPreMaybeSubmitted();
136: if (p1.wasSubmitted())
137: p1.onWasSubmitted();
138: else
139: p1.onNotSubmitted();
140: p1.onPostMaybeSubmitted();
141: }
142: } catch (WValidationException ve1) {
143: ve1.setPagelet(p1);
144: page.getErrors().add(ve1);
145: }
146: try {
147: p1.onMaybeErroneous();
148: } catch (WValidationException ve2) {
149: ve2.setPagelet(p1);
150: page.getErrors().add(ve2);
151: }
152: }
153: page.logPage();
154: }
155:
156: void retrieveParameters() throws Exception {
157: for (WPagelet p1 : pagelets.values())
158: p1.retrieveParameters();
159: }
160:
161: /**
162: * Called by wForEachRowTag to retreive the next row THE list pagelet.
163: * Does not support multiple list pagelets in same form.
164: */
165: public boolean doListRow() throws Exception {
166: return getCurrentPageletList().doListRow();
167: }
168:
169: /**
170: * Calls the finalizer, called by WPageTag or unit tests.
171: */
172: public void doFinalize() throws Exception {
173: for (WPagelet p1 : pagelets.values()) {
174: p1.onFinalize();
175: p1.onFinalizeInternal();
176: }
177: page.onFinalize();
178: page.onFinalizeInternal();
179: page.logger.debug("doFinalize end " + page.logger.time());
180: }
181:
182: void onFinalizeInternal() throws Exception {
183: pageThreadLocal.set(null);
184: currentPagelet = null;
185: pagelets = null;
186: pageItem = null;
187: buttonBar = null;
188: }
189:
190: /**
191: * Returns the simulated default name/value parameter map that the browser would submit.
192: * Only used for unit tests.
193: */
194: public Map<String, String> browserParameters() {
195: Map<String, String> res = new LinkedHashMap(50);
196: for (WPagelet plet : getPagelets().values()) {
197: for (WField field : plet.getAllFieldValues()) {
198: if (!field.notRetrieved) {
199: res.put(field.getHtmlName(), field.getText());
200: if (page.getLogger().isDebug())
201: page.getLogger().debug(
202: "browseParameter "
203: + field.getHtmlName() + " = "
204: + field.getText());
205: }
206: }
207: }
208: return res;
209: }
210:
211: public String toString() {
212: return "{PageComponents " + page.getClass().getSimpleName()
213: + "}";
214: }
215:
216: //////////// generated ///////////////
217:
218: public void setPageItem(WMenuItemGlobal pageItem) {
219: this .pageItem = pageItem;
220: }
221:
222: public WMenuItemGlobal getPageItem() {
223: return pageItem;
224: }
225:
226: public void setCurrentPagelet(WPagelet currentPagelet) {
227: this .currentPagelet = currentPagelet;
228: }
229:
230: public String getActualRedirectUrl() {
231: return actualRedirectUrl;
232: }
233:
234: public void setActualRedirectUrl(String actualRedirectUrl) {
235: this .actualRedirectUrl = actualRedirectUrl;
236: }
237:
238: public boolean isSuppressRender() {
239: return suppressRender;
240: }
241:
242: public void setSuppressRender(boolean suppressRender) {
243: this .suppressRender = suppressRender;
244: }
245:
246: public void setMultipart(boolean multipart) {
247: isMultipart = multipart;
248: }
249: }
|