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 **/
019package lucee.runtime.cache.tag.udf;
020
021import java.util.HashSet;
022import java.util.Iterator;
023import java.util.Map.Entry;
024import java.util.Set;
025
026import lucee.commons.lang.StringUtil;
027import lucee.runtime.exp.PageException;
028import lucee.runtime.op.Caster;
029import lucee.runtime.text.xml.struct.XMLStruct;
030import lucee.runtime.type.Collection;
031import lucee.runtime.type.Collection.Key;
032import lucee.runtime.type.Query;
033import lucee.runtime.type.SimpleValue;
034
035public class UDFArgConverter {
036
037        public static String serialize(Object o)  {
038                return serialize(o,new HashSet<Object>());
039        }
040        
041        
042        private static String serialize(Object o,Set<Object> done)  {
043                
044                if(o==null) return "null";
045                Object raw=toRaw(o);
046                
047                if(done.contains(raw)) return "parent reference";
048                done.add(raw);
049                Collection c=null;
050                Object other=null;
051                try{
052                        if((c=Caster.toCollection(o,null))!=null) {
053                                if(o!=c){
054                                        done.add(c);
055                                        other=c;
056                                }
057                                return serializeCollection(c,done);
058                        }
059                        if(o instanceof String) {
060                                return "'"+escape((String)o)+"'";
061                        }
062                        if(o instanceof SimpleValue || o instanceof Number || o instanceof Boolean)
063                                return Caster.toString(o,"");
064                        
065                        return o.toString();
066                }
067                finally {
068                        if(other!=null) done.remove(other);
069                        done.remove(raw);
070                }
071        }
072
073        private static Object toRaw(Object o) {
074                if(o instanceof XMLStruct)return ((XMLStruct)o).toNode();
075                return o;
076        }
077
078
079        private static String serializeCollection(Collection coll, Set<Object> done) {
080                if(coll instanceof Query) {
081                        Query qry=(Query) coll;
082                        StringBuilder sb=new StringBuilder();
083                        
084                        Iterator<Key> it = qry.keyIterator();
085                        Key k;
086                        sb.append("{");
087                        boolean oDoIt=false;
088                        int len=qry.getRecordcount();
089                        while(it.hasNext()) {
090                                k = it.next();
091                            if(oDoIt)sb.append(',');
092                            oDoIt=true;
093                            sb.append(k.getLowerString());
094                    sb.append(":[");
095                                boolean doIt=false;
096                                for(int y=1;y<=len;y++) {
097                                    if(doIt)sb.append(',');
098                                    doIt=true;
099                                    try {
100                                                sb.append(serialize(qry.getAt(k,y),done));
101                                        } catch (PageException e) {
102                                                sb.append(serialize(e.getMessage(),done));
103                                        }
104                                }
105                                sb.append(']');
106                        }
107                        
108                        sb.append('}');
109                        return sb.toString();
110                }
111                
112                
113                StringBuilder sb=new StringBuilder("{");
114                Iterator<Entry<Key, Object>> it = coll.entryIterator();
115                Entry<Key, Object> e;
116                boolean notFirst=false;
117                while(it.hasNext()) {
118                        if(notFirst)sb.append(",");
119                        e=it.next();
120                        sb.append(e.getKey().getLowerString());
121                        sb.append(":");
122                        sb.append(serialize(e.getValue(),done));
123                        notFirst=true;
124                }
125                
126                return sb.append("}").toString();
127        }
128        
129        private static String escape(String str) {
130        return StringUtil.replace(str,"'","''",false);
131    }
132}