/*
* Copyright 2004-2012 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.mayaa.impl.builder.library;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;
import org.seasar.mayaa.builder.library.PropertyDefinition;
import org.seasar.mayaa.builder.library.PropertySet;
import org.seasar.mayaa.cycle.script.CompiledScript;
import org.seasar.mayaa.engine.processor.ProcessorProperty;
import org.seasar.mayaa.engine.processor.TemplateProcessor;
import org.seasar.mayaa.engine.specification.SpecificationNode;
import org.seasar.mayaa.impl.engine.processor.JspProcessor;
import org.seasar.mayaa.impl.util.ObjectUtil;
/**
* @author Masataka Kurihara (Gluegent, Inc.)
* @author Hisayoshi Sasaki (Gluegent, Inc.)
*/
public class TLDProcessorDefinition extends ProcessorDefinitionImpl {
private static final long serialVersionUID = -646585734601397162L;
public static final String BODY_CONTENT_EMPTY = "empty";
public static final String BODY_CONTENT_JSP = "JSP";
public static final String BODY_CONTENT_SCRIPTLESS = "scriptless";
public static final String BODY_CONTENT_TAGDEPENDENT = "tagdependent";
private Class _tagClass;
private Class _teiClass;
private boolean _dynamicAttribute;
private String _bodyContent = BODY_CONTENT_JSP;
public void setProcessorClass(Class processorClass) {
if (JspProcessor.isSupportClass(processorClass) == false) {
throw new IllegalArgumentException();
}
_tagClass = processorClass;
}
public Class getProcessorClass() {
if (_tagClass == null) {
throw new IllegalStateException();
}
return _tagClass;
}
public void setExtraInfoClass(Class teiClass) {
if (teiClass == null
|| TagExtraInfo.class.isAssignableFrom(teiClass) == false) {
throw new IllegalArgumentException();
}
_teiClass = teiClass;
}
public Class getExtraInfoClass() {
return _teiClass;
}
public boolean isDynamicAttribute() {
return _dynamicAttribute;
}
public void setDynamicAttribute(boolean dynamicAttribute) {
this._dynamicAttribute = dynamicAttribute;
}
public String getBodyContent() {
if (_bodyContent == null) {
throw new IllegalStateException();
}
return _bodyContent;
}
public void setBodyContent(String bodyContent) {
if ((BODY_CONTENT_EMPTY.equals(bodyContent) ||
BODY_CONTENT_JSP.equals(bodyContent) ||// for JSP 1.2
BODY_CONTENT_SCRIPTLESS.equals(bodyContent) ||
BODY_CONTENT_TAGDEPENDENT.equals(bodyContent)) == false) {
throw new IllegalArgumentException();
}
_bodyContent = bodyContent;
}
protected TemplateProcessor newInstance() {
JspProcessor processor = new JspProcessor();
processor.setTagClass(getProcessorClass());
return processor;
}
protected void settingPropertySet(
SpecificationNode original, SpecificationNode injected,
TemplateProcessor processor, PropertySet propertySet) {
Hashtable tagDataSeed = new Hashtable();
JspProcessor jspProcessor = (JspProcessor) processor;
for (Iterator it = propertySet.iteratePropertyDefinition();
it.hasNext();) {
PropertyDefinition property = (PropertyDefinition) it.next();
Object prop =
property.createProcessorProperty(this, jspProcessor, original, injected);
if (prop != null) {
ProcessorProperty currentProp = (ProcessorProperty) prop;
jspProcessor.addProcessorProperty(currentProp);
CompiledScript value = currentProp.getValue();
tagDataSeed.put(
currentProp.getName().getQName().getLocalName(),
prepareScript(value));
}
}
if (getExtraInfoClass() != null) {
settingExtraInfo(jspProcessor, tagDataSeed);
}
if (getBodyContent().equals(BODY_CONTENT_EMPTY)) {
jspProcessor.setForceBodySkip(true);
}
// TODO 他のbody-content対応
}
private Object prepareScript(CompiledScript script) {
if (script.isLiteral()) {
return script.execute(null);
}
return script;
}
protected void settingExtraInfo(
JspProcessor processor, Hashtable seed) {
TagExtraInfo tei =
(TagExtraInfo) ObjectUtil.newInstance(getExtraInfoClass());
boolean hasNestedVariable = existsNestedVariable(tei, seed);
boolean hasDynamicName = existsDynamicName(seed);
TLDScriptingVariableInfo variableInfo = new TLDScriptingVariableInfo();
variableInfo.setTagExtraInfo(tei);
variableInfo.setNestedVariable(hasNestedVariable);
variableInfo.setDynamicName(hasDynamicName);
if (hasNestedVariable) {
ScriptableTagData tagData = new ScriptableTagData(seed);
if (hasDynamicName) {
variableInfo.setTagData(tagData);
} else {
variableInfo.setVariableInfos(tei.getVariableInfo(tagData));
}
}
processor.setTLDScriptingVariableInfo(variableInfo);
}
protected boolean existsNestedVariable(
TagExtraInfo tei, Hashtable seed) {
VariableInfo[] dummy = tei.getVariableInfo(new DummyTagData(seed));
if (dummy != null) {
for (int i = 0; i < dummy.length; i++) {
if (dummy[i].getScope() == VariableInfo.NESTED) {
return true;
}
}
}
return false;
}
protected boolean existsDynamicName(Hashtable seed) {
Enumeration keys = seed.keys();
while (keys.hasMoreElements()) {
if (seed.get(keys.nextElement()) instanceof CompiledScript) {
return true;
}
}
return false;
}
protected static class DummyTagData extends TagData {
public DummyTagData(Hashtable seed) {
super(seed);
}
public Object getAttribute(String attName) {
return attName;
}
public String getAttributeString(String attName) {
return attName;
}
}
protected static class ScriptableTagData extends TagData {
public ScriptableTagData(Hashtable seed) {
super(seed);
}
public boolean isDynamicAttribute(String attName) {
return (super.getAttribute(attName) instanceof CompiledScript);
}
public Object getAttribute(String attName) {
Object value = super.getAttribute(attName);
if (value instanceof CompiledScript) {
return ((CompiledScript) value).execute(null);
}
return value;
}
public String getAttributeString(String attName) {
Object value = getAttribute(attName);
if (value != null) {
return String.valueOf(value);
}
return (String) value;
}
}
}