package railo.transformer.library.tag;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import railo.commons.lang.CFTypes;
import railo.commons.lang.ClassUtil;
import railo.commons.lang.Md5;
import railo.commons.lang.StringUtil;
import railo.runtime.op.Caster;
import railo.runtime.type.dt.DateTime;
import railo.runtime.type.dt.TimeSpan;
import railo.runtime.type.util.ListUtil;
/**
* Die Klasse TagLibTagAttr repraesentiert ein einzelnes Attribute eines Tag
* und haelt saemtliche Informationen zu diesem Attribut.
*/
public final class TagLibTagAttr {
public static final short SCRIPT_SUPPORT_NONE = 0;
public static final short SCRIPT_SUPPORT_OPTIONAL = 1;
public static final short SCRIPT_SUPPORT_REQUIRED = 2;
private String name="noname";
private String type;
private String description="";
private boolean required;
private boolean rtexpr=true;
private Object defaultValue;
private TagLibTag tag;
private boolean hidden;
private boolean _default;
private boolean noname;
private short status=TagLib.STATUS_IMPLEMENTED;
private short scriptSupport=SCRIPT_SUPPORT_NONE;
private String valueList;
private char delimiter=',';
private Object[] values;
public TagLibTagAttr duplicate(TagLibTag tag) {
TagLibTagAttr tlta=new TagLibTagAttr(tag);
tlta.name=name;
tlta.type=type;
tlta.description=description;
tlta.required=required;
tlta.rtexpr=rtexpr;
tlta.defaultValue=defaultValue;
tlta.hidden=hidden;
tlta.valueList=valueList;
tlta.values=values;
tlta.delimiter=delimiter;
tlta.noname=noname;
tlta._default=_default;
tlta.status=status;
return tlta;
}
/**
* @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED)
*/
public short getStatus() {
return status;
}
/**
* @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED)
*/
public void setStatus(short status) {
this.status = status;
}
/**
* Geschuetzer Konstruktor ohne Argumente.
*/
public TagLibTagAttr(TagLibTag tag) {
this.tag=tag;
}
/**
* Gibt den Namen des Attribut zurueck.
* @return Name des Attribut.
*/
public String getName() {
return name;
}
/**
* Gibt zurueck, ob das Attribut Pflicht ist oder nicht.
* @return Ist das Attribut Pflicht.
*/
public boolean isRequired() {
return required;
}
/**
* Gibt den Typ des Attribut zur�ck (query, struct, string usw.)
* @return Typ des Attribut
*/
public String getType() {
if(this.type==null) {
try {
String methodName= "set"+
(name.length()>0?""+Character.toUpperCase(name.charAt(0)):"")+
(name.length()>1?name.substring(1):"");
Class clazz= ClassUtil.loadClass(tag.getTagClassName(),(Class)null);//Class.orName(tag.getTagClassName());
if(clazz!=null) {
Method[] methods = clazz.getMethods();
for(int i=0;i<methods.length;i++) {
Method method = methods[i];
if(method.getName().equalsIgnoreCase(methodName)) {
Class[] types = method.getParameterTypes();
if(types.length==1) {
Class type=types[0];
if(type==String.class)this.type="string";
else if(type==double.class)this.type="number";
else if(type==Date.class)this.type="datetime";
else this.type=type.getName();
}
}
}
}
}
catch(Throwable t) {
return "string";
}
}
return this.type;
}
/**
* Gibt zurueck ob das Attribute eines Tag, mithilfe des ExprTransformer, uebersetzt werden soll oder nicht.
* @return Soll das Attribut uebbersetzt werden
*/
public boolean getRtexpr() {
return rtexpr;
}
/**
* Setzt den Namen des Attribut.
* @param name Name des Attribut.
*/
public void setName(String name) {
this.name = name.toLowerCase();
}
/**
* Setzt, ob das Argument Pflicht ist oder nicht.
* @param required Ist das Attribut Pflicht.
*/
public void setRequired(boolean required) {
this.required = required;
}
/**
* Setzt, ob das Attribute eines Tag, mithilfe des ExprTransformer, uebersetzt werden soll oder nicht.
* @param rtexpr Soll das Attribut uebbersetzt werden
*/
public void setRtexpr(boolean rtexpr) {
this.rtexpr = rtexpr;
}
/**
* Setzt, den Typ des Attribut (query, struct, string usw.)
* @param type Typ des Attribut.
*/
public void setType(String type) {
this.type = type;
}
/**
* @return Returns the description.
*/
public String getDescription() {
return description;
}
/**
* @param description The description to set.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @param defaultValue
*/
public void setDefaultValue(Object defaultValue) {
this.defaultValue=defaultValue;
tag.setHasDefaultValue(true);
}
/**
* @return Returns the defaultValue.
*/
public Object getDefaultValue() {
return defaultValue;
}
/**
* @return
*/
public boolean hasDefaultValue() {
return defaultValue!=null;
}
public void setHidden(boolean hidden) {
this.hidden=hidden;
}
public boolean getHidden() {
return hidden;
}
public void setNoname(boolean noname) {
this.noname=noname;
}
public boolean getNoname() {
return noname;
}
public String getHash() {
StringBuffer sb=new StringBuffer();
sb.append(this.getDefaultValue());
sb.append(this.getName());
sb.append(this.getRtexpr());
sb.append(this.getType());
try {
return Md5.getDigestAsString(sb.toString());
} catch (IOException e) {
return "";
}
}
public void isDefault(boolean _default) {
if(_default)
tag.setDefaultAttribute(this);
this._default=_default;
}
public boolean isDefault() {
return _default;
}
public void setScriptSupport(String str) {
if(!StringUtil.isEmpty(str)) {
str=str.trim().toLowerCase();
if("optional".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_OPTIONAL;
else if("opt".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_OPTIONAL;
else if("required".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_REQUIRED;
else if("req".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_REQUIRED;
}
}
/**
* @return the scriptSupport
*/
public short getScriptSupport() {
return scriptSupport;
}
public Object getScriptSupportAsString() {
if(scriptSupport==SCRIPT_SUPPORT_OPTIONAL) return "optional";
if(scriptSupport==SCRIPT_SUPPORT_REQUIRED) return "required";
return "none";
}
public void setValueDelimiter(String delimiter) {
if(StringUtil.isEmpty(delimiter,true)) return;
this.delimiter=delimiter.trim().charAt(0);
}
public void setValues(String valueList) {
if(tag.getName().equalsIgnoreCase("pop"))
if(StringUtil.isEmpty(valueList,true)) return;
this.valueList=valueList;
}
public Object[] getValues() {
if(valueList==null) return null;
if(values!=null) return values;
String[] res = ListUtil.trimItems(ListUtil.listToStringArray(valueList, delimiter));
short type=CFTypes.toShort(getType(), false, CFTypes.TYPE_ANY);
// String
if(type==CFTypes.TYPE_STRING || type==CFTypes.TYPE_ANY) {
values=res;
}
// Numeric
else if(type==CFTypes.TYPE_NUMERIC) {
List<Double> list=new ArrayList<Double>();
Double d;
for(int i=0;i<res.length;i++){
d=Caster.toDouble(res[i],null);
if(d!=null)list.add(d);
}
values=list.toArray(new Double[list.size()]);
}
// Boolean
else if(type==CFTypes.TYPE_BOOLEAN) {
List<Boolean> list=new ArrayList<Boolean>();
Boolean b;
for(int i=0;i<res.length;i++){
b=Caster.toBoolean(res[i],null);
if(b!=null)list.add(b);
}
values=list.toArray(new Boolean[list.size()]);
}
// DateTime
else if(type==CFTypes.TYPE_DATETIME) {
List<DateTime> list=new ArrayList<DateTime>();
DateTime dt;
for(int i=0;i<res.length;i++){
dt=Caster.toDate(res[i],true,null,null);
if(dt!=null)list.add(dt);
}
values=list.toArray(new DateTime[list.size()]);
}
// Timespan
else if(type==CFTypes.TYPE_TIMESPAN) {
List<TimeSpan> list=new ArrayList<TimeSpan>();
TimeSpan ts;
for(int i=0;i<res.length;i++){
ts=Caster.toTimespan(res[i],null);
if(ts!=null)list.add(ts);
}
values=list.toArray(new TimeSpan[list.size()]);
}
// TODO add support for other types ?
else {
valueList=null;
}
return values;
}
}