001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.html;
020:
021: import org.apache.beehive.netui.tags.AbstractPageError;
022: import org.apache.beehive.netui.tags.ErrorHandling;
023: import org.apache.beehive.netui.tags.IErrorReporter;
024: import org.apache.beehive.netui.tags.IDocumentTypeProducer;
025: import org.apache.beehive.netui.tags.javascript.ScriptContainer;
026: import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
027: import org.apache.beehive.netui.tags.rendering.HtmlTag;
028: import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
029: import org.apache.beehive.netui.tags.rendering.WriteRenderAppender;
030: import org.apache.struts.Globals;
031:
032: import javax.servlet.ServletRequest;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpSession;
035: import javax.servlet.jsp.JspException;
036: import javax.servlet.jsp.tagext.Tag;
037: import java.util.ArrayList;
038: import java.util.Locale;
039:
040: /**
041: * Generates the html element and performs error handling within its body.
042: * @jsptagref.tagdescription <p>
043: * Renders an <html> tag.
044: * </p>
045: * @example In this sample, the <netui:html> tag uses the default locale and the direction of the HTML is
046: * left-to-right (LTR).
047: * <pre><netui:html dir="LTR" useLocale="true" /></pre>
048: *
049: * @netui:tag name="html" description="Generates the html element and performs error handling within its body."
050: */
051: public class Html extends ScriptContainer implements IErrorReporter,
052: IDocumentTypeProducer {
053: /**
054: * The HTML tag is registered into the request with this name. This allows tags reporting
055: * errors to find the top level <code>ErrorReporter</code>.
056: */
057: public static final String HTML_TAG_ID = "netui:html";
058:
059: /**
060: * This is an override of the Document type set in the request
061: */
062: public static final String DOC_TYPE_OVERRIDE = "netui:doctype";
063:
064: /**
065: * Constant representing the document type html 4.01
066: */
067: public static final String HTML_401 = "html4-loose";
068:
069: /**
070: * Constant representing the document type html 4.01
071: */
072: public static final String HTML_401_QUIRKS = "html4-loose-quirks";
073:
074: /**
075: * Constant representing the document type XHTML 1.0 Transitional.
076: */
077: public static final String XHTML_10 = "xhtml1-transitional";
078:
079: private HtmlTag.State _state = new HtmlTag.State();
080: private TagRenderingBase _br;
081: private WriteRenderAppender _writer;
082:
083: private boolean _useLocale = false; // include xml:lang=defaultLocale.getLanguage()
084: private boolean _scopeEnded = false;
085: private ArrayList _errors; // errors
086: private IErrorReporter _containerErrors; //Check to see if there is a parent error reporter
087:
088: private String _docType; // The document type
089:
090: private int _rendering = TagRenderingBase.UNKNOWN_RENDERING;
091:
092: /**
093: * Returns the name of the Tag.
094: */
095: public String getTagName() {
096: return "Html";
097: }
098:
099: /**
100: * This method will return the TagRenderBase enum value for the document type. The default
101: * value is HTML 4.01.
102: * @return int
103: */
104: public int getTargetDocumentType() {
105: if (_rendering != TagRenderingBase.UNKNOWN_RENDERING)
106: return _rendering;
107:
108: if (_docType != null) {
109: if (_docType.equals(HTML_401))
110: _rendering = TagRenderingBase.HTML_RENDERING;
111: else if (_docType.equals(HTML_401_QUIRKS))
112: _rendering = TagRenderingBase.HTML_RENDERING_QUIRKS;
113: else if (_docType.equals(XHTML_10))
114: _rendering = TagRenderingBase.XHTML_RENDERING;
115: else
116: _rendering = TagRenderingBase.getDefaultDocType();
117: } else {
118: _rendering = TagRenderingBase.getDefaultDocType();
119: }
120: return _rendering;
121: }
122:
123: /////////////////////////// Attributes ////////////////////////////
124:
125: /**
126: * Sets the dir value of the html.
127: * @param dir the direction of text, "LTR" or "RTL"
128: * @jsptagref.attributedescription Specifies the direction of text. (<code>LTR | RTL</code>)
129: * @jsptagref.databindable false
130: * @jsptagref.attributesyntaxvalue <i>string_dir</i>
131: * @netui:attribute required="false" rtexprvalue="true"
132: * description="Sets the dir value (ltr or rtl) of the html."
133: */
134: public void setDir(String dir) {
135: _state.dir = dir;
136: }
137:
138: /**
139: * Gets whether the default locale's language should be used.
140: * @return true or false
141: */
142: public boolean isUseLocale() {
143: return _useLocale;
144: }
145:
146: /**
147: * Sets whether the default locale's language should be used.
148: * @param locale true or false
149: * @jsptagref.attributedescription Sets whether the default locale's language should be used.
150: * @jsptagref.databindable false
151: * @jsptagref.attributesyntaxvalue <i>boolean_locale</i>
152: * @netui:attribute required="false" rtexprvalue="true" type="boolean"
153: * description="Sets whether the default locale's language should be used."
154: */
155: public void setUseLocale(boolean locale) {
156: _useLocale = locale;
157: }
158:
159: /**
160: * Set the document type (html4-loose or xhtml1-transitional) of the document.
161: * @jsptagref.attributedescription Set the document type (html4-loose or xhtml1-transitional) of the document.
162: * The default is html4-loose-quirks.
163: * @jsptagref.databindable false
164: * @jsptagref.attributesyntaxvalue <i>string_doctype</i>
165: * @netui:attribute required="false" rtexprvalue="true"
166: * description="Set the document type (html4-loose or xhtml1-transitional) of the document."
167: */
168: public void setDocumentType(String docType) {
169: _docType = docType;
170: }
171:
172: public int doStartTag() throws JspException {
173: // check to see if there is a scope id
174: ServletRequest req = pageContext.getRequest();
175: _containerErrors = (org.apache.beehive.netui.tags.IErrorReporter) req
176: .getAttribute(CONTAINER_ERRORS);
177:
178: //Make this tag available to child tags
179: req.setAttribute(HTML_TAG_ID, this );
180:
181: // set the local
182: Locale currentLocale = currentLocale();
183: if (currentLocale == null) {
184: currentLocale = Locale.getDefault();
185: }
186:
187: // write out the html...
188: _state.lang = currentLocale.getLanguage();
189: String idScope = getRealIdScope();
190: pushIdScope();
191: if (idScope != null) {
192: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
193: "netui:idScope", idScope);
194: }
195:
196: _writer = new WriteRenderAppender(pageContext);
197: _br = TagRenderingBase.Factory.getRendering(
198: TagRenderingBase.HTML_TAG, req);
199: _br.doStartTag(_writer, _state);
200: _writer.append("\n");
201:
202: return EVAL_BODY_INCLUDE;
203: }
204:
205: /**
206: * Write out the body content and report any errors that occured.
207: * @throws JspException if a JSP exception has occurred
208: */
209: public int doEndTag() throws JspException {
210: popIdScope();
211:
212: // if there are errors then we should output the error table
213: ErrorHandling.reportCollectedErrors(pageContext, this );
214:
215: // The body tag may cause the scope Div to be closed, if not we must do it now
216: //if (getIdScope() != null && !_scopeEnded) {
217: // _writer.append("</div>");
218: //}
219:
220: // the script can be written out by another tag, typically this would be the <body> tag.
221: writeScript(_writer);
222:
223: // close the html tag
224: if (!_scopeEnded)
225: _writer.append("\n");
226: _br.doEndTag(_writer);
227: localRelease();
228: return EVAL_PAGE;
229: }
230:
231: /**
232: * This will close the HTML div associated with the idScope. This may be
233: * called by the Body tag so the div ends before the body ends.
234: * @param _writer a writer to write the close tag into
235: */
236: public void endScope(WriteRenderAppender _writer) {
237: // write the close tag and mark the fact that it is now closed.
238: //_writer.append("</div>\n");
239: _scopeEnded = true;
240: }
241:
242: /**
243: * Add an error to the errors being reported by this tag.
244: * @param ape The AbstractPageError to add
245: */
246: public void addError(AbstractPageError ape) {
247: assert (ape != null);
248:
249: // if this is not the error reporter, then find an error reporter above this one.
250: if (_containerErrors == null && _errors == null) {
251: Tag par = getParent();
252: while (par != null) {
253: if (par instanceof org.apache.beehive.netui.tags.IErrorReporter) {
254: _containerErrors = (org.apache.beehive.netui.tags.IErrorReporter) par;
255: break;
256: }
257: par = par.getParent();
258: }
259: }
260:
261: // if there is an error reporter, add the error and return
262: if (_containerErrors != null) {
263: _containerErrors.addError(ape);
264: return;
265: }
266:
267: // This is the error reporter.
268: if (_errors == null) {
269: _errors = new ArrayList();
270: }
271:
272: // add the error and update it
273: _errors.add(ape);
274: ape.errorNo = _errors.size();
275: }
276:
277: /**
278: * Return an ArrayList of the errors
279: * @return an <code>ArrayList</code> of all errors.
280: */
281: public ArrayList returnErrors() {
282: if (_containerErrors != null)
283: return _containerErrors.returnErrors();
284: ArrayList e = _errors;
285: _errors = null;
286: return e;
287: }
288:
289: /**
290: * This boolean indicates if an ErrorReporter is reporting errors
291: * or not. The caller should check this before calling addError
292: * because the ErrorReporter may be off for some reason.
293: * @return a boolean indicating if the tag is reporting errors or not.
294: */
295: public boolean isReporting() {
296: return true;
297: }
298:
299: /**
300: * Return the current Locale for this request, creating a new one if
301: * necessary. If there is no current Locale, and locale support is not
302: * requested, return <code>null</code>.
303: */
304: protected Locale currentLocale() {
305: ServletRequest req = pageContext.getRequest();
306:
307: // Create a new session if necessary
308: HttpSession session = pageContext.getSession();
309: if ((_useLocale) && (session == null))
310: session = ((HttpServletRequest) req).getSession();
311: if (session == null)
312: return null;
313:
314: // Return any currently set Locale in our session
315: Locale current = (Locale) session
316: .getAttribute(Globals.LOCALE_KEY);
317: if (current != null)
318: return current;
319:
320: // Configure a new current Locale, if requested
321: if (!_useLocale)
322: return (null);
323: current = req.getLocale();
324: if (current != null)
325: session.setAttribute(Globals.LOCALE_KEY, current);
326: return current;
327: }
328:
329: /**
330: * Release any acquired resources.
331: */
332: protected void localRelease() {
333: super .localRelease();
334:
335: _state.clear();
336: _br = null;
337: _writer = null;
338:
339: _useLocale = false;
340: _scopeEnded = false;
341: _errors = null;
342: _containerErrors = null;
343: pageContext.getRequest().removeAttribute(HTML_TAG_ID);
344: }
345: }
|