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.net.URI; 023import java.net.URISyntaxException; 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.List; 028import java.util.Map; 029import java.util.Map.Entry; 030 031import lucee.commons.lang.ClassException; 032import lucee.commons.lang.ClassUtil; 033import lucee.commons.lang.Md5; 034import lucee.commons.lang.StringUtil; 035import lucee.runtime.exp.ExpressionException; 036import lucee.runtime.exp.PageRuntimeException; 037import lucee.transformer.cfml.ExprTransformer; 038 039 040/** 041 * Die Klasse TagLib repaesentiert eine Komplette TLD, 042 * mit ihrer Hilfe kann man alle Informationen, zu einer TLD Abfragen. 043 */ 044public class TagLib implements Cloneable { 045 046 public static final short STATUS_IMPLEMENTED=0; 047 public static final short STATUS_DEPRECATED=1; 048 public static final short STATUS_UNIMPLEMENTED=2; 049 public static final short STATUS_HIDDEN=4; 050 051 052 /** 053 * Field <code>EXPR_TRANSFORMER</code> 054 */ 055 public static String EXPR_TRANSFORMER="lucee.transformer.cfml.expression.CFMLExprTransformer"; 056 057 private String shortName=""; 058 private String displayName=null; 059 private String type="cfml"; 060 private String nameSpace; 061 private String nameSpaceSeperator=":"; 062 private String ELClass=EXPR_TRANSFORMER; 063 private HashMap<String,TagLibTag> tags=new HashMap<String,TagLibTag>(); 064 private HashMap<String,TagLibTag> appendixTags=new HashMap<String,TagLibTag>(); 065 private ExprTransformer exprTransformer; 066 067 private char[] nameSpaceAndNameSpaceSeperator; 068 069 private boolean isCore; 070 071 private String source; 072 073 private URI uri; 074 075 private String description; 076 private TagLibTag[] scriptTags; 077 private boolean ignoreUnknowTags; 078 079 080 /** 081 * Geschuetzer Konstruktor ohne Argumente. 082 */ 083 protected TagLib(boolean isCore) { 084 this.isCore=isCore; 085 } 086 protected TagLib() { 087 this(false); 088 } 089 090 /** 091 * @param source the source to set 092 */ 093 public void setSource(String source) { 094 this.source = source; 095 } 096 097 /** 098 * Gibt den Name-Space einer TLD als String zurueck. 099 * @return String Name der TLD. 100 */ 101 public String getNameSpace() { 102 103 return nameSpace; 104 } 105 106 /** 107 * Gibt den Trenner zwischen Name-Space und Name einer TLD zurueck. 108 * @return Name zwischen Name-Space und Name. 109 */ 110 public String getNameSpaceSeparator() { 111 return nameSpaceSeperator; 112 } 113 114 /** 115 * Gibt den Name-Space inkl. dem Seperator zurueck. 116 * @return String 117 */ 118 public String getNameSpaceAndSeparator() { 119 return nameSpace+nameSpaceSeperator; 120 } 121 122 /** 123 * Gibt den Name-Space inkl. dem Seperator zurueck. 124 * @return String 125 */ 126 public char[] getNameSpaceAndSeperatorAsCharArray() { 127 if(nameSpaceAndNameSpaceSeperator==null) { 128 nameSpaceAndNameSpaceSeperator=getNameSpaceAndSeparator().toCharArray(); 129 } 130 return nameSpaceAndNameSpaceSeperator; 131 } 132 133 /** 134 * Gibt einen Tag (TagLibTag)zurueck, dessen Name mit dem uebergebenen Wert uebereinstimmt, 135 * falls keine uebereinstimmung gefunden wird, wird null zurueck gegeben. 136 * @param name Name des Tag das zurueck gegeben werden soll. 137 * @return TagLibTag Tag das auf den Namen passt. 138 */ 139 public TagLibTag getTag(String name) { 140 return tags.get(name); 141 } 142 143 public TagLibTag getTag(Class clazz) { 144 Iterator<TagLibTag> _tags = tags.values().iterator(); 145 TagLibTag tlt; 146 while(_tags.hasNext()){ 147 tlt = _tags.next(); 148 if(tlt.getTagClassName().equalsIgnoreCase(clazz.getName())) { 149 return tlt; 150 } 151 } 152 return null; 153 } 154 155 /** 156 * Gibt einen Tag (TagLibTag)zurueck, welches definiert hat, dass es einen Appendix besitzt. 157 * D.h. dass der Name des Tag mit weiteren Buchstaben erweitert sein kann, 158 * also muss nur der erste Teil des Namen vom Tag mit dem uebergebenen Namen uebereinstimmen. 159 * Wenn keine uebereinstimmung gefunden wird, wird null zurueck gegeben. 160 * @param name Name des Tag inkl. Appendix das zurueck gegeben werden soll. 161 * @return TagLibTag Tag das auf den Namen passt. 162 */ 163 public TagLibTag getAppendixTag(String name) { 164 Iterator<String> it = appendixTags.keySet().iterator(); 165 String match=""; 166 while(it.hasNext()) { 167 String tagName=StringUtil.toStringNative(it.next(),""); 168 if(match.length()<tagName.length() && name.indexOf(tagName)==0) { 169 match=tagName; 170 } 171 } 172 return getTag(match); 173 } 174 175 /** 176 * Gibt alle Tags (TagLibTag) als HashMap zurueck. 177 * @return Alle Tags als HashMap. 178 */ 179 public Map<String,TagLibTag> getTags() { 180 return tags; 181 } 182 183 /** 184 * Gibt die Klasse des ExprTransformer als Zeichenkette zurueck. 185 * @return String 186 */ 187 public String getELClass() { 188 return ELClass; 189 } 190 191 /** 192 * Laedt den innerhalb der TagLib definierten ExprTransfomer und gibt diesen zurueck. 193 * Load Expression Transfomer defined in the tag library and return it. 194 * @return ExprTransformer 195 * @throws TagLibException 196 */ 197 public ExprTransformer getExprTransfomer() throws TagLibException { 198 //Class cls; 199 if(exprTransformer!=null) 200 return exprTransformer; 201 202 try { 203 exprTransformer = (ExprTransformer)ClassUtil.loadInstance(ELClass); 204 //exprTransformer = (ExprTransformer) cls.newInstance(); 205 } 206 catch (ClassException e) { 207 throw new TagLibException(e); 208 } 209 return exprTransformer; 210 } 211 212 /** 213 * Fuegt der TagLib einen weiteren Tag hinzu. 214 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 215 * @param tag Neuer Tag. 216 */ 217 public void setTag(TagLibTag tag) { 218 tag.setTagLib(this); 219 tags.put(tag.getName(),tag); 220 221 if(tag.hasAppendix()) 222 appendixTags.put(tag.getName(),tag); 223 else if(appendixTags.containsKey(tag.getName())) 224 appendixTags.remove(tag.getName()); 225 } 226 227 /** 228 * Fuegt der TagLib die Evaluator Klassendefinition als Zeichenkette hinzu. 229 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 230 * @param eLClass Zeichenkette der Evaluator Klassendefinition. 231 */ 232 protected void setELClass(String eLClass) { 233 ELClass = eLClass; 234 } 235 236 /** 237 * Fuegt der TagLib die die Definition des Name-Space hinzu. 238 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 239 * @param nameSpace Name-Space der TagLib. 240 */ 241 public void setNameSpace(String nameSpace) { 242 this.nameSpace = nameSpace.toLowerCase(); 243 } 244 245 /** 246 * Fuegt der TagLib die die Definition des Name-Space-Seperator hinzu. 247 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 248 * @param nameSpaceSeperator Name-Space-Seperator der TagLib. 249 */ 250 public void setNameSpaceSeperator(String nameSpaceSeperator) { 251 this.nameSpaceSeperator = nameSpaceSeperator; 252 } 253 254 /** 255 * @return Returns the displayName. 256 */ 257 public String getDisplayName() { 258 if(displayName==null)return shortName; 259 return displayName; 260 } 261 /** 262 * @param displayName The displayName to set. 263 */ 264 public void setDisplayName(String displayName) { 265 this.displayName = displayName; 266 } 267 /** 268 * @return Returns the shortName. 269 */ 270 public String getShortName() { 271 return shortName; 272 } 273 /** 274 * @param shortName The shortName to set. 275 */ 276 public void setShortName(String shortName) { 277 this.shortName = shortName; 278 if(nameSpace==null)nameSpace=shortName.toLowerCase(); 279 } 280 281 282 public void setIgnoreUnknowTags(boolean ignoreUnknowTags) { 283 this.ignoreUnknowTags=ignoreUnknowTags; 284 } 285 public boolean getIgnoreUnknowTags() { 286 return ignoreUnknowTags; 287 } 288 289 290 /** 291 * @return Returns the type. 292 */ 293 public String getType() { 294 return type; 295 } 296 /** 297 * @param type The type to set. 298 */ 299 public void setType(String type) { 300 this.type = type; 301 } 302 303 /** 304 * @see java.lang.Object#toString() 305 */ 306 public String toString() { 307 return getDisplayName()+":"+getShortName()+":"+super.toString(); 308 } 309 310 public String getHash() { 311 StringBuffer sb=new StringBuffer(); 312 Iterator<String> it = tags.keySet().iterator(); 313 while(it.hasNext()) { 314 //"__filename" 315 316 sb.append((tags.get(it.next())).getHash()+"\n"); 317 } 318 try { 319 return Md5.getDigestAsString(sb.toString()); 320 } catch (IOException e) { 321 return ""; 322 } 323 } 324 325 public boolean isCore() { 326 return isCore; 327 } 328 329 public void setIsCore(boolean isCore) { 330 this.isCore=isCore; 331 } 332 333 334 335 /** 336 * @see java.lang.Object#clone() 337 */ 338 public Object clone(){ 339 return duplicate(false); 340 } 341 342 /** 343 * duplicate the taglib, does not 344 * @param deepCopy duplicate also the children (TagLibTag) of this TagLib 345 * @return clone of this taglib 346 */ 347 public TagLib duplicate(boolean deepCopy) { 348 TagLib tl = new TagLib(isCore); 349 tl.appendixTags=duplicate(this.appendixTags,deepCopy); 350 tl.displayName=this.displayName; 351 tl.ELClass=this.ELClass; 352 tl.exprTransformer=this.exprTransformer; 353 tl.isCore=this.isCore; 354 tl.nameSpace=this.nameSpace; 355 tl.nameSpaceAndNameSpaceSeperator=this.nameSpaceAndNameSpaceSeperator; 356 tl.nameSpaceSeperator=this.nameSpaceSeperator; 357 tl.shortName=this.shortName; 358 tl.tags=duplicate(this.tags,deepCopy); 359 tl.type=this.type; 360 tl.source=this.source; 361 tl.ignoreUnknowTags=this.ignoreUnknowTags; 362 363 return tl; 364 } 365 366 /** 367 * duplcate a hashmap with TagLibTag's 368 * @param tags 369 * @param deepCopy 370 * @return cloned map 371 */ 372 private HashMap<String,TagLibTag> duplicate(HashMap<String,TagLibTag> tags, boolean deepCopy) { 373 if(deepCopy) throw new PageRuntimeException(new ExpressionException("deep copy not supported")); 374 375 Iterator<Entry<String, TagLibTag>> it = tags.entrySet().iterator(); 376 HashMap<String,TagLibTag> cm = new HashMap<String,TagLibTag>(); 377 Entry<String, TagLibTag> entry; 378 while(it.hasNext()){ 379 entry = it.next(); 380 cm.put( 381 entry.getKey(), 382 deepCopy? 383 entry.getValue(): // TODO add support for deepcopy ((TagLibTag)entry.getValue()).duplicate(deepCopy): 384 entry.getValue()); 385 } 386 return cm; 387 } 388 public String getSource() { 389 return source; 390 } 391 public URI getUri() { 392 // TODO Auto-generated method stub 393 return uri; 394 } 395 public void setUri(String strUri) throws URISyntaxException { 396 this.uri=new URI(strUri); 397 } 398 public void setUri(URI uri) { 399 this.uri=uri; 400 } 401 public void setDescription(String description) { 402 this.description=description; 403 } 404 405 public String getDescription() { 406 return description; 407 } 408 409 public TagLibTag[] getScriptTags() { 410 if(scriptTags==null) { 411 Iterator<TagLibTag> it = getTags().values().iterator(); 412 TagLibTag tag; 413 TagLibTagScript script; 414 List<TagLibTag> tags=new ArrayList<TagLibTag>(); 415 while(it.hasNext()){ 416 tag = it.next(); 417 script = tag.getScript(); 418 if(script!=null && script.getType()!=TagLibTagScript.TYPE_NONE) { 419 tags.add(tag); 420 //print.o(tag.getName()+":"+tag.getScript().getType()); 421 } 422 } 423 scriptTags=tags.toArray(new TagLibTag[tags.size()]); 424 } 425 return scriptTags; 426 } 427 428 429}