package railo.runtime.tag;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.servlet.jsp.tagext.Tag;
import railo.commons.lang.HTMLEntities;
import railo.commons.lang.StringUtil;
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;
import railo.runtime.op.Decision;
import railo.runtime.type.Array;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.util.KeyConstants;
import railo.runtime.type.util.ListUtil;
// FUTURE tag input
//attr validateAt impl tag atrr
//attr validate add support for submitOnce
// Added support for generating Flash and XML controls (specified in the cfform tag).
// Added support for preventing multiple submissions.
// attr mask impl. logik dahinter umsetzen
/**
*
*/
public class Input extends TagImpl {
public static final short TYPE_SELECT=-1;
public static final short TYPE_TEXT=0;
public static final short TYPE_RADIO=1;
public static final short TYPE_CHECKBOX=2;
public static final short TYPE_PASSWORD=3;
public static final short TYPE_BUTTON=4;
public static final short TYPE_FILE=5;
public static final short TYPE_HIDDEN=6;
public static final short TYPE_IMAGE=7;
public static final short TYPE_RESET=8;
public static final short TYPE_SUBMIT=9;
public static final short TYPE_DATEFIELD=10;
public static final short VALIDATE_DATE=4;
public static final short VALIDATE_EURODATE=5;
public static final short VALIDATE_TIME=6;
public static final short VALIDATE_FLOAT=7;
public static final short VALIDATE_INTEGER=8;
public static final short VALIDATE_TELEPHONE=9;
public static final short VALIDATE_ZIPCODE=10;
public static final short VALIDATE_CREDITCARD=11;
public static final short VALIDATE_SOCIAL_SECURITY_NUMBER=12;
public static final short VALIDATE_REGULAR_EXPRESSION=13;
public static final short VALIDATE_NONE=14;
public static final short VALIDATE_USDATE=15;
public static final short VALIDATE_RANGE=16;
public static final short VALIDATE_BOOLEAN=17;
public static final short VALIDATE_EMAIL=18;
public static final short VALIDATE_URL=19;
public static final short VALIDATE_UUID=20;
public static final short VALIDATE_GUID=21;
public static final short VALIDATE_MAXLENGTH=22;
public static final short VALIDATE_NOBLANKS=23;
// TODO SubmitOnce
/**
* @param validate The validate to set.
* @throws ApplicationException
*/
public void setValidate(String validate) throws ApplicationException {
validate=validate.toLowerCase().trim();
if(validate.equals("creditcard")) input.setValidate(VALIDATE_CREDITCARD);
else if(validate.equals("date")) input.setValidate(VALIDATE_DATE);
else if(validate.equals("usdate")) input.setValidate(VALIDATE_USDATE);
else if(validate.equals("eurodate")) input.setValidate(VALIDATE_EURODATE);
else if(validate.equals("float")) input.setValidate(VALIDATE_FLOAT);
else if(validate.equals("numeric")) input.setValidate(VALIDATE_FLOAT);
else if(validate.equals("integer")) input.setValidate(VALIDATE_INTEGER);
else if(validate.equals("int")) input.setValidate(VALIDATE_INTEGER);
else if(validate.equals("regular_expression")) input.setValidate(VALIDATE_REGULAR_EXPRESSION);
else if(validate.equals("regex")) input.setValidate(VALIDATE_REGULAR_EXPRESSION);
else if(validate.equals("social_security_number"))input.setValidate(VALIDATE_SOCIAL_SECURITY_NUMBER);
else if(validate.equals("ssn")) input.setValidate(VALIDATE_SOCIAL_SECURITY_NUMBER);
else if(validate.equals("telephone")) input.setValidate(VALIDATE_TELEPHONE);
else if(validate.equals("phone")) input.setValidate(VALIDATE_TELEPHONE);
else if(validate.equals("time")) input.setValidate(VALIDATE_TIME);
else if(validate.equals("zipcode")) input.setValidate(VALIDATE_ZIPCODE);
else if(validate.equals("zip")) input.setValidate(VALIDATE_ZIPCODE);
else if(validate.equals("range")) input.setValidate(VALIDATE_RANGE);
else if(validate.equals("boolean")) input.setValidate(VALIDATE_BOOLEAN);
else if(validate.equals("email")) input.setValidate(VALIDATE_EMAIL);
else if(validate.equals("url")) input.setValidate(VALIDATE_URL);
else if(validate.equals("uuid")) input.setValidate(VALIDATE_UUID);
else if(validate.equals("guid")) input.setValidate(VALIDATE_GUID);
else if(validate.equals("maxlength")) input.setValidate(VALIDATE_MAXLENGTH);
else if(validate.equals("noblanks")) input.setValidate(VALIDATE_NOBLANKS);
else throw new ApplicationException("attribute validate has an invalid value ["+validate+"]",
"valid values for attribute validate are [creditcard, date, eurodate, float, integer, regular, social_security_number, telephone, time, zipcode]");
}
public static final String[] DAYNAMES_DEFAULT = new String[]{"S", "M", "T", "W", "Th", "F", "S"};
public static final String[] MONTHNAMES_DEFAULT = new String[]{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
Struct attributes=new StructImpl();
InputBean input=new InputBean();
String passthrough;
String[] daynames=DAYNAMES_DEFAULT;
String[] monthnames=MONTHNAMES_DEFAULT;
boolean enabled=true;
boolean visible=true;
String label;
String tooltip;
String validateAt;
double firstDayOfWeek=0;
String mask;
@Override
public void release() {
super.release();
input=new InputBean();
attributes.clear();
passthrough=null;
daynames=DAYNAMES_DEFAULT;
monthnames=MONTHNAMES_DEFAULT;
enabled=true;
visible=true;
label=null;
tooltip=null;
validateAt=null;
firstDayOfWeek=0;
mask=null;
}
/**
* @param cssclass The cssclass to set.
*/
public void setClass(String cssclass) {
attributes.setEL("class",cssclass);
}
/**
* @param cssstyle The cssstyle to set.
*/
public void setStyle(String cssstyle) {
attributes.setEL("style",cssstyle);
}
/**
* @param id The id to set.
*/
public void setId(String id) {
attributes.setEL("id",id);
}
public void setAccept(String accept) {
attributes.setEL("accept",accept);
}
public void setAccesskey(String accesskey) {
attributes.setEL("accesskey",accesskey);
}
public void setAlign(String align) {
attributes.setEL("align",align);
}
public void setAlt(String alt) {
attributes.setEL("alt",alt);
}
public void setAutocomplete(String autocomplete) {
attributes.setEL("autocomplete",autocomplete);
}
public void setAutofocus(String autofocus) {
attributes.setEL("autofocus",autofocus);
}
public void setBorder(String border) {
attributes.setEL("border",border);
}
public void setDatafld(String datafld) {
attributes.setEL("datafld",datafld);
}
public void setDatasrc(String datasrc) {
attributes.setEL("datasrc",datasrc);
}
public void setForm(String form) {
attributes.setEL("form",form);
}
public void setFormaction(String formAction) {
attributes.setEL("formaction",formAction);
}
public void setFormenctype(String formenctype) {
attributes.setEL("formenctype",formenctype);
}
public void setFormmethod(String formmethod) {
attributes.setEL("formmethod",formmethod);
}
public void setFormnovalidate(String formnovalidate) {
attributes.setEL("formnovalidate",formnovalidate);
}
public void setFormtarget(String formtarget) {
attributes.setEL("formtarget",formtarget);
}
public void setLang(String lang) {
attributes.setEL("lang",lang);
}
public void setList(String list) {
attributes.setEL("list",list);
}
public void setDir(String dir) {
//dir=dir.trim();
//String lcDir=dir.toLowerCase();
//if( "ltr".equals(lcDir) || "rtl".equals(lcDir))
attributes.setEL("dir",dir);
//else throw new ApplicationException("attribute dir for tag input has an invalid value ["+dir+"], valid values are [ltr, rtl]");
}
public void setDataformatas(String dataformatas) {
dataformatas=dataformatas.trim();
//String lcDataformatas=dataformatas.toLowerCase();
//if( "plaintext".equals(lcDataformatas) || "html".equals(lcDataformatas))
attributes.setEL("dataformatas",dataformatas);
//else throw new ApplicationException("attribute dataformatas for tag input has an invalid value ["+dataformatas+"], valid values are [plaintext, html");
}
public void setDisabled(String disabled) {
// alles ausser false ist true
//if(Caster.toBooleanValue(disabled,true))
attributes.setEL("disabled",disabled);
}
public void setEnabled(String enabled) {
// alles ausser false ist true
//setDisabled(Caster.toString(!Caster.toBooleanValue(enabled,true)));
attributes.setEL("enabled",enabled);
}
public void setIsmap(String ismap) {
// alles ausser false ist true
//if(Caster.toBooleanValue(ismap,true)) attributes.setEL("ismap","ismap");
attributes.setEL("ismap",ismap);
}
public void setReadonly(String readonly) {
// alles ausser false ist true
//if(Caster.toBooleanValue(readonly,true)) attributes.setEL("readonly","readonly");
attributes.setEL("readonly",readonly);
}
public void setUsemap(String usemap) {
attributes.setEL("usemap",usemap);
}
/**
* @param onBlur The onBlur to set.
*/
public void setOnblur(String onBlur) {
attributes.setEL("onblur",onBlur);
}
/**
* @param onChange The onChange to set.
*/
public void setOnchange(String onChange) {
attributes.setEL("onchange",onChange);
}
/**
* @param onClick The onClick to set.
*/
public void setOnclick(String onClick) {
attributes.setEL("onclick",onClick);
}
/**
* @param onDblclick The onDblclick to set.
*/
public void setOndblclick(String onDblclick) {
attributes.setEL("ondblclick",onDblclick);
}
/**
* @param onFocus The onFocus to set.
*/
public void setOnfocus(String onFocus) {
attributes.setEL("onfocus",onFocus);
}
/**
* @param onKeyDown The onKeyDown to set.
*/
public void setOnkeydown(String onKeyDown) {
attributes.setEL("onkeydown",onKeyDown);
}
/**
* @param onKeyPress The onKeyPress to set.
*/
public void setOnkeypress(String onKeyPress) {
attributes.setEL("onkeypress",onKeyPress);
}
/**
* @param onKeyUp The onKeyUp to set.
*/
public void setOnkeyup(String onKeyUp) {
attributes.setEL("onKeyUp",onKeyUp);
}
/**
* @param onMouseDown The onMouseDown to set.
*/
public void setOnmousedown(String onMouseDown) {
attributes.setEL("onMouseDown",onMouseDown);
}
/**
* @param onMouseMove The onMouseMove to set.
*/
public void setOnmousemove(String onMouseMove) {
attributes.setEL("onMouseMove",onMouseMove);
}
/**
* @param onMouseUp The onMouseUp to set.
*/
public void setOnmouseup(String onMouseUp) {
attributes.setEL("onMouseUp",onMouseUp);
}
/**
* @param onMouseUp The onMouseUp to set.
*/
public void setOnselect(String onselect) {
attributes.setEL("onselect",onselect);
}
/**
* @param onMouseOut The onMouseOut to set.
*/
public void setOnmouseout(String onMouseOut) {
attributes.setEL("onMouseOut",onMouseOut);
}
/**
* @param onMouseOver The onKeyPress to set.
*/
public void setOnmouseover(String onMouseOver) {
attributes.setEL("onMouseOver",onMouseOver);
}
/**
* @param tabIndex The tabIndex to set.
*/
public void setTabindex(String tabIndex) {
attributes.setEL("tabindex",tabIndex);
}
/**
* @param title The title to set.
*/
public void setTitle(String title) {
attributes.setEL("title",title);
}
/**
* @param value The value to set.
*/
public void setValue(String value) {
attributes.setEL("value",value);
}
/**
* @param size The size to set.
*/
public void setSize(String size) {
attributes.setEL("size",size);
}
/**
* @param maxLength The maxLength to set.
*/
public void setMaxlength(double maxLength) {
input.setMaxLength((int)maxLength);
attributes.setEL("maxLength",Caster.toString(maxLength));
}
/**
* @param checked The checked to set.
*/
public void setChecked(String checked) {
// alles ausser false ist true
if(Caster.toBooleanValue(checked,true)) attributes.setEL("checked","checked");
}
/**
* @param daynames The daynames to set.
* @throws ApplicationException
*/
public void setDaynames(String listDaynames) throws ApplicationException {
String[] arr = ListUtil.listToStringArray(listDaynames, ',');
if(arr.length==7)
throw new ApplicationException("value of attribute [daynames] must contain a string list with 7 values, now there are "+arr.length+" values");
this.daynames=arr;
}
/**
* @param daynames The daynames to set.
* @throws ApplicationException
*/
public void setFirstdayofweek(double firstDayOfWeek) throws ApplicationException {
if(firstDayOfWeek<0 || firstDayOfWeek>6)
throw new ApplicationException("value of attribute [firstDayOfWeek] must conatin a numeric value between 0-6");
this.firstDayOfWeek=firstDayOfWeek;
}
/**
* @param daynames The daynames to set.
* @throws ApplicationException
*/
public void setMonthnames(String listMonthNames) throws ApplicationException {
String[] arr = ListUtil.listToStringArray(listMonthNames, ',');
if(arr.length==12)
throw new ApplicationException("value of attribute [MonthNames] must contain a string list with 12 values, now there are "+arr.length+" values");
this.monthnames=arr;
}
/**
* @param daynames The daynames to set.
*/
public void setLabel(String label) {
this.label=label;
}
/**
* @param daynames The daynames to set.
*/
public void setMask(String mask) {
this.mask=mask;
}
public void setMax(String max) {
attributes.setEL("max",max);
}
public void setMin(String min) {
attributes.setEL("min",min);
}
public void setMultiple(String multiple) {
attributes.setEL("multiple",multiple);
}
public void setPlaceholder(String placeholder) {
attributes.setEL("placeholder",placeholder);
}
/**
* @param daynames The daynames to set.
*/
public void setNotab(String notab) {
attributes.setEL("notab",notab);
}
/**
* @param daynames The daynames to set.
*/
public void setHspace(String hspace) {
attributes.setEL("hspace",hspace);
}
/**
* @param type The type to set.
* @throws ApplicationException
*/
public void setType(String type) throws ApplicationException {
type=type.toLowerCase().trim();
if( "checkbox".equals(type)) input.setType(TYPE_CHECKBOX);
else if("password".equals(type)) input.setType(TYPE_PASSWORD);
else if("text".equals(type)) input.setType(TYPE_TEXT);
else if("radio".equals(type)) input.setType(TYPE_RADIO);
else if("button".equals(type)) input.setType(TYPE_BUTTON);
else if("file".equals(type)) input.setType(TYPE_FILE);
else if("hidden".equals(type)) input.setType(TYPE_HIDDEN);
else if("image".equals(type)) input.setType(TYPE_IMAGE);
else if("reset".equals(type)) input.setType(TYPE_RESET);
else if("submit".equals(type)) input.setType(TYPE_SUBMIT);
else if("datefield".equals(type)) input.setType(TYPE_DATEFIELD);
else throw new ApplicationException("attribute type has an invalid value ["+type+"]","valid values for attribute type are " +
"[checkbox, password, text, radio, button, file, hidden, image, reset, submit, datefield]");
attributes.setEL("type",type);
}
/**
* @param onError The onError to set.
*/
public void setOnerror(String onError) {
input.setOnError(onError);
}
/**
* @param onValidate The onValidate to set.
*/
public void setOnvalidate(String onValidate) {
input.setOnValidate(onValidate);
}
/**
* @param passthrough The passThrough to set.
* @throws PageException
*/
public void setPassthrough(Object passthrough) throws PageException {
if(passthrough instanceof Struct) {
Struct sct = (Struct) passthrough;
Iterator<Entry<Key, Object>> it = sct.entryIterator();
Entry<Key, Object> e;
while(it.hasNext()) {
e=it.next();
attributes.setEL(e.getKey(),e.getValue());
}
}
else this.passthrough = Caster.toString(passthrough);
//input.setPassThrough(passThrough);
}
/**
* @param pattern The pattern to set.
* @throws ExpressionException
*/
public void setPattern(String pattern) throws ExpressionException {
input.setPattern(pattern);
}
/**
* @param range The range to set.
* @throws PageException
*/
public void setRange(String range) throws PageException {
String errMessage="attribute range has an invalid value ["+range+"], must be string list with numbers";
String errDetail="Example: [number_from,number_to], [number_from], [number_from,], [,number_to]";
Array arr=ListUtil.listToArray(range,',');
if(arr.size()==1) {
double from=Caster.toDoubleValue(arr.get(1,null),Double.NaN);
if(!Decision.isValid(from))throw new ApplicationException(errMessage,errDetail);
input.setRangeMin(from);
input.setRangeMax(Double.NaN);
}
else if(arr.size()==2) {
String strFrom=arr.get(1,"").toString().trim();
double from=Caster.toDoubleValue(strFrom,Double.NaN);
if(!Decision.isValid(from) && strFrom.length()>0) {
throw new ApplicationException(errMessage,errDetail);
}
input.setRangeMin(from);
String strTo=arr.get(2,"").toString().trim();
double to=Caster.toDoubleValue(strTo,Double.NaN);
if(!Decision.isValid(to) && strTo.length()>0) {
throw new ApplicationException(errMessage,errDetail);
}
input.setRangeMax(to);
}
else throw new ApplicationException(errMessage,errDetail);
}
/**
* @param required The required to set.
*/
public void setRequired(boolean required) {
input.setRequired(required);
}
/**
* @param name The name to set.
*/
public void setName(String name) {
attributes.setEL(KeyConstants._name,name);
input.setName(name);
}
/**
* @param message The message to set.
*/
public void setMessage(String message) {
if(!StringUtil.isEmpty(message))input.setMessage(message);
}
@Override
public int doEndTag() throws PageException {
try {
_doEndTag();
}
catch (IOException e) {
throw Caster.toPageException(e);
}
return EVAL_PAGE;
}
private void _doEndTag() throws PageException, IOException {
// check attributes
if(input.getValidate()==VALIDATE_REGULAR_EXPRESSION && input.getPattern()==null) {
throw new ApplicationException("when validation type regular_expression is seleted, the pattern attribute is required");
}
Tag parent = getParent();
while(parent!=null && !(parent instanceof Form)){
parent=parent.getParent();
}
if(parent instanceof Form) {
Form form = (Form)parent;
form.setInput(input);
if(input.getType()==TYPE_DATEFIELD && form.getFormat()!=Form.FORMAT_FLASH)
throw new ApplicationException("type [datefield] is only allowed if form format is flash");
}
else {
throw new ApplicationException("Tag must be inside a form tag");
}
draw();
}
void draw() throws IOException, PageException {
// start output
pageContext.forceWrite("<input");
//railo.runtime.type.Collection.Key[] keys = attributes.keys();
//railo.runtime.type.Collection.Key key;
Iterator<Entry<Key, Object>> it = attributes.entryIterator();
Entry<Key, Object> e;
while(it.hasNext()) {
e = it.next();
pageContext.forceWrite(" ");
pageContext.forceWrite(e.getKey().getString());
pageContext.forceWrite("=\"");
pageContext.forceWrite(enc(Caster.toString(e.getValue())));
pageContext.forceWrite("\"");
}
if(passthrough!=null) {
pageContext.forceWrite(" ");
pageContext.forceWrite(passthrough);
}
pageContext.forceWrite(">");
}
/**
* html encode a string
* @param str string to encode
* @return encoded string
*/
String enc(String str) {
return HTMLEntities.escapeHTML(str,HTMLEntities.HTMLV20);
}
/**
* @return the monthnames
*/
public String[] getMonthnames() {
return monthnames;
}
/**
* @param monthnames the monthnames to set
*/
public void setMonthnames(String[] monthnames) {
this.monthnames = monthnames;
}
/**
* @param height the height to set
*/
public void setHeight(String height) {
attributes.setEL("height",height);
}
/**
* @param input the input to set
*/
public void setInput(InputBean input) {
this.input = input;
}
/**
* @param passthrough the passthrough to set
*/
public void setPassthrough(String passthrough) {
this.passthrough = passthrough;
}
/**
* @param tooltip the tooltip to set
* @throws ApplicationException
*/
public void setTooltip(String tooltip) {
this.tooltip = tooltip;
}
/**
* @param validateAt the validateAt to set
* @throws ApplicationException
*/
public void setValidateat(String validateAt) throws ApplicationException {
this.validateAt = validateAt;
throw new ApplicationException("attribute validateAt is not supportrd for tag input ");
}
/**
* @param visible the visible to set
* @throws ApplicationException
*/
public void setVisible(boolean visible) {
this.visible = visible;
}
/**
* @param width the width to set
* @throws ApplicationException
*/
public void setWidth(String width) {
attributes.setEL("width", width);
}
private ExpressionException notSupported(String label) {
return new ExpressionException("attribute ["+label+"] is not supported");
}
public void setAutosuggest(String autosuggest) throws ExpressionException {
throw notSupported("autosuggest");
//attributes.setEL("bind",bind);
}
public void setAutosuggestbinddelay(double autosuggestBindDelay) throws ExpressionException {
throw notSupported("autosuggestBindDelay");
//attributes.setEL("bind",bind);
}
public void setAutosuggestminlength(double autosuggestMinLength) throws ExpressionException {
throw notSupported("autosuggestMinLength");
//attributes.setEL("bind",bind);
}
public void setBind(String bind) throws ExpressionException {
throw notSupported("bind");
//attributes.setEL("bind",bind);
}
public void setBindattribute(String bindAttribute) throws ExpressionException {
throw notSupported("bindAttribute");
//attributes.setEL("bind",bind);
}
public void setBindonload(boolean bindOnLoad) throws ExpressionException {
throw notSupported("bindOnLoad");
//attributes.setEL("bind",bind);
}
public void setDelimiter(String delimiter) throws ExpressionException {
throw notSupported("delimiter");
//attributes.setEL("bind",bind);
}
public void setMaxresultsdisplayed(double maxResultsDisplayed) throws ExpressionException {
throw notSupported("maxResultsDisplayed");
//attributes.setEL("bind",bind);
}
public void setOnbinderror(String onBindError) throws ExpressionException {
throw notSupported("onBindError");
//attributes.setEL("bind",bind);
}
public void setShowautosuggestloadingicon(boolean showAutosuggestLoadingIcon) throws ExpressionException {
throw notSupported("showAutosuggestLoadingIcon");
//attributes.setEL("bind",bind);
}
public void setSourcefortooltip(String sourceForTooltip) throws ExpressionException {
throw notSupported("sourceForTooltip");
//attributes.setEL("bind",bind);
}
public void setSrc(String src) {
attributes.setEL("src",src);
}
public void setStep(String step) {
attributes.setEL("step",step);
}
public void setTypeahead(boolean typeahead) throws ExpressionException {
throw notSupported("typeahead");
//attributes.setEL("src",src);
}
}