001    package railo.runtime.net.amf;
002    
003    import java.util.ArrayList;
004    import java.util.Iterator;
005    import java.util.List;
006    import java.util.ListIterator;
007    import java.util.Map;
008    import java.util.Map.Entry;
009    
010    import railo.commons.lang.CFTypes;
011    import railo.commons.lang.StringUtil;
012    import railo.runtime.Component;
013    import railo.runtime.ComponentWrap;
014    import railo.runtime.engine.ThreadLocalPageContext;
015    import railo.runtime.exp.PageException;
016    import railo.runtime.op.Caster;
017    import railo.runtime.op.Duplicator;
018    import railo.runtime.type.Array;
019    import railo.runtime.type.Collection;
020    import railo.runtime.type.KeyImpl;
021    import railo.runtime.type.Query;
022    import railo.runtime.type.UDF;
023    import railo.runtime.type.cfc.ComponentAccess;
024    import railo.runtime.type.util.ArrayUtil;
025    import railo.runtime.type.wrap.ArrayAsList;
026    import flex.messaging.io.amf.ASObject;
027    
028    
029    /**
030     * Cast a CFML object to AMF Objects and the other way
031     */
032    public final class ModernAMFCaster extends ClassicAMFCaster {
033    
034            private boolean doProperties=true;
035            private boolean doGetters=true;
036            private boolean doRemoteValues=true;
037            
038            /**
039             * @see railo.runtime.net.amf.ClassicAMFCaster#init(java.util.Map)
040             */
041            public void init(Map arguments){
042                    super.init(arguments);
043                    
044                    String strValues = Caster.toString(arguments.get("component-values"),null);
045                    if(!StringUtil.isEmpty(strValues)){
046                            doProperties = railo.runtime.type.List.listFindNoCase(strValues, "properties")!=-1;
047                            doGetters=railo.runtime.type.List.listFindNoCase(strValues, "getters")!=-1;
048                            doRemoteValues=railo.runtime.type.List.listFindNoCase(strValues, "remote-values")!=-1;
049                    }
050            }
051    
052            public Object toAMFObject(Object cf) throws PageException {
053                    if(cf instanceof List) return toAMFObject((List)cf);
054                    if(cf instanceof Array) return toAMFObject(ArrayAsList.toList((Array)cf));
055                    if(cf instanceof Component)     return toAMFObject((Component)cf);
056                    if(cf instanceof Query) return super.toAMFObject((Query)cf);
057                    if(cf instanceof Map) return super.toAMFObject((Map)cf);
058                    if(cf instanceof Object[]) return toAMFObject((Object[])cf);
059                    
060                    return cf;
061            }
062            
063    
064            protected ASObject toAMFObject(Component cfc) throws PageException {
065                    // add properties
066                    ASObject aso = doProperties?super.toAMFObject(cfc):new ASObject();
067                    ComponentWrap cw=null;
068                    if(cfc instanceof ComponentAccess)cw=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,cfc);
069                    
070                    Iterator it = cfc.entrySet().iterator();
071            Map.Entry entry;
072            Object v;
073            Collection.Key k;
074            UDF udf;
075            String name;
076            while(it.hasNext()) {
077                entry=(Entry) it.next();
078                k=KeyImpl.toKey(entry.getKey());
079                v=entry.getValue();
080                
081                // add getters
082                if(v instanceof UDF){
083                    if(!doGetters) continue;
084                    udf=(UDF) v;
085                    name=udf.getFunctionName();
086                    if(!StringUtil.startsWithIgnoreCase(name, "get"))continue;
087                    if(udf.getReturnType()==CFTypes.TYPE_VOID) continue;
088                    if(udf.getFunctionArguments().length>0) continue;
089                    
090                    try {
091                                            v=cfc.call(ThreadLocalPageContext.get(), name, ArrayUtil.OBJECT_EMPTY);
092                                    } catch (PageException e) {
093                                            continue;
094                                    }
095                    name=name.substring(3);
096                    
097                    aso.put(toString(name,forceCFCLower), toAMFObject(v));
098                }
099                
100                // add remote data members
101                if(cw!=null && doRemoteValues){
102                    v=cw.get(k,null);
103                    if(v!=null)aso.put(toString(k,forceCFCLower), toAMFObject(v));
104                }
105            }
106            return aso;
107            }
108        
109            protected Object toAMFObject(List list) throws PageException {
110                    list = Duplicator.duplicateList(list, false);
111            ListIterator it = list.listIterator();
112            while(it.hasNext()) {
113                    list.set(it.nextIndex(),toAMFObject(it.next()));
114            }
115            return list;
116        }
117            
118            protected Object toAMFObject(Object[] src) throws PageException {
119                    ArrayList list=new ArrayList();
120                    for(int i=0;i<src.length;i++){
121                            list.add(toAMFObject(src[i]));
122                    }
123                    return list;
124        }
125    }