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.converter;
020
021import java.io.IOException;
022import java.io.Writer;
023import java.util.HashSet;
024import java.util.Iterator;
025import java.util.Set;
026
027import lucee.runtime.PageContext;
028import lucee.runtime.op.Caster;
029import lucee.runtime.text.xml.struct.XMLStruct;
030import lucee.runtime.type.Array;
031import lucee.runtime.type.Collection.Key;
032import lucee.runtime.type.SimpleValue;
033import lucee.runtime.type.Struct;
034
035public class LazyConverter extends ConverterSupport {
036
037        public static String serialize(Object o)  {
038                return serialize(o,new HashSet<Object>());
039        }
040
041        @Override
042        public void writeOut(PageContext pc, Object source, Writer writer) throws ConverterException, IOException {
043                writer.write(serialize(source));
044                writer.flush();
045        }
046        
047        
048        private static String serialize(Object o,Set<Object> done)  {
049                
050                if(o==null) return "null";
051                Object raw=toRaw(o);
052                
053                if(done.contains(raw)) return "parent reference";
054                done.add(raw);
055                try{
056                         if(o instanceof Array)return serializeArray((Array)o,done);
057                         if(o instanceof Struct){
058                                 return serializeStruct((Struct)o,done);
059                         }
060                         if(o instanceof SimpleValue || o instanceof Number || o instanceof Boolean)return Caster.toString(o,null);
061                         return o.toString();
062                }
063                finally {
064                        done.remove(raw);
065                }
066        }
067
068        public static Object toRaw(Object o) {
069                if(o instanceof XMLStruct)return ((XMLStruct)o).toNode();
070                return o;
071        }
072
073
074        private static String serializeStruct(Struct struct, Set<Object> done) {
075                StringBuilder sb=new StringBuilder("{");
076                Iterator<Key> it = struct.keyIterator();
077                Key key;
078                boolean notFirst=false;
079                while(it.hasNext()) {
080                        if(notFirst)sb.append(", ");
081                        key=it.next();
082                        sb.append(key);
083                        sb.append("={");
084                        sb.append(serialize(struct.get(key,null),done));
085                        sb.append("}");
086                        notFirst=true;
087                }
088                
089                return sb.append("}").toString();
090        }
091
092        private static String serializeArray(Array array, Set<Object> done) {
093                StringBuilder sb=new StringBuilder("[");
094                int len=array.size();
095                for(int i=1;i<=len;i++){
096                        if(i>1)sb.append(", ");
097                        sb.append(serialize(array.get(i,null),done));
098                }
099                return sb.append("]").toString();
100        }
101}