package railo.runtime.tag;
import java.io.IOException;
import javax.xml.parsers.FactoryConfigurationError;
import railo.runtime.converter.ConverterException;
import railo.runtime.converter.JSConverter;
import railo.runtime.converter.WDDXConverter;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.TagImpl;
import railo.runtime.op.Caster;
/**
* Serializes and de-serializes CFML data structures to the XML-based WDDX format.
* Generates JavaScript statements to instantiate JavaScript objects equivalent to the contents of a
* WDDX packet or some CFML data structures.
*
*
*
**/
public final class Wddx extends TagImpl {
/** The value to be processed. */
private Object input;
/** Specifies the action taken by the cfwddx tag. */
private String action;
/** The name of the variable to hold the output of the operation. This attribute is required for
** action = 'WDDX2CFML'. For all other actions, if this attribute is not provided, the result of the
** WDDX processing is outputted in the HTML stream. */
private String output;
private boolean validate;
/** The name of the top-level JavaScript object created by the deserialization process. The object
** created is an instance of the WddxRecordset object, explained in WddxRecordset Object. */
private String toplevelvariable;
/** Indicates whether to output time-zone information when serializing CFML to WDDX. If time-zone
** information is taken into account, the hour-minute offset, as represented in the ISO8601 format, is
** calculated in the date-time output. If time-zone information is not taken into account, the local
** time is output. The default is Yes. */
private boolean usetimezoneinfo;
private boolean xmlConform;
@Override
public void release() {
super.release();
input=null;
action=null;
output=null;
validate=false;
toplevelvariable=null;
usetimezoneinfo=false;
xmlConform=false;
}
/** set the value input
* The value to be processed.
* @param input value to set
**/
public void setInput(Object input) {
this.input=input;
}
/** set the value action
* Specifies the action taken by the cfwddx tag.
* @param action value to set
**/
public void setAction(String action) {
this.action=action.toLowerCase();
}
/** set the value output
* The name of the variable to hold the output of the operation. This attribute is required for
* action = 'WDDX2CFML'. For all other actions, if this attribute is not provided, the result of the
* WDDX processing is outputted in the HTML stream.
* @param output value to set
**/
public void setOutput(String output) {
this.output=output;
}
/** set the value validate
*
* @param validate value to set
**/
public void setValidate(boolean validate) {
this.validate=validate;
}
/** set the value toplevelvariable
* The name of the top-level JavaScript object created by the deserialization process. The object
* created is an instance of the WddxRecordset object, explained in WddxRecordset Object.
* @param toplevelvariable value to set
**/
public void setToplevelvariable(String toplevelvariable) {
this.toplevelvariable=toplevelvariable;
}
/** set the value usetimezoneinfo
* Indicates whether to output time-zone information when serializing CFML to WDDX. If time-zone
* information is taken into account, the hour-minute offset, as represented in the ISO8601 format, is
* calculated in the date-time output. If time-zone information is not taken into account, the local
* time is output. The default is Yes.
* @param usetimezoneinfo value to set
**/
public void setUsetimezoneinfo(boolean usetimezoneinfo) {
this.usetimezoneinfo=usetimezoneinfo;
}
/**
* sets if generated code is xml or wddx conform
* @param xmlConform
*/
public void setXmlconform(boolean xmlConform) {
this.xmlConform=xmlConform;
}
@Override
public int doStartTag() throws PageException {
try {
doIt();
} catch (Exception e) {
throw Caster.toPageException(e);
}
return SKIP_BODY;
}
private void doIt() throws ExpressionException, PageException, ConverterException, IOException, FactoryConfigurationError {
// cfml > wddx
if(action.equals("cfml2wddx")) {
if(output!=null) pageContext.setVariable(output,cfml2wddx(input));
else pageContext.forceWrite(cfml2wddx(input));
}
// wddx > cfml
else if(action.equals("wddx2cfml")) {
if(output==null) throw new ApplicationException("at tag cfwddx the attribute output is required if you set action==wddx2cfml");
pageContext.setVariable(output,wddx2cfml(Caster.toString(input)));
}
// cfml > js
else if(action.equals("cfml2js")) {
if(output!=null) pageContext.setVariable(output,cfml2js(input));
else pageContext.forceWrite(cfml2js(input));
}
// wddx > js
else if(action.equals("wddx2js")) {
if(output!=null) pageContext.setVariable(output,wddx2js(Caster.toString(input)));
else pageContext.forceWrite(wddx2js(Caster.toString(input)));
}
else throw new ExpressionException("invalid attribute action for tag cfwddx, attributes are [cfml2wddx, wddx2cfml,cfml2js, wddx2js].");
}
private String cfml2wddx(Object input) throws ConverterException {
WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),xmlConform,true);
if(!usetimezoneinfo)converter.setTimeZone(null);
return converter.serialize(input);
}
private Object wddx2cfml(String input) throws ConverterException, IOException, FactoryConfigurationError {
WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),xmlConform,true);
converter.setTimeZone(pageContext.getTimeZone());
return converter.deserialize(input,validate);
}
private String cfml2js(Object input) throws ConverterException {
if(toplevelvariable==null)missingTopLevelVariable();
JSConverter converter =new JSConverter();
return converter.serialize(input,toplevelvariable);
}
private String wddx2js(String input) throws ConverterException, IOException, FactoryConfigurationError {
if(toplevelvariable==null)missingTopLevelVariable();
JSConverter converter =new JSConverter();
return converter.serialize(wddx2cfml(input),toplevelvariable);
}
private ApplicationException missingTopLevelVariable() {
return new ApplicationException("at tag cfwddx the attribute topLevelVariable is required if you set action equal wddx2js or cfml2js");
}
@Override
public int doEndTag() {
return EVAL_PAGE;
}
}