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.Constructor; 023import java.lang.reflect.InvocationTargetException; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.LinkedHashMap; 027import java.util.Map; 028import java.util.Map.Entry; 029 030import lucee.commons.lang.ClassException; 031import lucee.commons.lang.ClassUtil; 032import lucee.commons.lang.ExceptionUtil; 033import lucee.commons.lang.Md5; 034import lucee.commons.lang.StringUtil; 035import lucee.runtime.op.Caster; 036import lucee.runtime.type.util.ArrayUtil; 037import lucee.transformer.bytecode.Position; 038import lucee.transformer.bytecode.cast.CastOther; 039import lucee.transformer.bytecode.expression.Expression; 040import lucee.transformer.bytecode.literal.LitBoolean; 041import lucee.transformer.bytecode.literal.LitDouble; 042import lucee.transformer.bytecode.literal.LitString; 043import lucee.transformer.bytecode.statement.tag.Attribute; 044import lucee.transformer.bytecode.statement.tag.Tag; 045import lucee.transformer.bytecode.statement.tag.TagOther; 046import lucee.transformer.cfml.attributes.AttributeEvaluator; 047import lucee.transformer.cfml.attributes.AttributeEvaluatorException; 048import lucee.transformer.cfml.evaluator.Evaluator; 049import lucee.transformer.cfml.evaluator.EvaluatorException; 050import lucee.transformer.cfml.tag.TagDependentBodyTransformer; 051 052import org.objectweb.asm.Type; 053 054/** 055 * Die Klasse TagLibTag repaesentiert ein einzelne Tag Definition einer TagLib, 056 * beschreibt also alle Informationen die man zum validieren eines Tags braucht. 057 */ 058public final class TagLibTag { 059 060 public final static int ATTRIBUTE_TYPE_FIXED=0; 061 public final static int ATTRIBUTE_TYPE_DYNAMIC=1; 062 public final static int ATTRIBUTE_TYPE_NONAME=3; 063 public final static int ATTRIBUTE_TYPE_MIXED=4; 064 065 066 /** 067 * Definition des Attribut Type 068 */ 069 //public final static int ATTRIBUTE_TYPE_FULLDYNAMIC=2; deprecated 070 /** 071 * Definition des Attribut Type 072 */ 073 074 private final static Class[] CONSTRUCTOR_PARAMS=new Class[]{Position.class,Position.class}; 075 076 private int attributeType; 077 private String name; 078 private boolean hasBody=true; 079 080 private boolean isBodyReq=false; 081 private boolean isTagDependent=false; 082 private boolean bodyFree=true; 083 084 private boolean parseBody; 085 private boolean hasAppendix; 086 private String description=""; 087 private String tagClass; 088 private String tteClass; 089 private String tdbtClass; 090 private int min; 091 private int max; 092 private TagLib tagLib; 093 private Evaluator eval; 094 private TagDependentBodyTransformer tdbt; 095 096 private Map<String,TagLibTagAttr> attributes=new LinkedHashMap<String,TagLibTagAttr>(); 097 private Map<String,String> setters=new HashMap<String,String>(); 098 private TagLibTagAttr attrFirst; 099 private TagLibTagAttr attrLast; 100 101 private String strAttributeEvaluator; 102 private AttributeEvaluator attributeEvaluator; 103 private boolean handleException; 104 private boolean hasDefaultValue=false; 105 private Type tagType; 106 private String tttClass; 107 private Constructor tttConstructor; 108 private boolean allowRemovingLiteral; 109 private TagLibTagAttr defaultAttribute; 110 private short status=TagLib.STATUS_IMPLEMENTED; 111 private Class clazz; 112 private TagLibTagScript script; 113 private final static TagLibTagAttr UNDEFINED=new TagLibTagAttr(null); 114 private TagLibTagAttr singleAttr=UNDEFINED; 115 private Expression attributeDefaultValue; 116 117 public TagLibTag duplicate(boolean cloneAttributes) { 118 TagLibTag tlt = new TagLibTag(tagLib); 119 120 tlt.attributeType=attributeType; 121 tlt.name=name; 122 tlt.hasBody=hasBody; 123 tlt.isBodyReq=isBodyReq; 124 tlt.isTagDependent=isTagDependent; 125 tlt.bodyFree=bodyFree; 126 tlt.parseBody=parseBody; 127 tlt.hasAppendix=hasAppendix; 128 tlt.description=description; 129 tlt.tagClass=tagClass; 130 tlt.tteClass=tteClass; 131 tlt.tdbtClass=tdbtClass; 132 tlt.min=min; 133 tlt.max=max; 134 tlt.strAttributeEvaluator=strAttributeEvaluator; 135 tlt.handleException=handleException; 136 tlt.hasDefaultValue=hasDefaultValue; 137 tlt.tagType=tagType; 138 tlt.tttClass=tttClass; 139 tlt.tttConstructor=tttConstructor; 140 tlt.allowRemovingLiteral=allowRemovingLiteral; 141 tlt.status=status; 142 143 tlt.eval=null; 144 tlt.tdbt=null; 145 tlt.attributeEvaluator=null; 146 147 148 Iterator<Entry<String, TagLibTagAttr>> it = attributes.entrySet().iterator(); 149 if(cloneAttributes) { 150 while(it.hasNext()){ 151 tlt.setAttribute(it.next().getValue().duplicate(tlt)); 152 } 153 if(defaultAttribute!=null)tlt.defaultAttribute=defaultAttribute.duplicate(tlt); 154 } 155 else { 156 while(it.hasNext()){ 157 tlt.setAttribute(it.next().getValue()); 158 tlt.attrFirst=attrFirst; 159 tlt.attrLast=attrLast; 160 } 161 tlt.defaultAttribute=defaultAttribute; 162 } 163 164 165 // setter 166 Iterator<Entry<String, String>> sit = setters.entrySet().iterator(); 167 Entry<String, String> se; 168 while(sit.hasNext()){ 169 se = sit.next(); 170 tlt.setters.put(se.getKey(), se.getValue()); 171 } 172 173 174 175/* 176 private Map attributes=new HashMap(); 177 private TagLibTagAttr attrFirst; 178 private TagLibTagAttr attrLast; 179 180 private Map setters=new HashMap(); 181 private TagLibTagAttr defaultAttribute; 182 */ 183 return tlt; 184 } 185 186 187 /** 188 * Geschuetzer Konstruktor ohne Argumente. 189 * @param tagLib 190 */ 191 public TagLibTag(TagLib tagLib) { 192 this.tagLib=tagLib; 193 } 194 195 /** 196 * Gibt alle Attribute (TagLibTagAttr) eines Tag als HashMap zurueck. 197 * @return HashMap Attribute als HashMap. 198 */ 199 public Map<String,TagLibTagAttr> getAttributes() { 200 return attributes; 201 } 202 203 /** 204 * Gibt ein bestimmtes Attribut anhand seines Namens zurueck, 205 * falls dieses Attribut nicht existiert wird null zurueckgegeben. 206 * @param name Name des Attribut das zurueckgegeben werden soll. 207 * @return Attribute das angfragt wurde oder null. 208 */ 209 public TagLibTagAttr getAttribute(String name) { 210 return getAttribute(name, false); 211 } 212 213 public TagLibTagAttr getAttribute(String name, boolean checkAlias) { 214 TagLibTagAttr attr = attributes.get(name); 215 // checking alias 216 if(attr==null && checkAlias) 217 return getAttributeByAlias(name); 218 return attr; 219 220 } 221 222 223 public TagLibTagAttr getAttributeByAlias(String alias) { 224 Iterator<TagLibTagAttr> it = attributes.values().iterator(); 225 TagLibTagAttr attr; 226 String[] aliases; 227 while(it.hasNext()){ 228 attr = it.next(); 229 if(ArrayUtil.isEmpty(attr.getAlias())) continue; 230 aliases = attr.getAlias(); 231 for(int i=0;i<aliases.length;i++){ 232 if(aliases[i].equalsIgnoreCase(alias)) return attr; 233 } 234 } 235 return null; 236 } 237 238 239 /** 240 * Gibt das erste Attribut, welches innerhalb des Tag definiert wurde, zurueck. 241 * @return Attribut das angfragt wurde oder null. 242 */ 243 public TagLibTagAttr getFirstAttribute() { 244 return attrFirst; 245 } 246 247 /** 248 * Gibt das letzte Attribut, welches innerhalb des Tag definiert wurde, zurueck. 249 * @return Attribut das angfragt wurde oder null. 250 */ 251 public TagLibTagAttr getLastAttribute() { 252 return attrLast; 253 } 254 255 /** 256 * Gibt den Namen des Tag zurueck. 257 * @return String Name des Tag. 258 */ 259 public String getName() { 260 return name; 261 } 262 263 /** 264 * Gibt den kompletten Namen des Tag zurueck, inkl. Name-Space und Trenner. 265 * @return String Kompletter Name des Tag. 266 */ 267 public String getFullName() { 268 String fullName; 269 if(tagLib!=null) { 270 fullName=tagLib.getNameSpaceAndSeparator()+name; 271 } 272 else { 273 fullName=name; 274 } 275 return fullName; 276 } 277 278 /** 279 * Gibt die Klassendefinition, welche diesen Tag implementiert, als Zeichenkette zurueck. 280 * Achtung: Die implementierende Klasse ist keine Java Klasse. 281 * @return String Zeichenkette der Klassendefinition. 282 */ 283 public String getTagClassName() { 284 return tagClass; 285 } 286 287 288 public Class getClazz() throws ClassException { 289 if(clazz==null) { 290 clazz=ClassUtil.loadClass(tagClass); 291 } 292 return clazz; 293 } 294 295 296 public Type getTagType() throws ClassException { 297 if(tagType==null) { 298 tagType=Type.getType(getClazz()); 299 } 300 return tagType; 301 } 302 /** 303 * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 304 */ 305 public short getStatus() { 306 return status; 307 } 308 309 310 /** 311 * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 312 */ 313 public void setStatus(short status) { 314 this.status = status; 315 } 316 317 /** 318 * Gibt die Klassendefinition, der Klasse die den Evaluator (Translation Time Evaluator) implementiert, 319 * als Zeichenkette zurueck. 320 * Falls kein Evaluator definiert ist wird null zurueckgegeben. 321 * @return String Zeichenkette der Klassendefinition. 322 */ 323 public String getTteClassName() { 324 return tteClass; 325 } 326 327 public String getTttClassName() { 328 return tttClass; 329 } 330 331 /** 332 * Gibt den Evaluator (Translation Time Evaluator) dieser Klasse zurueck. 333 * Falls kein Evaluator definiert ist, wird null zurueckgegeben. 334 * @return Implementation des Evaluator zu dieser Klasse. 335 * @throws EvaluatorException Falls die Evaluator-Klasse nicht geladen werden kann. 336 */ 337 public Evaluator getEvaluator() throws EvaluatorException { 338 if(!hasTteClass()) return null; 339 if(eval!=null) return eval; 340 try { 341 eval = (Evaluator) ClassUtil.loadInstance(tteClass); 342 } 343 catch (ClassException e) { 344 throw new EvaluatorException(e.getMessage()); 345 } 346 return eval; 347 } 348 349 /** 350 * Gibt den TagDependentBodyTransformer dieser Klasse zurueck. 351 * Falls kein TagDependentBodyTransformer definiert ist, wird null zurueckgegeben. 352 * @return Implementation des TagDependentBodyTransformer zu dieser Klasse. 353 * @throws TagLibException Falls die TagDependentBodyTransformer-Klasse nicht geladen werden kann. 354 */ 355 public TagDependentBodyTransformer getBodyTransformer() throws TagLibException { 356 if(!hasTdbtClass()) return null; 357 if(tdbt!=null) return tdbt; 358 try { 359 tdbt = (TagDependentBodyTransformer) ClassUtil.loadInstance(tdbtClass); 360 } catch (ClassException e) { 361 throw new TagLibException(e); 362 } 363 return tdbt; 364 } 365 366 /** 367 * Gibt zurueck ob Exception durch die implementierte Klasse abgehandelt werden oder nicht 368 * @return Wird eine Exception abgehandelt? 369 */ 370 public boolean handleException() { 371 return handleException; 372 } 373 374 /** 375 * Gibt zurueck, ob eine Klassendefinition 376 * der Klasse die den Evaluator (Translation Time Evaluator) implementiert existiert. 377 * @return Ob eine Evaluator definiert ist. 378 */ 379 public boolean hasTteClass() { 380 return tteClass !=null && tteClass.length()>0; 381 } 382 383 /** 384 * Gibt zurueck, ob eine Klassendefinition 385 * der Klasse die den TagDependentBodyTransformer implementiert existiert. 386 * @return Ob eine Evaluator definiert ist. 387 */ 388 public boolean hasTdbtClass() { 389 return tdbtClass !=null && tdbtClass.length()>0; 390 } 391 392 /** 393 * Gibt den Attributetyp der Klasse zurueck. 394 * ( ATTRIBUTE_TYPE_FIX, ATTRIBUTE_TYPE_DYNAMIC, ATTRIBUTE_TYPE_NONAME) 395 * @return int 396 */ 397 public int getAttributeType() { 398 return attributeType; 399 } 400 401 /** 402 * Gibt zurueck, ob das Tag einen Body haben kann oder nicht. 403 * @return Kann das Tag einen Body haben. 404 */ 405 public boolean getHasBody() { 406 return hasBody; 407 } 408 409 /** 410 * Gibt die maximale Anzahl Attribute zurueck, die das Tag haben kann. 411 * @return Maximale moegliche Anzahl Attribute. 412 */ 413 public int getMax() { 414 return max; 415 } 416 417 /** 418 * Gibt die minimale Anzahl Attribute zurueck, die das Tag haben muss. 419 * @return Minimal moegliche Anzahl Attribute. 420 */ 421 public int getMin() { 422 return min; 423 } 424 425 /** 426 * Gibt die TagLib zurueck zu der das Tag gehoert. 427 * @return TagLib Zugehoerige TagLib. 428 */ 429 public TagLib getTagLib() { 430 return tagLib; 431 } 432 433 /** 434 * Gibt zurueck ob das Tag seinen Body parsen soll oder nicht. 435 * @return Soll der Body geparst werden. 436 */ 437 public boolean getParseBody() { 438 return parseBody; 439 } 440 441 /** 442 * Gibt zurueck, ob das Tag einen Appendix besitzen kann oder nicht. 443 * @return Kann das Tag einen Appendix besitzen. 444 */ 445 public boolean hasAppendix() { 446 return hasAppendix; 447 } 448 449 /** 450 * Fragt ab ob der Body eines Tag freiwillig ist oder nicht. 451 * @return is required 452 */ 453 public boolean isBodyReq() { 454 return isBodyReq; 455 } 456 457 /** 458 * Fragt ab ob die verarbeitung des Inhaltes eines Tag mit einem eigenen Transformer 459 * vorgenommen werden soll. 460 * @return Fragt ab ob die verarbeitung des Inhaltes eines Tag mit einem eigenen Transformer 461 * vorgenommen werden soll. 462 */ 463 public boolean isTagDependent() { 464 return isTagDependent; 465 } 466 467 /** 468 * Setzt die TagLib des Tag. 469 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 470 * @param tagLib TagLib des Tag. 471 */ 472 protected void setTagLib(TagLib tagLib) { 473 this.tagLib = tagLib; 474 } 475 476 /** 477 * Setzt ein einzelnes Attribut (TagLibTagAttr) eines Tag. 478 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 479 * @param attribute Attribute eines Tag. 480 */ 481 public void setAttribute(TagLibTagAttr attribute) { 482 attributes.put(attribute.getName(),attribute); 483 if(attrFirst==null)attrFirst=attribute; 484 attrLast=attribute; 485 } 486 487 /** 488 * Setzt den Attributtyp eines Tag. 489 * ( ATTRIBUTE_TYPE_FIX, ATTRIBUTE_TYPE_DYNAMIC, ATTRIBUTE_TYPE_FULLDYNAMIC, ATTRIBUTE_TYPE_NONAME) 490 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 491 * @param attributeType The attributeType to set 492 */ 493 public void setAttributeType(int attributeType) { 494 495 this.attributeType = attributeType; 496 } 497 498 /** 499 * Setzt die Information, was fuer ein BodyContent das Tag haben kann. 500 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 501 * @param value BodyContent Information. 502 */ 503 public void setBodyContent(String value) { 504 // empty, free, must, tagdependent 505 value=value.toLowerCase().trim(); 506 //if(value.equals("jsp")) value="free"; 507 508 this.hasBody = !value.equals("empty"); 509 this.isBodyReq = !value.equals("free"); 510 this.isTagDependent = value.equals("tagdependent"); 511 bodyFree=value.equals("free"); 512 } 513 514 /** 515 * Setzt wieviele Attribute das Tag maximal haben darf. 516 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 517 * @param max The max to set 518 */ 519 protected void setMax(int max) { 520 this.max = max; 521 } 522 523 /** 524 * Setzt wieviele Attribute das Tag minimal haben darf. 525 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 526 * @param min The min to set 527 */ 528 protected void setMin(int min) { 529 this.min = min; 530 } 531 532 /** 533 * Setzt den Namen des Tag. 534 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 535 * @param name Name des Tag. 536 */ 537 public void setName(String name) { 538 this.name = name.toLowerCase(); 539 } 540 541 /** 542 * Setzt die implementierende Klassendefinition des Tag. 543 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 544 * @param tagClass Klassendefinition der Tag-Implementation. 545 */ 546 public void setTagClass(String tagClass) { 547 this.tagClass = tagClass; 548 } 549 550 /** 551 * Setzt die implementierende Klassendefinition des Evaluator. 552 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 553 * @param tteClass Klassendefinition der Evaluator-Implementation. 554 */ 555 protected void setTteClass(String tteClass) { 556 this.tteClass = tteClass; 557 } 558 559 /** 560 * Setzt die implementierende Klassendefinition des Evaluator. 561 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 562 * @param tteClass Klassendefinition der Evaluator-Implementation. 563 */ 564 public void setTttClass(String tttClass) { 565 this.tttClass = tttClass; 566 this.tttConstructor=null; 567 } 568 569 /** 570 * Setzt die implementierende Klassendefinition des TagDependentBodyTransformer. 571 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 572 * @param tdbtClass Klassendefinition der TagDependentBodyTransformer-Implementation. 573 */ 574 public void setTdbtClass(String tdbtClass) { 575 this.tdbtClass = tdbtClass; 576 this.tdbt = null; 577 } 578 579 /** 580 * Setzt, ob der Body des Tag geparst werden soll oder nicht. 581 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 582 * @param parseBody Soll der Body geparst werden. 583 */ 584 public void setParseBody(boolean parseBody) { 585 this.parseBody = parseBody; 586 } 587 588 /** 589 * Setzt ob das Tag einen Appendix besitzen kann oder nicht. 590 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 591 * @param hasAppendix Kann das Tag einen Appendix besitzen. 592 */ 593 public void setAppendix(boolean hasAppendix) { 594 this.hasAppendix = hasAppendix; 595 } 596 /** 597 * @return Returns the description. 598 */ 599 public String getDescription() { 600 return description; 601 } 602 603 /** 604 * @param description The description to set. 605 */ 606 public void setDescription(String description) { 607 this.description = description; 608 } 609 610 /** 611 * @return Returns the bodyIsFree. 612 */ 613 public boolean isBodyFree() { 614 return bodyFree; 615 } 616 617 public boolean hasBodyMethodExists() { 618 Class clazz= ClassUtil.loadClass(getTagClassName(),(Class)null);//Class.orName(tag.getTagClassName()); 619 if(clazz==null) return false; 620 621 try { 622 java.lang.reflect.Method method = clazz.getMethod("hasBody", new Class[]{boolean.class}); 623 if(method==null)return false; 624 return method.getReturnType()==void.class; 625 } 626 catch (Exception e) {} 627 return false; 628 } 629 630 /** 631 * @return Gibt zurueck ob ein Attribut Evaluator definiert ist oder nicht. 632 */ 633 public boolean hasAttributeEvaluator() { 634 return strAttributeEvaluator!=null; 635 } 636 637 /** 638 * @return Gibt den AttributeEvaluator zum Tag zurueck 639 * @throws AttributeEvaluatorException 640 */ 641 public AttributeEvaluator getAttributeEvaluator() throws AttributeEvaluatorException { 642 if(!hasAttributeEvaluator()) return null; 643 if(attributeEvaluator!=null) return attributeEvaluator; 644 try { 645 return attributeEvaluator=(AttributeEvaluator) ClassUtil.loadInstance(strAttributeEvaluator); 646 647 } catch (ClassException e) { 648 throw new AttributeEvaluatorException(e.getMessage()); 649 } 650 } 651 652 /** 653 * Setzt den Namen der Klasse welche einen AttributeEvaluator implementiert. 654 * @param value Name der AttributeEvaluator Klassse 655 */ 656 public void setAttributeEvaluatorClassName(String value) { 657 strAttributeEvaluator=value; 658 659 } 660 661 /** 662 * sets if tag handle exception inside his body or not 663 * @param handleException handle it or not 664 */ 665 public void setHandleExceptions(boolean handleException) { 666 this.handleException=handleException; 667 } 668 669 /** 670 * @return 671 */ 672 public boolean hasDefaultValue() { 673 return hasDefaultValue; 674 } 675 676 /** 677 * @param hasDefaultValue The hasDefaultValue to set. 678 */ 679 public void setHasDefaultValue(boolean hasDefaultValue) { 680 this.hasDefaultValue = hasDefaultValue; 681 } 682 683 /** 684 * return ASM Tag for this tag 685 * @param line 686 * @return 687 688 */ 689 public Tag getTag(Position start,Position end) throws TagLibException { 690 if(StringUtil.isEmpty(tttClass)) return new TagOther(start,end); 691 try { 692 return _getTag(start,end); 693 } 694 catch (ClassException e) { 695 throw new TagLibException(e.getMessage()); 696 } 697 catch (NoSuchMethodException e) { 698 throw new TagLibException(e.getMessage()); 699 } 700 catch (Throwable e) { 701 ExceptionUtil.rethrowIfNecessary(e); 702 throw new TagLibException(e); 703 } 704 } 705 private Tag _getTag(Position start,Position end) throws ClassException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { 706 if(tttConstructor==null) { 707 Class clazz = ClassUtil.loadClass(tttClass); 708 tttConstructor = clazz.getConstructor(CONSTRUCTOR_PARAMS); 709 } 710 return (Tag) tttConstructor.newInstance(new Object[]{start,end}); 711 } 712 713 public void setAllowRemovingLiteral(boolean allowRemovingLiteral) { 714 this.allowRemovingLiteral=allowRemovingLiteral; 715 } 716 717 /** 718 * @return the allowRemovingLiteral 719 */ 720 public boolean isAllowRemovingLiteral() { 721 return allowRemovingLiteral; 722 } 723 724 public String getAttributeNames() { 725 Iterator<String> it = attributes.keySet().iterator(); 726 StringBuffer sb=new StringBuffer(); 727 while(it.hasNext()) { 728 if(sb.length()>0)sb.append(","); 729 sb.append(it.next()); 730 } 731 return sb.toString(); 732 } 733 734 public String getSetter(Attribute attr, Type type) { 735 if(tagLib.isCore()) 736 return "set"+StringUtil.ucFirst(attr.getName()); 737 738 String setter=setters.get(attr.getName()); 739 if(setter!=null)return setter; 740 setter = "set"+StringUtil.ucFirst(attr.getName()); 741 Class clazz; 742 try { 743 if(type==null) type = CastOther.getType(attr.getType()); 744 clazz=ClassUtil.loadClass(getTagClassName()); 745 java.lang.reflect.Method m = ClassUtil.getMethodIgnoreCase(clazz,setter,new Class[]{ClassUtil.loadClass(type.getClassName())}); 746 setter=m.getName(); 747 } 748 catch (Exception e) { 749 //print.err(setter); 750 e.printStackTrace(); 751 } 752 setters.put(attr.getName(), setter); 753 return setter; 754 } 755 756 public String getHash() { 757 StringBuilder sb=new StringBuilder(); 758 sb.append(this.getTagClassName()); 759 sb.append(this.getAttributeNames()); 760 sb.append(this.getAttributeType()); 761 sb.append(this.getMax()); 762 sb.append(this.getMin()); 763 sb.append(this.getName()); 764 sb.append(this.getParseBody()); 765 sb.append(this.getTteClassName()); 766 sb.append(this.getTttClassName()); 767 Iterator<Entry<String, TagLibTagAttr>> it = this.getAttributes().entrySet().iterator(); 768 Entry<String, TagLibTagAttr> entry; 769 while(it.hasNext()){ 770 entry = it.next(); 771 sb.append(entry.getKey()); 772 sb.append(entry.getValue().getHash()); 773 } 774 775 try { 776 return Md5.getDigestAsString(sb.toString()); 777 } catch (IOException e) { 778 return ""; 779 } 780 } 781 782 public TagLibTagAttr getDefaultAttribute() { 783 return defaultAttribute; 784 } 785 786 public void setDefaultAttribute(TagLibTagAttr defaultAttribute) { 787 this.defaultAttribute=defaultAttribute; 788 } 789 790 791 public void setScript(TagLibTagScript script) { 792 this.script=script; 793 } 794 795 796 /** 797 * @return the script 798 */ 799 public TagLibTagScript getScript() { 800 return script; 801 } 802 803 804 public TagLibTagAttr getSingleAttr() { 805 806 if(singleAttr==UNDEFINED) { 807 singleAttr=null; 808 Iterator<TagLibTagAttr> it = getAttributes().values().iterator(); 809 TagLibTagAttr attr; 810 while(it.hasNext()){ 811 attr=it.next(); 812 if(attr.getNoname()){ 813 singleAttr=attr; 814 break; 815 } 816 } 817 } 818 return singleAttr; 819 } 820 821 822 /** 823 * attribute value set, if the attribute has no value defined 824 * @return 825 */ 826 public Expression getAttributeDefaultValue() { 827 if(attributeDefaultValue==null) return LitBoolean.TRUE; 828 return attributeDefaultValue; 829 } 830 831 public void setAttributeDefaultValue(String defaultValue) { 832 defaultValue=defaultValue.trim(); 833 // boolean 834 if(StringUtil.startsWithIgnoreCase(defaultValue, "boolean:")) { 835 String str=defaultValue.substring(8).trim(); 836 Boolean b = Caster.toBoolean(str,null); 837 if(b!=null){ 838 this.attributeDefaultValue=LitBoolean.toExprBoolean(b.booleanValue()); 839 return; 840 } 841 842 } 843 // number 844 else if(StringUtil.startsWithIgnoreCase(defaultValue, "number:")) { 845 String str=defaultValue.substring(7).trim(); 846 Double d = Caster.toDouble(str,null); 847 if(d!=null){ 848 this.attributeDefaultValue=LitDouble.toExprDouble(d.doubleValue()); 849 return; 850 } 851 852 } 853 else this.attributeDefaultValue=LitString.toExprString(defaultValue); 854 } 855}