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