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 **/
019/**
020 * Implements the CFML Function getfunctiondescription
021 */
022package lucee.runtime.functions.other;
023
024import java.util.Iterator;
025import java.util.Map.Entry;
026
027import lucee.commons.lang.ExceptionUtil;
028import lucee.commons.lang.StringUtil;
029import lucee.runtime.Component;
030import lucee.runtime.ComponentSpecificAccess;
031import lucee.runtime.PageContext;
032import lucee.runtime.PageContextImpl;
033import lucee.runtime.component.ComponentLoader;
034import lucee.runtime.config.ConfigImpl;
035import lucee.runtime.customtag.InitFile;
036import lucee.runtime.exp.ExpressionException;
037import lucee.runtime.exp.PageException;
038import lucee.runtime.ext.function.Function;
039import lucee.runtime.op.Caster;
040import lucee.runtime.tag.CFTagCore;
041import lucee.runtime.type.Collection.Key;
042import lucee.runtime.type.Struct;
043import lucee.runtime.type.StructImpl;
044import lucee.runtime.type.util.KeyConstants;
045import lucee.runtime.type.util.ListUtil;
046import lucee.transformer.library.tag.TagLib;
047import lucee.transformer.library.tag.TagLibFactory;
048import lucee.transformer.library.tag.TagLibTag;
049import lucee.transformer.library.tag.TagLibTagAttr;
050import lucee.transformer.library.tag.TagLibTagScript;
051
052public final class GetTagData implements Function {
053        
054        public static Struct call(PageContext pc , String nameSpace, String strTagName) throws PageException {
055                TagLib[] tlds;
056                tlds = ((ConfigImpl)pc.getConfig()).getTLDs();
057
058                
059                TagLib tld=null;
060                TagLibTag tag=null;
061                for(int i=0;i<tlds.length;i++) {
062                    tld=tlds[i];
063                        if(tld.getNameSpaceAndSeparator().equalsIgnoreCase(nameSpace)) {
064                            tag = tld.getTag(strTagName.toLowerCase());
065                            if(tag!=null)break;
066                        }
067                        
068                }
069                if(tag == null) throw new ExpressionException("tag ["+nameSpace+strTagName+"] is not a built in tag");
070
071                // CFML Based Function
072                Class clazz=null;
073                try{
074                        clazz=tag.getClazz();
075                }
076                catch(Throwable t){
077                        ExceptionUtil.rethrowIfNecessary(t);
078                }
079                
080                if(clazz==CFTagCore.class){
081                        PageContextImpl pci=(PageContextImpl) pc;
082                        boolean prior = pci.useSpecialMappings(true);
083                        try{
084                                return cfmlBasedTag(pc,tld,tag);
085                        }
086                        finally {
087                                pci.useSpecialMappings(prior);
088                        }
089                        
090                }
091                return javaBasedTag(tld,tag);
092                
093                
094                
095                
096                
097        }
098
099        private static Struct cfmlBasedTag(PageContext pc, TagLib tld, TagLibTag tag) throws PageException {
100                
101                //Map attrs = tag.getAttributes();
102
103                TagLibTagAttr attrFilename = tag.getAttribute("__filename");
104                //TagLibTagAttr attrName = tag.getAttribute("__name");
105                TagLibTagAttr attrIsWeb = tag.getAttribute("__isweb");
106                
107                String filename = Caster.toString(attrFilename.getDefaultValue());
108                String name = Caster.toString(attrFilename.getDefaultValue());
109                boolean isWeb = Caster.toBooleanValue(attrIsWeb.getDefaultValue());
110                InitFile source = CFTagCore.createInitFile(pc, isWeb, filename);
111                
112                Component cfc = ComponentLoader.loadComponent(pc,null,source.getPageSource(), source.getFilename().substring(0,source.getFilename().length()-(pc.getConfig().getCFCExtension().length()+1)), false,true);
113        ComponentSpecificAccess cw=ComponentSpecificAccess.toComponentSpecificAccess(Component.ACCESS_PRIVATE, cfc);
114                Struct metadata=Caster.toStruct(cw.get("metadata",null),null,false);
115                
116                
117                Struct sct=new StructImpl();
118                sct.set("nameSpaceSeperator",tld.getNameSpaceSeparator());
119                sct.set("nameSpace",tld.getNameSpace());
120                sct.set(KeyConstants._name,name.substring(0,name.lastIndexOf('.')));
121                sct.set("hasNameAppendix",Boolean.FALSE);
122                sct.set(KeyConstants._status,"implemeted");
123                sct.set(KeyConstants._type,"cfml");
124                
125                sct.set("bodyType",getBodyType(tag));
126                sct.set("attrMin",Caster.toDouble(0));
127                sct.set("attrMax",Caster.toDouble(0));
128                sct.set("attributeCollection",getSupportAttributeCollection(tag));
129                
130                // TODO add support for script for cfml tags
131                Struct scp=new StructImpl();
132                sct.set(KeyConstants._script,scp);
133                scp.set("rtexpr", Boolean.FALSE);
134                scp.set(KeyConstants._type, "none");
135                
136                
137                
138                
139                if(metadata!=null) {
140                        sct.set(KeyConstants._description,metadata.get("hint",""));
141                        sct.set("attributeType",metadata.get("attributeType",""));
142                        sct.set("parseBody",Caster.toBoolean(metadata.get("parseBody",Boolean.FALSE),Boolean.FALSE));
143                        
144                        Struct _attrs=new StructImpl();
145                        sct.set(KeyConstants._attributes,_attrs);
146                        
147                        Struct srcAttrs = Caster.toStruct(metadata.get(KeyConstants._attributes,null),null,false);
148                        Struct src;
149                        if(srcAttrs!=null){
150                                //Key[] keys = srcAttrs.keys();
151                                Iterator<Entry<Key, Object>> it = srcAttrs.entryIterator();
152                                Entry<Key, Object> e;
153                                while(it.hasNext()){
154                                        e = it.next();
155                                        src = Caster.toStruct(e.getValue(),null,false);
156                                        if(Caster.toBooleanValue(src.get(KeyConstants._hidden,null),false))continue;
157                                        Struct _attr=new StructImpl();
158                                        _attr.set(KeyConstants._status,"implemeted");
159                                        _attr.set(KeyConstants._description,src.get(KeyConstants._hint,""));
160                                        _attr.set(KeyConstants._type,src.get(KeyConstants._type,"any"));
161                                        _attr.set(KeyConstants._required,Caster.toBoolean(src.get(KeyConstants._required,""),null));
162                                        _attr.set("scriptSupport","none");
163                                        _attrs.setEL(e.getKey().getLowerString(),_attr);
164                                        
165                                }
166                        }
167                        
168                }
169                
170                
171                /* /////////////////////
172                
173                
174                Map atts = tag.getAttributes();
175                Iterator it = atts.keySet().iterator();
176                
177                while(it.hasNext()) {
178                    Object key = it.next();
179                    TagLibTagAttr attr=(TagLibTagAttr) atts.get(key);
180                    if(attr.getHidden()) continue;
181                //for(int i=0;i<args.size();i++) {
182                        Struct _arg=new StructImpl();
183                        _arg.set("status",TagLibFactory.toStatus(attr.getStatus()));
184                        _arg.set("description",attr.getDescription());
185                        _arg.set("type",attr.getType());
186                        _arg.set("required",attr.isRequired()?Boolean.TRUE:Boolean.FALSE);
187                        _args.setEL(attr.getName(),_arg);
188                }
189                */
190                
191                
192                
193                return sct;
194        }
195
196        private static Struct javaBasedTag(TagLib tld, TagLibTag tag) throws PageException {
197                Struct sct=new StructImpl();
198                sct.set("nameSpaceSeperator",tld.getNameSpaceSeparator());
199                sct.set("nameSpace",tld.getNameSpace());
200                sct.set(KeyConstants._name,tag.getName());
201                sct.set(KeyConstants._description,tag.getDescription());
202                sct.set(KeyConstants._status,TagLibFactory.toStatus(tag.getStatus()));
203                
204                sct.set("attributeType",getAttributeType(tag));
205                sct.set("parseBody",Caster.toBoolean(tag.getParseBody()));
206                sct.set("bodyType",getBodyType(tag));
207                sct.set("attrMin",Caster.toDouble(tag.getMin()));
208                sct.set("attrMax",Caster.toDouble(tag.getMax()));
209                sct.set("hasNameAppendix",Caster.toBoolean(tag.hasAppendix()));
210                sct.set("attributeCollection",getSupportAttributeCollection(tag));
211                
212                // script
213                TagLibTagScript script = tag.getScript();
214                if(script!=null) {
215                        Struct scp=new StructImpl();
216                        sct.set(KeyConstants._script,scp);
217                        scp.set("rtexpr", Caster.toBoolean(script.getRtexpr()));
218                        scp.set(KeyConstants._type, script.getTypeAsString());
219                        if(script.getType()==TagLibTagScript.TYPE_SINGLE) {
220                                TagLibTagAttr attr = script.getSingleAttr();
221                                if(attr!=null)scp.set("singletype", attr.getScriptSupportAsString());
222                                else scp.set("singletype", "none");
223                        }
224                }
225                
226                
227                sct.set(KeyConstants._type,"java");
228                
229                Struct _args=new StructImpl();
230                sct.set(KeyConstants._attributes,_args);
231                
232                //Map<String,TagLibTagAttr> atts = tag.getAttributes();
233                Iterator<Entry<String, TagLibTagAttr>> it = tag.getAttributes().entrySet().iterator();
234                Entry<String, TagLibTagAttr> e;
235                while(it.hasNext()) {
236                    e = it.next();
237                    TagLibTagAttr attr=e.getValue();
238                    if(attr.getHidden()) continue;
239                //for(int i=0;i<args.size();i++) {
240                        Struct _arg=new StructImpl();
241                        _arg.set(KeyConstants._status,TagLibFactory.toStatus(attr.getStatus()));
242                        _arg.set(KeyConstants._description,attr.getDescription());
243                        _arg.set(KeyConstants._type,attr.getType());
244                        if(attr.getAlias()!=null)_arg.set(KeyConstants._alias,ListUtil.arrayToList(attr.getAlias(), ","));
245                        if(attr.getValues()!=null)_arg.set(KeyConstants._values,Caster.toArray(attr.getValues()));
246                        if(attr.getDefaultValue()!=null)_arg.set("defaultValue",attr.getDefaultValue());
247                        _arg.set(KeyConstants._required,attr.isRequired()?Boolean.TRUE:Boolean.FALSE);
248                        _arg.set("scriptSupport",attr.getScriptSupportAsString());
249                        _args.setEL(attr.getName(),_arg);
250                }
251                return sct;
252        }
253
254        private static String getBodyType(TagLibTag tag) {
255                if(!tag.getHasBody()) return "prohibited";
256                if(tag.isBodyFree()) return "free";
257                return "required";
258        }
259
260        private static String getAttributeType(TagLibTag tag) {
261                int type = tag.getAttributeType();
262                if(TagLibTag.ATTRIBUTE_TYPE_DYNAMIC==type) return "dynamic";
263                if(TagLibTag.ATTRIBUTE_TYPE_FIXED==type) return "fixed";
264                if(TagLibTag.ATTRIBUTE_TYPE_MIXED==type) return "mixed";
265                if(TagLibTag.ATTRIBUTE_TYPE_NONAME==type) return "noname";
266                
267                return "fixed";
268        }
269
270
271        private static Boolean getSupportAttributeCollection(TagLibTag tag) {   
272                return StringUtil.isEmpty(tag.getTttClassName())?Boolean.TRUE:Boolean.FALSE;
273        }
274}