001    package railo.runtime;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.Iterator;
006    import java.util.List;
007    import java.util.Map;
008    import java.util.Map.Entry;
009    import java.util.Set;
010    
011    import railo.commons.lang.StringUtil;
012    import railo.runtime.component.ComponentLoader;
013    import railo.runtime.dump.DumpData;
014    import railo.runtime.dump.DumpProperties;
015    import railo.runtime.dump.DumpTable;
016    import railo.runtime.engine.ThreadLocalPageContext;
017    import railo.runtime.exp.PageException;
018    import railo.runtime.type.Array;
019    import railo.runtime.type.ArrayImpl;
020    import railo.runtime.type.Collection;
021    import railo.runtime.type.KeyImpl;
022    import railo.runtime.type.Struct;
023    import railo.runtime.type.StructImpl;
024    import railo.runtime.type.UDF;
025    import railo.runtime.type.UDFImpl;
026    import railo.runtime.type.UDFProperties;
027    import railo.runtime.type.util.ArrayUtil;
028    import railo.runtime.type.util.KeyConstants;
029    
030    /**
031     * 
032     * MUST add handling for new attributes (style, namespace, serviceportname, porttypename, wsdlfile, bindingname, and output)
033     */ 
034    public class InterfaceImpl implements Interface {
035    
036            private static final long serialVersionUID = -2488865504508636253L;
037    
038            private static final InterfaceImpl[] EMPTY = new InterfaceImpl[]{};
039            
040            //private InterfacePage page;
041            private PageSource pageSource;
042            private String extend;
043            private String hint;
044            private String dspName;
045            private String callPath;
046            private boolean realPath;
047            private Map meta;
048            
049            private InterfaceImpl[] superInterfaces;
050            
051            private Map<Collection.Key,UDF> udfs=new HashMap<Collection.Key,UDF>();
052            private Map<Collection.Key,UDF> interfacesUDFs;
053    
054            /**
055         * Constructor of the Component
056         * @param output 
057         * @param extend 
058         * @param hint 
059         * @param dspName 
060         */
061            public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs) {
062            this(page.getPageSource(),extend, hint, dspName,callPath, realPath,interfacesUDFs,null);
063            }
064            public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs, Map meta) {
065            this(page.getPageSource(),extend, hint, dspName,callPath, realPath,interfacesUDFs,meta);
066            }
067            public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs) {
068            this(pageSource, extend, hint, dspName, callPath, realPath, interfacesUDFs, null);
069            }
070            public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs, Map meta) {
071            this.pageSource=pageSource;
072            this.extend=extend;
073            this.hint=hint;
074            this.dspName=dspName;
075            this.callPath=callPath;
076            this.realPath=realPath;
077            this.interfacesUDFs=interfacesUDFs;
078            this.meta=meta;
079    }
080             
081             
082             
083                
084    
085            private static void init(PageContext pc,InterfaceImpl icfc) throws PageException {
086    
087                    if(!StringUtil.isEmpty(icfc.extend) && (icfc.superInterfaces==null || icfc.superInterfaces.length==0)) {
088                            icfc.superInterfaces=loadImplements(ThreadLocalPageContext.get(pc),icfc.extend,icfc.interfacesUDFs);
089                    }
090                    else icfc.superInterfaces=EMPTY;
091            }
092    
093    
094        public static InterfaceImpl[] loadImplements(PageContext pc, String lstExtend, Map interfaceUdfs) throws PageException {
095            List<InterfaceImpl> interfaces=new ArrayList<InterfaceImpl>();
096            loadImplements(pc, lstExtend, interfaces, interfaceUdfs);
097            return interfaces.toArray(new InterfaceImpl[interfaces.size()]);
098            
099            }
100    
101        private static void loadImplements(PageContext pc, String lstExtend,List interfaces, Map interfaceUdfs) throws PageException {
102            
103            Array arr = railo.runtime.type.util.ListUtil.listToArrayRemoveEmpty(lstExtend, ',');
104            Iterator<Object> it = arr.valueIterator();
105            InterfaceImpl ic;
106            String extend;
107    
108            while(it.hasNext()) {
109                    extend=((String) it.next()).trim();
110                    ic=ComponentLoader.loadInterface(pc,extend,interfaceUdfs);
111                    interfaces.add(ic);
112                    ic.setUDFListener(interfaceUdfs);
113                    if(!StringUtil.isEmpty(ic.extend)) {
114                            loadImplements(pc,ic.extend,interfaces,interfaceUdfs);
115                    }
116            }
117            }
118        
119        private void setUDFListener(Map<Collection.Key,UDF> interfacesUDFs) {
120                    this.interfacesUDFs=interfacesUDFs;
121            }
122    
123    
124    
125            /*public boolean instanceOf(String type) {
126            boolean b = _instanceOf(type);
127            print.out("instanceOf("+type+"):"+page+":"+b);
128            return b;
129        }*/
130        public boolean instanceOf(String type) {
131                    if(realPath) {
132                    if(type.equalsIgnoreCase(callPath)) return true;
133                if(type.equalsIgnoreCase(pageSource.getComponentName())) return true;
134                if(type.equalsIgnoreCase(_getName())) return true;       
135            }
136            else {
137                    if(type.equalsIgnoreCase(callPath)) return true;
138                if(type.equalsIgnoreCase(_getName())) return true; 
139            }
140                    if(superInterfaces==null){
141                            try {
142                                    init(null,this);
143                            } catch (PageException e) {
144                                    superInterfaces=EMPTY;
145                            }
146                    }
147            for(int i=0;i<superInterfaces.length;i++){
148                    if(superInterfaces[i].instanceOf(type))return true;
149            }
150            return false;
151        }
152    
153     
154        /**
155             * @return the callPath
156             */
157            public String getCallPath() {
158                    return callPath;
159            }
160    
161    
162    
163            private String _getName() { // MUST nicht so toll
164                if(callPath==null) return "";
165                return railo.runtime.type.util.ListUtil.last(callPath,"./",true);
166            }
167        
168        public void registerUDF(String key, UDF udf) {
169            udfs.put(KeyImpl.init(key),udf);
170            interfacesUDFs.put(KeyImpl.init(key), udf);
171        }
172        
173        public void registerUDF(Collection.Key key, UDF udf) {
174            udfs.put(key,udf);
175            interfacesUDFs.put(key, udf);
176        }
177        
178        public void registerUDF(String key, UDFProperties props) {
179            registerUDF(key, new UDFImpl(props));
180        }
181        
182        public void registerUDF(Collection.Key key, UDFProperties props) {
183            registerUDF(key, new UDFImpl(props));
184        }
185        
186        
187        
188        
189        
190        
191        
192        
193        @Override
194            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
195                DumpTable table = new DumpTable("interface","#99cc99","#ffffff","#000000");
196            table.setTitle("Interface "+callPath+""+(" "+StringUtil.escapeHTML(dspName)));
197            table.setComment("Interface can not directly invoked as a object");
198            //if(top.properties.extend.length()>0)table.appendRow(1,new SimpleDumpData("Extends"),new SimpleDumpData(top.properties.extend));
199            //if(top.properties.hint.trim().length()>0)table.appendRow(1,new SimpleDumpData("Hint"),new SimpleDumpData(top.properties.hint));
200            
201            //table.appendRow(1,new SimpleDumpData(""),_toDumpData(top,pageContext,maxlevel,access));
202            return table;
203        }
204    
205            /* *
206             * @return the page
207             * /
208            public InterfacePage getPage() {
209                    return page;
210            }*/
211            
212            public PageSource getPageSource() {
213                    return pageSource;
214            }
215    
216    
217            public Struct getMetaData(PageContext pc) throws PageException {
218                    return _getMetaData(pc,this);
219            }
220            private static Struct _getMetaData(PageContext pc,InterfaceImpl icfc) throws PageException {
221                    Struct sct=new StructImpl();
222                    ArrayImpl arr=new ArrayImpl();
223            {
224                            Iterator<UDF> it = icfc.udfs.values().iterator();
225                    while(it.hasNext()) {
226                            arr.append(it.next().getMetaData(pc));
227                    }
228                    }
229            
230            if(icfc.meta!=null) {
231                    Iterator it = icfc.meta.entrySet().iterator();
232                    Map.Entry entry;
233                    while(it.hasNext()){
234                            entry=(Entry) it.next();
235                            sct.setEL(KeyImpl.toKey(entry.getKey()), entry.getValue());
236                    }
237            }
238            
239            
240            if(!StringUtil.isEmpty(icfc.hint,true))sct.set(KeyConstants._hint,icfc.hint);
241            if(!StringUtil.isEmpty(icfc.dspName,true))sct.set(KeyConstants._displayname,icfc.dspName);
242            init(pc,icfc);
243            if(!ArrayUtil.isEmpty(icfc.superInterfaces)){
244                Set<String> _set = railo.runtime.type.util.ListUtil.listToSet(icfc.extend,',',true);
245                Struct ex=new StructImpl();
246                    sct.set(KeyConstants._extends,ex);
247                    for(int i=0;i<icfc.superInterfaces.length;i++){
248                            if(!_set.contains(icfc.superInterfaces[i].getCallPath())) continue;
249                            ex.setEL(KeyImpl.init(icfc.superInterfaces[i].getCallPath()),_getMetaData(pc,icfc.superInterfaces[i]));
250                    }
251                    
252            }
253            
254            if(arr.size()!=0)sct.set(KeyConstants._functions,arr);
255            PageSource ps = icfc.pageSource;
256            sct.set(KeyConstants._name,ps.getComponentName());
257            sct.set(KeyConstants._fullname,ps.getComponentName());
258           
259            sct.set(KeyConstants._path,ps.getDisplayPath());
260            sct.set(KeyConstants._type,"interface");
261            return sct;
262            }
263    
264    }