You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2009/03/09 19:20:16 UTC
svn commit: r751785 [2/2] - in
/incubator/click/trunk/click/framework/src/org/apache/click: ./ control/
util/
Modified: incubator/click/trunk/click/framework/src/org/apache/click/util/PageImports.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/util/PageImports.java?rev=751785&r1=751784&r2=751785&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/util/PageImports.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/util/PageImports.java Mon Mar 9 18:20:16 2009
@@ -19,13 +19,17 @@
package org.apache.click.util;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import org.apache.click.Control;
import org.apache.click.Page;
+import org.apache.click.control.Container;
+import org.apache.click.control.Table;
import org.apache.click.service.LogService;
import org.apache.commons.lang.StringUtils;
@@ -76,10 +80,10 @@
* <span class="blue">$jsImports</span>
* </pre>
*
- * Please also see {@link Page#getHtmlImports()} and
- * {@link Control#getHtmlImports()}.
- *
- * @see Format
+ * Please also see {@link org.apache.click.Page#getHtmlHeaders()},
+ * {@link org.apache.click.Control#getHtmlHeaders()},
+ * {@link org.apache.click.Page#getHtmlImports()} and
+ * {@link org.apache.click.Control#getHtmlImports()}.
*
* @author Malcolm Edgar
*/
@@ -97,6 +101,9 @@
/** The list of JS script block lines. */
protected List jsScripts = new ArrayList();
+ /** The list of CSS styles. */
+ protected List cssStyles = new ArrayList();
+
/** The page instance. */
protected final Page page;
@@ -114,9 +121,52 @@
// --------------------------------------------------------- Public Methods
/**
- * Process the given control HTML import line.
+ * Add the given HtmlHeader to the Page HTML imports.
+ *
+ * @param htmlHeader the HtmlHeader to add
+ */
+ public void add(HtmlHeader htmlHeader) {
+ if (htmlHeader instanceof JavascriptImport) {
+ if (jsImports.contains(htmlHeader)) {
+ return;
+ }
+ jsImports.add(htmlHeader);
+
+ } else if (htmlHeader instanceof Javascript) {
+ if (((Javascript) htmlHeader).isUnique()) {
+ if (jsScripts.contains(htmlHeader)) {
+ return;
+ }
+ }
+ jsScripts.add(htmlHeader);
+
+ } else if (htmlHeader instanceof CssImport) {
+ if (cssImports.contains(htmlHeader)) {
+ return;
+ }
+ cssImports.add(htmlHeader);
+
+ } else if (htmlHeader instanceof Css) {
+ if (((Css) htmlHeader).isUnique()) {
+ if (cssStyles.contains(htmlHeader)) {
+ return;
+ }
+ }
+ cssStyles.add(htmlHeader);
+
+ } else {
+ throw new IllegalArgumentException(htmlHeader.getClass().getName()
+ + " is not a supported type.");
+ }
+ }
+
+ /**
+ * Add the given HTML import line to the Page HTML imports.
*
- * @param value the HTML import line to process
+ * @deprecated use the new {@link #add(org.apache.click.util.HtmlHeader)}
+ * instead
+ *
+ * @param value the HTML import line to add
*/
public void addImport(String value) {
if (value == null || value.length() == 0) {
@@ -128,17 +178,23 @@
for (int i = 0; i < lines.length; i++) {
String line = lines[i].trim().toLowerCase();
if (line.startsWith("<link") && line.indexOf("text/css") != -1) {
- addToList(lines[i], cssImports);
+ CssImport cssImport = asCssImport(lines[i]);
+ add(cssImport);
} else if (line.startsWith("<style") && line.indexOf("text/css") != -1) {
- addToList(lines[i], cssImports);
+ Css css = asCss(lines[i]);
+ css.setUnique(true);
+ add(css);
} else if (line.startsWith("<script")) {
if (line.indexOf(" src=") != -1) {
- addToList(lines[i], jsImports);
+ JavascriptImport javascriptImport = asJavascriptImport(lines[i]);
+ add(javascriptImport);
} else {
- addToList(lines[i], jsScripts);
+ Javascript javascript = asJavascript(lines[i]);
+ javascript.setUnique(true);
+ add(javascript);
}
} else {
@@ -239,85 +295,58 @@
// ------------------------------------------------------ Protected Methods
/**
- * Return a HTML string of all the page's HTML imports, including:
- * CSS imports, JS imports and JS script blocks.
+ * Render an HTML representation of all the page's HTML imports,
+ * including: CSS imports, CSS styles, JS imports and JS scripts.
*
- * @return a HTML string of all the page's HTML imports, including:
- * CSS imports, JS imports and JS script blocks.
+ * @param buffer the specified buffer to render the page's HTML imports to
*/
- protected String getAllIncludes() {
- processPageControls();
-
- int size = 80 * cssImports.size() + jsImports.size() + jsScripts.size();
- HtmlStringBuffer buffer = new HtmlStringBuffer(size);
-
- for (int i = 0; i < cssImports.size(); i++) {
- String line = cssImports.get(i).toString();
- buffer.append(line);
- buffer.append('\n');
- }
- for (int i = 0; i < jsImports.size(); i++) {
- String line = jsImports.get(i).toString();
- buffer.append(line);
- buffer.append('\n');
- }
- for (int i = 0; i < jsScripts.size(); i++) {
- String line = jsScripts.get(i).toString();
- buffer.append(line);
- buffer.append('\n');
- }
-
- return buffer.toString();
+ protected void renderAllIncludes(HtmlStringBuffer buffer) {
+ renderCssImports(buffer);
+ renderJsImports(buffer);
}
/**
- * Return a HTML string of all the page's HTML CSS imports.
+ * Render an HTML representation of all all the page's HTML CSS
+ * {@link #cssImports imports} and {@link #cssStyles styles}.
*
- * @return a HTML string of all the page's HTML CSS imports.
+ * @param buffer the specified buffer to render the page's HTML imports to
*/
- protected String getCssImports() {
- processPageControls();
-
- HtmlStringBuffer buffer = new HtmlStringBuffer(80 * cssImports.size());
-
- for (int i = 0; i < cssImports.size(); i++) {
- String line = cssImports.get(i).toString();
- buffer.append(line);
- if (i < cssImports.size() - 1) {
- buffer.append('\n');
- }
+ protected void renderCssImports(HtmlStringBuffer buffer) {
+ // First include all the imports e.g. <link href="...">
+ for (Iterator it = cssImports.iterator(); it.hasNext();) {
+ CssImport cssImport = (CssImport) it.next();
+ cssImport.render(buffer);
+ buffer.append('\n');
}
- return buffer.toString();
+ // Then include all the styles e.g. <style>...</style>
+ for (Iterator it = cssStyles.iterator(); it.hasNext();) {
+ Css cssInclude = (Css) it.next();
+ cssInclude.render(buffer);
+ buffer.append('\n');
+ }
}
/**
- * Return a HTML string of all the page's HTML JS imports and scripts.
+ * Render an HTML representation of all the page's HTML JavaScript
+ * {@link #jsImports imports} and {@link #jsScripts scripts}.
*
- * @return a HTML string of all the page's HTML JS imports and scripts.
+ * @param buffer the specified buffer to render the page's HTML imports to
*/
- protected String getJsImports() {
- processPageControls();
-
- HtmlStringBuffer buffer = new HtmlStringBuffer(80 * jsImports.size());
-
- for (int i = 0; i < jsImports.size(); i++) {
- String line = jsImports.get(i).toString();
- buffer.append(line);
- if (i < jsImports.size() - 1 || !jsScripts.isEmpty()) {
- buffer.append('\n');
- }
+ protected void renderJsImports(HtmlStringBuffer buffer) {
+ // First include all the imports e.g. <script src="...">
+ for (Iterator it = jsImports.iterator(); it.hasNext();) {
+ JavascriptImport javascriptImport = (JavascriptImport) it.next();
+ javascriptImport.render(buffer);
+ buffer.append('\n');
}
- for (int i = 0; i < jsScripts.size(); i++) {
- String line = jsScripts.get(i).toString();
- buffer.append(line);
- if (i < jsScripts.size() - 1) {
- buffer.append('\n');
- }
+ // Then include all the scripts e.g. <script>...</script>
+ for (Iterator it = jsScripts.iterator(); it.hasNext();) {
+ Javascript javascriptInclude = (Javascript) it.next();
+ javascriptInclude.render(buffer);
+ buffer.append('\n');
}
-
- return buffer.toString();
}
/**
@@ -334,40 +363,75 @@
for (int i = 0; i < page.getControls().size(); i++) {
Control control = (Control) page.getControls().get(i);
+ // import from getHtmlImports
addImport(control.getHtmlImports());
+
+ // import from getHtmlHeaders
+ processControl(control);
}
}
addImport(page.getHtmlImports());
+
+ processHtmlHeaders(page.getHtmlHeaders());
}
/**
- * Add the given string item to the list if it is not already present.
+ * Process the given control HTML headers. This method will recursively
+ * process Containers and all child controls.
+ * <p/>
+ * This method delegates to {@link #processHtmlHeaders(java.util.List)}
+ * to add the HTML headers to the Page imports.
*
- * @param item the line item to add
- * @param list the list to add the item to
+ * @param control the control to process
*/
- protected void addToList(String item, List list) {
- item = item.trim();
+ protected void processControl(Control control) {
+ processHtmlHeaders(control.getHtmlHeaders());
- boolean found = false;
+ if (control instanceof Container) {
+ Container container = (Container) control;
+ if (container.hasControls()) {
+ List controls = container.getControls();
+ for (int i = 0, size = controls.size(); i < size; i++) {
+ processControl((Control) controls.get(i));
+ }
+ }
- for (int i = 0; i < list.size(); i++) {
- if (list.get(i).equals(item)) {
- found = true;
- break;
+ } else if (control instanceof Table) {
+ Table table = (Table) control;
+ if (table.hasControls()) {
+ List controls = table.getControls();
+ for (int i = 0, size = controls.size(); i < size; i++) {
+ processControl((Control) controls.get(i));
+ }
}
}
+ }
+
+ /**
+ * Process the given list of HTML headers.
+ * <p/>
+ * This method invokes {@link #add(org.apache.click.util.HtmlHeader)} for
+ * every <tt>HtmlHeader</tt> entry in the specified list.
+ *
+ * @param htmlHeaders the list of HTML headers to process
+ */
+ protected void processHtmlHeaders(List htmlHeaders) {
+ if (htmlHeaders == null || htmlHeaders.isEmpty()) {
+ return;
+ }
- if (!found) {
- list.add(item);
+ Iterator it = htmlHeaders.iterator();
+ while (it.hasNext()) {
+ add((HtmlHeader) it.next());
}
}
// ------------------------------------------------------- Internal Classes
/**
- * This class enables lazy, on demand importing for {@link #getAllIncludes()}.
+ * This class enables lazy, on demand importing for
+ * {@link #renderAllIncludes(org.apache.click.util.HtmlStringBuffer)}.
*/
class Imports {
@@ -377,12 +441,20 @@
* @return a string representing all includes
*/
public String toString() {
- return PageImports.this.getAllIncludes();
+ processPageControls();
+ HtmlStringBuffer buffer = new HtmlStringBuffer(
+ 80 * jsImports.size()
+ + 80 * jsScripts.size()
+ + 80 * cssImports.size()
+ + 80 * cssStyles.size());
+ PageImports.this.renderAllIncludes(buffer);
+ return buffer.toString();
}
}
/**
- * This class enables lazy, on demand importing for {@link #getJsImports()}.
+ * This class enables lazy, on demand importing for
+ * {@link #renderJsImports(org.apache.click.util.HtmlStringBuffer)}.
*/
class JsImports {
@@ -392,12 +464,18 @@
* @return a string representing all JavaScript imports
*/
public String toString() {
- return PageImports.this.getJsImports();
+ processPageControls();
+ HtmlStringBuffer buffer = new HtmlStringBuffer(
+ 80 * jsImports.size() + 80 * jsScripts.size());
+
+ PageImports.this.renderJsImports(buffer);
+ return buffer.toString();
}
}
/**
- * This class enables lazy, on demand importing for {@link #getCssImports()}.
+ * This class enables lazy, on demand importing for
+ * {@link #renderCssImports(org.apache.click.util.HtmlStringBuffer)}.
*/
class CssImports {
@@ -407,7 +485,123 @@
* @return a string representing all CSS imports
*/
public String toString() {
- return PageImports.this.getCssImports();
+ processPageControls();
+ HtmlStringBuffer buffer = new HtmlStringBuffer(
+ 80 * cssImports.size() + 80 * cssStyles.size());
+
+ PageImports.this.renderCssImports(buffer);
+ return buffer.toString();
+ }
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+ /**
+ * Convert the given HTML import line to a {@link CssImport} instance.
+ *
+ * @param line the HTML import line to convert to a CssImport instance
+ * @return a CssImport instance
+ */
+ private CssImport asCssImport(String line) {
+ CssImport cssImport = new CssImport();
+ copyAttributes(cssImport, line);
+ return cssImport;
+ }
+
+ /**
+ * Convert the given HTML import line to a {@link Css} instance.
+ *
+ * @param line the HTML import line to convert to a Css instance
+ * @return a Css instance
+ */
+ private Css asCss(String line) {
+ Css css = new Css();
+ copyAttributes(css, line);
+ css.append(extractContent(line));
+ return css;
+ }
+
+ /**
+ * Convert the given HTML import line to a {@link JavascriptImport} instance.
+ *
+ * @param line the HTML import line to convert to a JavaScriptImport instance
+ * @return a JavascriptImport instance
+ */
+ private JavascriptImport asJavascriptImport(String line) {
+ JavascriptImport javascriptImport = new JavascriptImport();
+ copyAttributes(javascriptImport, line);
+ return javascriptImport;
+ }
+
+ /**
+ * Convert the given HTML import line to a {@link Javascript} instance.
+ *
+ * @param line the HTML import line to convert to a JavaScript instance
+ * @return a Javascript instance
+ */
+ private Javascript asJavascript(String line) {
+ Javascript javascript = new Javascript();
+ copyAttributes(javascript, line);
+ javascript.append(extractContent(line));
+ return javascript;
+ }
+
+ /**
+ * Extract the JavaScript or CSS content from the given HTML import line.
+ *
+ * @param line the HTML import line
+ * @return the JavaScript or CSS content contained in the HTML import line
+ */
+ private String extractContent(String line) {
+ if (line.endsWith("/>")) {
+ // If tag has no content, exit early
+ return "";
+ }
+
+ // Find index where tag ends
+ int start = line.indexOf('>');
+ if (start == -1) {
+ throw new IllegalArgumentException(line + " is not a valid element");
+ }
+ int end = line.indexOf('<', start);
+ if (end == -1) {
+ return "";
+ }
+ return line.substring(start + 1, end);
+ }
+
+ /**
+ * Copy all available attributes from HTML import line to the HtmlHeader
+ * instance.
+ *
+ * @param htmlHeader the HTML header to copy the attributes to
+ * @param line the HTML import line to copy attributes from
+ */
+ private void copyAttributes(HtmlHeader htmlHeader, String line) {
+ // Find index where attributes start: the first space
+ int start = line.indexOf(' ');
+ if (start == -1) {
+ // If no attributes found, exit early
+ return;
+ }
+
+ // Find index where attributes end: closing tag
+ int end = line.indexOf("/>");
+ if (end == -1) {
+ end = line.indexOf(">");
+ }
+ if (end == -1) {
+ throw new IllegalArgumentException(line + " is not a valid HTML import");
+ }
+
+ line = line.substring(start, end);
+ StringTokenizer tokens = new StringTokenizer(line, " ");
+ while (tokens.hasMoreTokens()) {
+ String token = tokens.nextToken();
+ StringTokenizer attribute = new StringTokenizer(token, "=");
+ String key = attribute.nextToken();
+ String value = attribute.nextToken();
+ htmlHeader.setAttribute(key, StringUtils.strip(value, "'\""));
}
}
}