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