/* HeaderInfo.java
{{IS_NOTE
Purpose:
Description:
History:
Thu Sep 14 22:02:29 2006, Created by tomyeh
}}IS_NOTE
Copyright (C) 2006 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
}}IS_RIGHT
*/
package org.zkoss.zk.ui.metainfo;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.zkoss.html.HTMLs;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.util.ConditionImpl;
import org.zkoss.zk.xel.Evaluator;
import org.zkoss.zk.xel.ExValue;
/**
* Represents a header element, such as <?link> and <?meta>
* directives on the ZUML page.
* They are usually represented as directives in ZUML.
* For example, the link and meta directives represent <link>
* and <meta> HTML tags, respectively.
*
* <p>Notice
* <ul>
* <li>Directives are evaluated before all other tags. Thus, it is not
* possible to set a value in zscript and then reference it in an attribute
* of the directive.</li>
* <li>If a page is included by another page with the instant mode
* ({@link org.zkoss.zul.Include#getMode}), the directives will be ignored.</li>
* <li>EL is allowed for every attribute.</li>
* <li>Since 5.0.0, the if and unless attributes are supported.</li>
* </ul>
*
* <p>It is not serializable.
*
* @author tomyeh
* @see ResponseHeaderInfo
*/
public class HeaderInfo { //directive
private final String _name;
/** A list of AttrInfo. */
private final List<AttrInfo> _attrs;
private final ConditionImpl _cond;
/** Constructor.
*
* <p>Note: it detects the href attribute (from the attrs argument), and
* encodes it with {@link Executions#encodeURL}.
*
* @param name the tag name, such as link (never null or empty).
* @param attrs a map of (String, String) attributes.
*/
public HeaderInfo(String name, Map<String, String> attrs, ConditionImpl cond) {
if (name == null || name.length() == 0)
throw new IllegalArgumentException("empty");
_name = name;
_cond = cond;
if (attrs == null || attrs.isEmpty()) {
_attrs = Collections.emptyList();
} else {
_attrs = new LinkedList<AttrInfo>();
for (Map.Entry<String, String> me : attrs.entrySet()) {
final String nm = me.getKey(), val = me.getValue();
_attrs.add(new AttrInfo(nm, new ExValue(val, String.class)));
}
}
}
/** Returns the tag name of this header element.
*/
public String getName() {
return _name;
}
/** Returns as HTML tag(s) representing this header element.
*
* @param page the page containing this header element.
* It is used to evaluate EL expression, if any, contained in the value.
* @since 6.0.0
*/
public String toHTML(PageDefinition pgdef, Page page) {
final Evaluator eval = pgdef.getEvaluator();
if (_cond != null && !_cond.isEffective(eval, page))
return "";
final boolean bScript = "script".equals(_name), bStyle = !bScript && "style".equals(_name);
//1. scan content
final StringBuffer sb = new StringBuffer(128);
if (bScript || bStyle) {
String content = null;
boolean srcFound = false;
for (AttrInfo attr : _attrs) {
final String nm = attr.name;
if ("content".equals(nm)) {
content = (String) attr.value.getValue(eval, page);
} else {
srcFound = srcFound || "src".equals(nm) || "href".equals(nm);
}
}
if (content != null) {
sb.append('<').append(_name).append(" type=\"text/").append(bScript ? "javascript" : "css")
.append("\">\n").append(content).append("\n</").append(_name).append('>');
if (srcFound)
sb.append('\n');
}
if (!srcFound)
return sb.toString(); //no more to generate
}
sb.append('<').append(bStyle ? "link" : _name);
boolean relFound = false, typeFound = false;
for (AttrInfo attr : _attrs) {
final String nm = attr.name;
if ((bScript || bStyle) && "content".equals(nm))
continue; //skip
relFound = bStyle && (relFound || "rel".equals(nm));
typeFound = (bScript || bStyle) && (typeFound || "type".equals(nm));
String val = (String) attr.value.getValue(eval, page);
if (val == null || val.length() == 0)
val = "";
else if ("href".equals(nm) || ((bScript || bStyle) && "src".equals(nm)))
val = Executions.encodeURL(val);
HTMLs.appendAttribute(sb, bStyle && "src".equals(nm) ? "href" : bScript && "href".equals(nm) ? "src" : nm,
val);
}
if (bStyle && !relFound)
sb.append(" rel=\"stylesheet\"");
if ((bScript || bStyle) && !typeFound)
sb.append(" type=\"text/").append(bScript ? "javascript" : "css").append('"');
return sb.append(bScript ? ">\n</script>" : "/>").toString();
}
private static class AttrInfo {
private final String name;
private final ExValue value;
private AttrInfo(String name, ExValue value) {
this.name = name;
this.value = value;
}
}
}