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            @Override
039            public void init(Map arguments){
040                    super.init(arguments);
041                    
042                    String strValues = Caster.toString(arguments.get("component-values"),null);
043                    if(!StringUtil.isEmpty(strValues)){
044                            doProperties = railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "properties")!=-1;
045                            doGetters=railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "getters")!=-1;
046                            doRemoteValues=railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "remote-values")!=-1;
047                    }
048            }
049    
050            public Object toAMFObject(Object cf) throws PageException {
051                    if(cf instanceof List) return toAMFObject((List)cf);
052                    if(cf instanceof Array) return toAMFObject(ArrayAsList.toList((Array)cf));
053                    if(cf instanceof Component)     return toAMFObject((Component)cf);
054                    if(cf instanceof Query) return super.toAMFObject((Query)cf);
055                    if(cf instanceof Map) return super.toAMFObject((Map)cf);
056                    if(cf instanceof Object[]) return toAMFObject((Object[])cf);
057                    
058                    return cf;
059            }
060            
061    
062            protected ASObject toAMFObject(Component cfc) throws PageException {
063                    // add properties
064                    ASObject aso = doProperties?super.toAMFObject(cfc):new ASObject();
065                    ComponentWrap cw=null;
066                    if(cfc instanceof ComponentAccess)cw=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,cfc);
067                    
068                    Iterator it = cfc.entrySet().iterator();
069            Map.Entry entry;
070            Object v;
071            Collection.Key k;
072            UDF udf;
073            String name;
074            while(it.hasNext()) {
075                entry=(Entry) it.next();
076                k=KeyImpl.toKey(entry.getKey());
077                v=entry.getValue();
078                
079                // add getters
080                if(v instanceof UDF){
081                    if(!doGetters) continue;
082                    udf=(UDF) v;
083                    name=udf.getFunctionName();
084                    if(!StringUtil.startsWithIgnoreCase(name, "get"))continue;
085                    if(udf.getReturnType()==CFTypes.TYPE_VOID) continue;
086                    if(udf.getFunctionArguments().length>0) continue;
087                    
088                    try {
089                                            v=cfc.call(ThreadLocalPageContext.get(), name, ArrayUtil.OBJECT_EMPTY);
090                                    } catch (PageException e) {
091                                            continue;
092                                    }
093                    name=name.substring(3);
094                    
095                    aso.put(toString(name,forceCFCLower), toAMFObject(v));
096                }
097                
098                // add remote data members
099                if(cw!=null && doRemoteValues){
100                    v=cw.get(k,null);
101                    if(v!=null)aso.put(toString(k,forceCFCLower), toAMFObject(v));
102                }
103            }
104            return aso;
105            }
106        
107            protected Object toAMFObject(List list) throws PageException {
108                    list = Duplicator.duplicateList(list, false);
109            ListIterator it = list.listIterator();
110            while(it.hasNext()) {
111                    list.set(it.nextIndex(),toAMFObject(it.next()));
112            }
113            return list;
114        }
115            
116            protected Object toAMFObject(Object[] src) throws PageException {
117                    ArrayList list=new ArrayList();
118                    for(int i=0;i<src.length;i++){
119                            list.add(toAMFObject(src[i]));
120                    }
121                    return list;
122        }
123    }