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