001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.library.tag; 020 021import java.io.IOException; 022import java.lang.reflect.Method; 023import java.util.ArrayList; 024import java.util.Date; 025import java.util.List; 026 027import lucee.commons.lang.CFTypes; 028import lucee.commons.lang.ClassUtil; 029import lucee.commons.lang.ExceptionUtil; 030import lucee.commons.lang.Md5; 031import lucee.commons.lang.StringUtil; 032import lucee.runtime.op.Caster; 033import lucee.runtime.type.dt.DateTime; 034import lucee.runtime.type.dt.TimeSpan; 035import lucee.runtime.type.util.ListUtil; 036 037 038/** 039 * Die Klasse TagLibTagAttr repraesentiert ein einzelnes Attribute eines Tag 040 * und haelt saemtliche Informationen zu diesem Attribut. 041 */ 042public final class TagLibTagAttr { 043 044 public static final short SCRIPT_SUPPORT_NONE = 0; 045 public static final short SCRIPT_SUPPORT_OPTIONAL = 1; 046 public static final short SCRIPT_SUPPORT_REQUIRED = 2; 047 048 private String name="noname"; 049 private String[] alias=null; 050 051 052 053 private String type; 054 private String description=""; 055 private boolean required; 056 private boolean rtexpr=true; 057 private Object defaultValue; 058 private TagLibTag tag; 059 private boolean hidden; 060 private boolean _default; 061 private boolean noname; 062 private short status=TagLib.STATUS_IMPLEMENTED; 063 private short scriptSupport=SCRIPT_SUPPORT_NONE; 064 private String valueList; 065 private char delimiter=','; 066 private Object[] values; 067 068 069 public TagLibTagAttr duplicate(TagLibTag tag) { 070 TagLibTagAttr tlta=new TagLibTagAttr(tag); 071 tlta.name=name; 072 tlta.alias=alias; 073 tlta.type=type; 074 tlta.description=description; 075 tlta.required=required; 076 tlta.rtexpr=rtexpr; 077 tlta.defaultValue=defaultValue; 078 tlta.hidden=hidden; 079 tlta.valueList=valueList; 080 tlta.values=values; 081 tlta.delimiter=delimiter; 082 tlta.noname=noname; 083 tlta._default=_default; 084 tlta.status=status; 085 086 087 return tlta; 088 } 089 090 091 /** 092 * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 093 */ 094 public short getStatus() { 095 return status; 096 } 097 098 099 /** 100 * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 101 */ 102 public void setStatus(short status) { 103 this.status = status; 104 } 105 106 /** 107 * Geschuetzer Konstruktor ohne Argumente. 108 */ 109 public TagLibTagAttr(TagLibTag tag) { 110 this.tag=tag; 111 } 112 113 /** 114 * Gibt den Namen des Attribut zurueck. 115 * @return Name des Attribut. 116 */ 117 public String getName() { 118 return name; 119 } 120 121 122 public TagLibTag getTag() { 123 return tag; 124 } 125 126 public String[] getAlias() { 127 return alias; 128 } 129 130 131 public void setAlias(String strAlias) { 132 this.alias = lucee.runtime.type.util.ListUtil.trimItems(lucee.runtime.type.util.ListUtil.listToStringArray(strAlias.toLowerCase(),',')); 133 } 134 135 /** 136 * Gibt zurueck, ob das Attribut Pflicht ist oder nicht. 137 * @return Ist das Attribut Pflicht. 138 */ 139 public boolean isRequired() { 140 return required; 141 } 142 143 /** 144 * Gibt den Typ des Attribut zurueck (query, struct, string usw.) 145 * @return Typ des Attribut 146 */ 147 public String getType() { 148 if(this.type==null) { 149 try { 150 String methodName="set"+ 151 (name.length()>0?""+Character.toUpperCase(name.charAt(0)):"")+ 152 (name.length()>1?name.substring(1):""); 153 154 Class clazz= ClassUtil.loadClass(tag.getTagClassName(),(Class)null);//Class.orName(tag.getTagClassName()); 155 if(clazz!=null) { 156 Method[] methods = clazz.getMethods(); 157 for(int i=0;i<methods.length;i++) { 158 Method method = methods[i]; 159 if(method.getName().equalsIgnoreCase(methodName)) { 160 Class[] types = method.getParameterTypes(); 161 if(types.length==1) { 162 Class type=types[0]; 163 if(type==String.class)this.type="string"; 164 else if(type==double.class)this.type="number"; 165 else if(type==Date.class)this.type="datetime"; 166 else this.type=type.getName(); 167 } 168 } 169 } 170 } 171 } 172 catch(Throwable t) { 173 ExceptionUtil.rethrowIfNecessary(t); 174 return "string"; 175 } 176 } 177 return this.type; 178 } 179 180 /** 181 * Gibt zurueck ob das Attribute eines Tag, mithilfe des ExprTransformer, uebersetzt werden soll oder nicht. 182 * @return Soll das Attribut uebbersetzt werden 183 */ 184 public boolean getRtexpr() { 185 return rtexpr; 186 } 187 188 /** 189 * Setzt den Namen des Attribut. 190 * @param name Name des Attribut. 191 */ 192 public void setName(String name) { 193 this.name = name.toLowerCase(); 194 } 195 196 /** 197 * Setzt, ob das Argument Pflicht ist oder nicht. 198 * @param required Ist das Attribut Pflicht. 199 */ 200 public void setRequired(boolean required) { 201 this.required = required; 202 } 203 204 /** 205 * Setzt, ob das Attribute eines Tag, mithilfe des ExprTransformer, uebersetzt werden soll oder nicht. 206 * @param rtexpr Soll das Attribut uebbersetzt werden 207 */ 208 public void setRtexpr(boolean rtexpr) { 209 this.rtexpr = rtexpr; 210 } 211 212 /** 213 * Setzt, den Typ des Attribut (query, struct, string usw.) 214 * @param type Typ des Attribut. 215 */ 216 public void setType(String type) { 217 this.type = type; 218 } 219 220 /** 221 * @return Returns the description. 222 */ 223 public String getDescription() { 224 return description; 225 } 226 227 /** 228 * @param description The description to set. 229 */ 230 public void setDescription(String description) { 231 this.description = description; 232 } 233 234 /** 235 * @param defaultValue 236 */ 237 public void setDefaultValue(Object defaultValue) { 238 this.defaultValue=defaultValue; 239 tag.setHasDefaultValue(true); 240 } 241 242 /** 243 * @return Returns the defaultValue. 244 */ 245 public Object getDefaultValue() { 246 return defaultValue; 247 } 248 249 /** 250 * @return 251 */ 252 public boolean hasDefaultValue() { 253 return defaultValue!=null; 254 } 255 256 public void setHidden(boolean hidden) { 257 this.hidden=hidden; 258 } 259 public boolean getHidden() { 260 return hidden; 261 } 262 263 public void setNoname(boolean noname) { 264 this.noname=noname; 265 } 266 public boolean getNoname() { 267 return noname; 268 } 269 270 public String getHash() { 271 StringBuffer sb=new StringBuffer(); 272 sb.append(this.getDefaultValue()); 273 sb.append(this.getName()); 274 sb.append(this.getRtexpr()); 275 sb.append(this.getType()); 276 277 try { 278 return Md5.getDigestAsString(sb.toString()); 279 } catch (IOException e) { 280 return ""; 281 } 282 } 283 284 public void isDefault(boolean _default) { 285 if(_default) 286 tag.setDefaultAttribute(this); 287 this._default=_default; 288 } 289 290 public boolean isDefault() { 291 return _default; 292 } 293 294 295 public void setScriptSupport(String str) { 296 if(!StringUtil.isEmpty(str)) { 297 str=str.trim().toLowerCase(); 298 if("optional".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_OPTIONAL; 299 else if("opt".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_OPTIONAL; 300 else if("required".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_REQUIRED; 301 else if("req".equals(str)) this.scriptSupport=SCRIPT_SUPPORT_REQUIRED; 302 } 303 } 304 305 306 /** 307 * @return the scriptSupport 308 */ 309 public short getScriptSupport() { 310 return scriptSupport; 311 } 312 313 314 public Object getScriptSupportAsString() { 315 if(scriptSupport==SCRIPT_SUPPORT_OPTIONAL) return "optional"; 316 if(scriptSupport==SCRIPT_SUPPORT_REQUIRED) return "required"; 317 return "none"; 318 } 319 320 321 public void setValueDelimiter(String delimiter) { 322 if(StringUtil.isEmpty(delimiter,true)) return; 323 this.delimiter=delimiter.trim().charAt(0); 324 } 325 326 public void setValues(String valueList) { 327 if(tag.getName().equalsIgnoreCase("pop")) 328 if(StringUtil.isEmpty(valueList,true)) return; 329 this.valueList=valueList; 330 } 331 332 public Object[] getValues() { 333 if(valueList==null) return null; 334 if(values!=null) return values; 335 String[] res = ListUtil.trimItems(ListUtil.listToStringArray(valueList, delimiter)); 336 short type=CFTypes.toShort(getType(), false, CFTypes.TYPE_ANY); 337 // String 338 if(type==CFTypes.TYPE_STRING || type==CFTypes.TYPE_ANY) { 339 values=res; 340 } 341 // Numeric 342 else if(type==CFTypes.TYPE_NUMERIC) { 343 List<Double> list=new ArrayList<Double>(); 344 Double d; 345 for(int i=0;i<res.length;i++){ 346 d=Caster.toDouble(res[i],null); 347 if(d!=null)list.add(d); 348 } 349 values=list.toArray(new Double[list.size()]); 350 } 351 // Boolean 352 else if(type==CFTypes.TYPE_BOOLEAN) { 353 List<Boolean> list=new ArrayList<Boolean>(); 354 Boolean b; 355 for(int i=0;i<res.length;i++){ 356 b=Caster.toBoolean(res[i],null); 357 if(b!=null)list.add(b); 358 } 359 values=list.toArray(new Boolean[list.size()]); 360 } 361 // DateTime 362 else if(type==CFTypes.TYPE_DATETIME) { 363 List<DateTime> list=new ArrayList<DateTime>(); 364 DateTime dt; 365 for(int i=0;i<res.length;i++){ 366 dt=Caster.toDate(res[i],true,null,null); 367 if(dt!=null)list.add(dt); 368 } 369 values=list.toArray(new DateTime[list.size()]); 370 } 371 // Timespan 372 else if(type==CFTypes.TYPE_TIMESPAN) { 373 List<TimeSpan> list=new ArrayList<TimeSpan>(); 374 TimeSpan ts; 375 for(int i=0;i<res.length;i++){ 376 ts=Caster.toTimespan(res[i],null); 377 if(ts!=null)list.add(ts); 378 } 379 values=list.toArray(new TimeSpan[list.size()]); 380 } 381 382 // TODO add support for other types ? 383 else { 384 valueList=null; 385 } 386 return values; 387 388 } 389 390 391 392}