/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.utils.properties;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PushbackReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * The <code>ConfigurationHandler</code> class implements configuration reading
 * form a <code>java.io.InputStream</code> and writing to a
 * <code>java.io.OutputStream</code> on behalf of the
 * {@code FilePersistenceManager} class.
 *
 * <pre>
 * cfg = prop &quot;=&quot; value .
 *  prop = symbolic-name . // 1.4.2 of OSGi Core Specification
 *  symbolic-name = token { &quot;.&quot; token } .
 *  token = { [ 0..9 ] | [ a..z ] | [ A..Z ] | '_' | '-' } .
 *  value = [ type ] ( &quot;[&quot; values &quot;]&quot; | &quot;(&quot; values &quot;)&quot; | simple ) .
 *  values = simple { &quot;,&quot; simple } .
 *  simple = &quot;&quot;&quot; stringsimple &quot;&quot;&quot; .
 *  type = // 1-char type code .
 *  stringsimple = // quoted string representation of the value .
 * </pre>
 */
public class ConfigurationHandler
{
    protected static final String ENCODING = "UTF-8";

    protected static final int TOKEN_NAME = 'N';
    protected static final int TOKEN_EQ = '=';
    protected static final int TOKEN_ARR_OPEN = '[';
    protected static final int TOKEN_ARR_CLOS = ']';
    protected static final int TOKEN_VEC_OPEN = '(';
    protected static final int TOKEN_VEC_CLOS = ')';
    protected static final int TOKEN_COMMA = ',';
    protected static final int TOKEN_VAL_OPEN = '"'; // '{';
    protected static final int TOKEN_VAL_CLOS = '"'; // '}';
    protected static final int TOKEN_SPACE = ' ';

    protected static final int TOKEN_COMMENT = '#';

    // simple types (string & primitive wrappers)
    protected static final int TOKEN_SIMPLE_STRING = 'T';
    protected static final int TOKEN_SIMPLE_INTEGER = 'I';
    protected static final int TOKEN_SIMPLE_LONG = 'L';
    protected static final int TOKEN_SIMPLE_FLOAT = 'F';
    protected static final int TOKEN_SIMPLE_DOUBLE = 'D';
    protected static final int TOKEN_SIMPLE_BYTE = 'X';
    protected static final int TOKEN_SIMPLE_SHORT = 'S';
    protected static final int TOKEN_SIMPLE_CHARACTER = 'C';
    protected static final int TOKEN_SIMPLE_BOOLEAN = 'B';

    // primitives
    protected static final int TOKEN_PRIMITIVE_INT = 'i';
    protected static final int TOKEN_PRIMITIVE_LONG = 'l';
    protected static final int TOKEN_PRIMITIVE_FLOAT = 'f';
    protected static final int TOKEN_PRIMITIVE_DOUBLE = 'd';
    protected static final int TOKEN_PRIMITIVE_BYTE = 'x';
    protected static final int TOKEN_PRIMITIVE_SHORT = 's';
    protected static final int TOKEN_PRIMITIVE_CHAR = 'c';
    protected static final int TOKEN_PRIMITIVE_BOOLEAN = 'b';

    protected static final String CRLF = "\r\n";
    protected static final String INDENT = "  ";
    protected static final String COLLECTION_LINE_BREAK = " \\\r\n";

    protected static final Map code2Type;
    protected static final Map type2Code;

    // set of valid characters for "symblic-name"
    private static final BitSet NAME_CHARS;
    private static final BitSet TOKEN_CHARS;

    static
    {
        type2Code = new HashMap();

        // simple (exclusive String whose type code is not written)
        type2Code.put( Integer.class, new Integer( TOKEN_SIMPLE_INTEGER ) );
        type2Code.put( Long.class, new Integer( TOKEN_SIMPLE_LONG ) );
        type2Code.put( Float.class, new Integer( TOKEN_SIMPLE_FLOAT ) );
        type2Code.put( Double.class, new Integer( TOKEN_SIMPLE_DOUBLE ) );
        type2Code.put( Byte.class, new Integer( TOKEN_SIMPLE_BYTE ) );
        type2Code.put( Short.class, new Integer( TOKEN_SIMPLE_SHORT ) );
        type2Code.put( Character.class, new Integer( TOKEN_SIMPLE_CHARACTER ) );
        type2Code.put( Boolean.class, new Integer( TOKEN_SIMPLE_BOOLEAN ) );

        // primitives
        type2Code.put( Integer.TYPE, new Integer( TOKEN_PRIMITIVE_INT ) );
        type2Code.put( Long.TYPE, new Integer( TOKEN_PRIMITIVE_LONG ) );
        type2Code.put( Float.TYPE, new Integer( TOKEN_PRIMITIVE_FLOAT ) );
        type2Code.put( Double.TYPE, new Integer( TOKEN_PRIMITIVE_DOUBLE ) );
        type2Code.put( Byte.TYPE, new Integer( TOKEN_PRIMITIVE_BYTE ) );
        type2Code.put( Short.TYPE, new Integer( TOKEN_PRIMITIVE_SHORT ) );
        type2Code.put( Character.TYPE, new Integer( TOKEN_PRIMITIVE_CHAR ) );
        type2Code.put( Boolean.TYPE, new Integer( TOKEN_PRIMITIVE_BOOLEAN ) );

        // reverse map to map type codes to classes, string class mapping
        // to be added manually, as the string type code is not written and
        // hence not included in the type2Code map
        code2Type = new HashMap();
        for ( Iterator ti = type2Code.entrySet().iterator(); ti.hasNext(); )
        {
            Map.Entry entry = ( Map.Entry ) ti.next();
            code2Type.put( entry.getValue(), entry.getKey() );
        }
        code2Type.put( new Integer( TOKEN_SIMPLE_STRING ), String.class );

        NAME_CHARS = new BitSet();
        for ( int i = '0'; i <= '9'; i++ )
            NAME_CHARS.set( i );
        for ( int i = 'a'; i <= 'z'; i++ )
            NAME_CHARS.set( i );
        for ( int i = 'A'; i <= 'Z'; i++ )
            NAME_CHARS.set( i );
        NAME_CHARS.set( '_' );
        NAME_CHARS.set( '-' );
        NAME_CHARS.set( '.' );
        NAME_CHARS.set( '\\' );

        TOKEN_CHARS = new BitSet();
        TOKEN_CHARS.set( TOKEN_EQ );
        TOKEN_CHARS.set( TOKEN_ARR_OPEN );
        TOKEN_CHARS.set( TOKEN_ARR_CLOS );
        TOKEN_CHARS.set( TOKEN_VEC_OPEN );
        TOKEN_CHARS.set( TOKEN_VEC_CLOS );
        TOKEN_CHARS.set( TOKEN_COMMA );
        TOKEN_CHARS.set( TOKEN_VAL_OPEN );
        TOKEN_CHARS.set( TOKEN_VAL_CLOS );
        TOKEN_CHARS.set( TOKEN_SIMPLE_STRING );
        TOKEN_CHARS.set( TOKEN_SIMPLE_INTEGER );
        TOKEN_CHARS.set( TOKEN_SIMPLE_LONG );
        TOKEN_CHARS.set( TOKEN_SIMPLE_FLOAT );
        TOKEN_CHARS.set( TOKEN_SIMPLE_DOUBLE );
        TOKEN_CHARS.set( TOKEN_SIMPLE_BYTE );
        TOKEN_CHARS.set( TOKEN_SIMPLE_SHORT );
        TOKEN_CHARS.set( TOKEN_SIMPLE_CHARACTER );
        TOKEN_CHARS.set( TOKEN_SIMPLE_BOOLEAN );

        // primitives
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_INT );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_LONG );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_FLOAT );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_DOUBLE );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_BYTE );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_SHORT );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_CHAR );
        TOKEN_CHARS.set( TOKEN_PRIMITIVE_BOOLEAN );
    }


    /**
     * Writes the configuration data from the <code>Dictionary</code> to the
     * given <code>OutputStream</code>.
     * <p>
     * This method writes at the current location in the stream and does not
     * close the outputstream.
     *
     * @param out
     *            The <code>OutputStream</code> to write the configurtion data
     *            to.
     * @param properties
     *            The <code>Dictionary</code> to write.
     * @throws IOException
     *             If an error occurrs writing to the output stream.
     */
    public static void write( OutputStream out, Dictionary properties ) throws IOException
    {
        BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( out, ENCODING ) );

        for ( Enumeration ce = orderedKeys(properties); ce.hasMoreElements(); )
        {
            String key = ( String ) ce.nextElement();

            // cfg = prop "=" value "." .
            writeQuoted( bw, key );
            bw.write( TOKEN_EQ );
            writeValue( bw, properties.get( key ) );
            bw.write( CRLF );
        }

        bw.flush();
    }

    public static String write( Object value ) throws IOException
    {
        StringWriter sw = new StringWriter();
        writeValue(sw, value);
        return sw.toString();
    }

    /**
     * Generates an <code>Enumeration</code> for the given
     * <code>Dictionary</code> where the keys of the <code>Dictionary</code>
     * are provided in sorted order.
     *
     * @param properties
     *                   The <code>Dictionary</code> that keys are sorted.
     * @return An <code>Enumeration</code> that provides the keys of
     *         properties in an ordered manner.
     */
    private static Enumeration orderedKeys(Dictionary properties) {
        String[] keyArray = new String[properties.size()];
        int i = 0;
        for ( Enumeration ce = properties.keys(); ce.hasMoreElements(); )
        {
            keyArray[i] = ( String ) ce.nextElement();
            i++;
        }
        Arrays.sort(keyArray);
        return Collections.enumeration( Arrays.asList( keyArray ) );
    }


    /**
     * Reads configuration data from the given <code>InputStream</code> and
     * returns a new <code>Dictionary</code> object containing the data.
     * <p>
     * This method reads from the current location in the stream upto the end of
     * the stream but does not close the stream at the end.
     *
     * @param ins
     *            The <code>InputStream</code> from which to read the
     *            configuration data.
     * @return A <code>Dictionary</code> object containing the configuration
     *         data. This object may be empty if the stream contains no
     *         configuration data.
     * @throws IOException
     *             If an error occurrs reading from the stream. This exception
     *             is also thrown if a syntax error is encountered.
     */
    public static Dictionary read( InputStream ins ) throws IOException
    {
        return new ConfigurationHandler().readInternal( ins );
    }

    public static Object read( String value ) throws IOException
    {
        PushbackReader pr = new PushbackReader( new StringReader( value ), 1 );
        ConfigurationHandler ch = new ConfigurationHandler();
        return ch.readValue(pr);
    }

    // private constructor, this class is not to be instantiated from the
    // outside
    private ConfigurationHandler()
    {
    }

    // ---------- Configuration Input Implementation ---------------------------

    private int token;
    private String tokenValue;
    private int line;
    private int pos;


    private Dictionary readInternal( InputStream ins ) throws IOException
    {
        BufferedReader br = new BufferedReader( new InputStreamReader( ins, ENCODING ) );
        PushbackReader pr = new PushbackReader( br, 1 );

        token = 0;
        tokenValue = null;
        line = 0;
        pos = 0;

        Hashtable configuration = new Hashtable();
        token = 0;
        while ( nextToken( pr, true ) == TOKEN_NAME )
        {
            String key = tokenValue;

            // expect equal sign
            if ( nextToken( pr, false ) != TOKEN_EQ )
            {
                throw readFailure( token, TOKEN_EQ );
            }

            // expect the token value
            Object value = readValue( pr );
            if ( value != null )
            {
                configuration.put( key, value );
            }
        }

        return configuration;
    }


    /**
     * value = type ( "[" values "]" | "(" values ")" | simple ) .
     * values = value { "," value } .
     * simple = "{" stringsimple "}" .
     * type = // 1-char type code .
     * stringsimple = // quoted string representation of the value .
     *
     * @param pr
     * @return
     * @throws IOException
     */
    private Object readValue( PushbackReader pr ) throws IOException
    {
        // read past any whitespace and (optional) type code
        int type = ignorableWhiteSpace( pr );

        // read value kind code if type code is not a value kinde code
        int code;
        if ( code2Type.containsKey( new Integer( type ) ) )
        {
            code = read( pr );
        }
        else
        {
            code = type;
            type = TOKEN_SIMPLE_STRING;
        }

        switch ( code )
        {
            case TOKEN_ARR_OPEN:
                return readArray( type, pr );

            case TOKEN_VEC_OPEN:
                return readCollection( type, pr );

            case TOKEN_VAL_OPEN:
                Object value = readSimple( type, pr );
                ensureNext( pr, TOKEN_VAL_CLOS );
                return value;

            default:
                return null;
        }
    }


    private Object readArray( int typeCode, PushbackReader pr ) throws IOException
    {
        List list = new ArrayList();
        for ( ;; )
        {
            int c = ignorablePageBreakAndWhiteSpace( pr );
            if ( c == TOKEN_VAL_OPEN )
            {
                Object value = readSimple( typeCode, pr );
                if ( value == null )
                {
                    // abort due to error
                    return null;
                }

                ensureNext( pr, TOKEN_VAL_CLOS );

                list.add( value );

                c = ignorablePageBreakAndWhiteSpace( pr );
            }

            if ( c == TOKEN_ARR_CLOS )
            {
                Class type = ( Class ) code2Type.get( new Integer( typeCode ) );
                Object array = Array.newInstance( type, list.size() );
                for ( int i = 0; i < list.size(); i++ )
                {
                    Array.set( array, i, list.get( i ) );
                }
                return array;
            }
            else if ( c < 0 )
            {
                return null;
            }
            else if ( c != TOKEN_COMMA )
            {
                return null;
            }
        }
    }


    private Collection readCollection( int typeCode, PushbackReader pr ) throws IOException
    {
        Collection collection = new ArrayList();
        for ( ;; )
        {
            int c = ignorablePageBreakAndWhiteSpace( pr );
            if ( c == TOKEN_VAL_OPEN )
            {
                Object value = readSimple( typeCode, pr );
                if ( value == null )
                {
                    // abort due to error
                    return null;
                }

                ensureNext( pr, TOKEN_VAL_CLOS );

                collection.add( value );

                c = ignorablePageBreakAndWhiteSpace( pr );
            }

            if ( c == TOKEN_VEC_CLOS )
            {
                return collection;
            }
            else if ( c < 0 )
            {
                return null;
            }
            else if ( c != TOKEN_COMMA )
            {
                return null;
            }
        }
    }


    private Object readSimple( int code, PushbackReader pr ) throws IOException
    {
        switch ( code )
        {
            case -1:
                return null;

            case TOKEN_SIMPLE_STRING:
                return readQuoted( pr );

                // Simple/Primitive, only use wrapper classes
            case TOKEN_SIMPLE_INTEGER:
            case TOKEN_PRIMITIVE_INT:
                return Integer.valueOf( readQuoted( pr ) );

            case TOKEN_SIMPLE_LONG:
            case TOKEN_PRIMITIVE_LONG:
                return Long.valueOf( readQuoted( pr ) );

            case TOKEN_SIMPLE_FLOAT:
            case TOKEN_PRIMITIVE_FLOAT:
                String fString = readQuoted( pr );
                if ( fString.indexOf('.') >= 0 )
                    return Float.valueOf( fString );
                else
                    return Float.intBitsToFloat( Integer.parseInt( fString ) );

            case TOKEN_SIMPLE_DOUBLE:
            case TOKEN_PRIMITIVE_DOUBLE:
                String dString = readQuoted( pr );
                if (dString.indexOf('.') >= 0 )
                    return Double.valueOf( dString );
                else
                    return Double.longBitsToDouble( Long.parseLong( dString ) );

            case TOKEN_SIMPLE_BYTE:
            case TOKEN_PRIMITIVE_BYTE:
                return Byte.valueOf( readQuoted( pr ) );

            case TOKEN_SIMPLE_SHORT:
            case TOKEN_PRIMITIVE_SHORT:
                return Short.valueOf( readQuoted( pr ) );

            case TOKEN_SIMPLE_CHARACTER:
            case TOKEN_PRIMITIVE_CHAR:
                String cString = readQuoted( pr );
                if ( cString != null && cString.length() > 0 )
                {
                    return new Character( cString.charAt( 0 ) );
                }
                return null;

            case TOKEN_SIMPLE_BOOLEAN:
            case TOKEN_PRIMITIVE_BOOLEAN:
                return Boolean.valueOf( readQuoted( pr ) );

                // unknown type code
            default:
                return null;
        }
    }


    private void ensureNext( PushbackReader pr, int expected ) throws IOException
    {
        int next = read( pr );
        if ( next != expected )
        {
            readFailure( next, expected );
        }
    }


    private String readQuoted( PushbackReader pr ) throws IOException
    {
        StringBuffer buf = new StringBuffer();
        for ( ;; )
        {
            int c = read( pr );
            switch ( c )
            {
                // escaped character
                case '\\':
                    c = read( pr );
                    switch ( c )
                    {
                        // well known escapes
                        case 'b':
                            buf.append( '\b' );
                            break;
                        case 't':
                            buf.append( '\t' );
                            break;
                        case 'n':
                            buf.append( '\n' );
                            break;
                        case 'f':
                            buf.append( '\f' );
                            break;
                        case 'r':
                            buf.append( '\r' );
                            break;
                        case 'u':// need 4 characters !
                            char[] cbuf = new char[4];
                            if ( read( pr, cbuf ) == 4 )
                            {
                                c = Integer.parseInt( new String( cbuf ), 16 );
                                buf.append( ( char ) c );
                            }
                            break;

                        // just an escaped character, unescape
                        default:
                            buf.append( ( char ) c );
                    }
                    break;

                // eof
                case -1: // fall through

                // separator token
                case TOKEN_VAL_CLOS:
                    pr.unread( c );
                    return buf.toString();

                // no escaping
                default:
                    buf.append( ( char ) c );
            }
        }
    }

    private String readUnquoted( PushbackReader pr ) throws IOException
    {
        StringBuffer buf = new StringBuffer();
        for ( ;; )
        {
            int c = read( pr );
            switch ( c )
            {
                // escaped character
                case '\\':
                    c = read( pr );
                    switch ( c )
                    {
                        // well known escapes
                        case 'b':
                            buf.append( '\b' );
                            break;
                        case 't':
                            buf.append( '\t' );
                            break;
                        case 'n':
                            buf.append( '\n' );
                            break;
                        case 'f':
                            buf.append( '\f' );
                            break;
                        case 'r':
                            buf.append( '\r' );
                            break;
                        case 'u':// need 4 characters !
                            char[] cbuf = new char[4];
                            if ( read( pr, cbuf ) == 4 )
                            {
                                c = Integer.parseInt( new String( cbuf ), 16 );
                                buf.append( ( char ) c );
                            }
                            break;

                        // just an escaped character, unescape
                        default:
                            buf.append( ( char ) c );
                    }
                    break;

                // eof
                case -1: // fall through

                // separator token
                case TOKEN_SPACE:
                case TOKEN_EQ:
                case TOKEN_VAL_CLOS:
                    pr.unread( c );
                    return buf.toString();

                // no escaping
                default:
                    buf.append( ( char ) c );
            }
        }
    }

    private int nextToken( PushbackReader pr, final boolean newLine ) throws IOException
    {
        int c = ignorableWhiteSpace( pr );

        // immediately return EOF
        if ( c < 0 )
        {
            return ( token = c );
        }

        // check for comment
        if ( newLine && c == TOKEN_COMMENT )
        {
            // skip everything until end of line
            do
            {
                c = read( pr );
            } while ( c != -1 && c != '\n' );
            if ( c == -1 )
            {
                return ( token = c);
            }
            // and start over
            return nextToken( pr, true );
        }

        // check whether there is a name
        if ( NAME_CHARS.get( c ) || !TOKEN_CHARS.get( c ) )
        {
            // read the property name
            pr.unread( c );
            tokenValue = readUnquoted( pr );
            return ( token = TOKEN_NAME );
        }

        // check another token
        if ( TOKEN_CHARS.get( c ) )
        {
            return ( token = c );
        }

        // unexpected character -> so what ??
        return ( token = -1 );
    }


    private int ignorableWhiteSpace( PushbackReader pr ) throws IOException
    {
        int c = read( pr );
        while ( c >= 0 && Character.isWhitespace( ( char ) c ) )
        {
            c = read( pr );
        }
        return c;
    }


    private int ignorablePageBreakAndWhiteSpace( PushbackReader pr ) throws IOException
    {
        int c = ignorableWhiteSpace( pr );
        for ( ;; )
        {
            if ( c != '\\' )
            {
                break;
            }
            int c1 = pr.read();
            if ( c1 == '\r' || c1 == '\n' )
            {
                c = ignorableWhiteSpace( pr );
            } else {
                pr.unread(c1);
                break;
            }
        }
        return c;
    }


    private int read( PushbackReader pr ) throws IOException
    {
        int c = pr.read();
        if ( c == '\r' )
        {
            int c1 = pr.read();
            if ( c1 != '\n' )
            {
                pr.unread( c1 );
            }
            c = '\n';
        }

        if ( c == '\n' )
        {
            line++;
            pos = 0;
        }
        else
        {
            pos++;
        }

        return c;
    }


    private int read( PushbackReader pr, char[] buf ) throws IOException
    {
        for ( int i = 0; i < buf.length; i++ )
        {
            int c = read( pr );
            if ( c >= 0 )
            {
                buf[i] = ( char ) c;
            }
            else
            {
                return i;
            }
        }

        return buf.length;
    }


    private IOException readFailure( int current, int expected )
    {
        return new IOException( "Unexpected token " + current + "; expected: " + expected + " (line=" + line + ", pos="
            + pos + ")" );
    }


    // ---------- Configuration Output Implementation --------------------------

    private static void writeValue( Writer out, Object value ) throws IOException
    {
        Class clazz = value.getClass();
        if ( clazz.isArray() )
        {
            writeArray( out, value );
        }
        else if ( value instanceof Collection )
        {
            writeCollection( out, ( Collection ) value );
        }
        else
        {
            writeType( out, clazz );
            writeSimple( out, value );
        }
    }


    private static void writeArray( Writer out, Object arrayValue ) throws IOException
    {
        int size = Array.getLength( arrayValue );
        writeType( out, arrayValue.getClass().getComponentType() );
        out.write( TOKEN_ARR_OPEN );
        out.write( COLLECTION_LINE_BREAK );
        for ( int i = 0; i < size; i++ )
        {
            writeCollectionElement(out, Array.get( arrayValue, i ));
        }
        out.write( INDENT );
        out.write( TOKEN_ARR_CLOS );
    }


    private static void writeCollection( Writer out, Collection collection ) throws IOException
    {
        if ( collection.isEmpty() )
        {
            out.write( TOKEN_VEC_OPEN );
            out.write( COLLECTION_LINE_BREAK );
            out.write( TOKEN_VEC_CLOS );
        }
        else
        {
            Iterator ci = collection.iterator();
            Object firstElement = ci.next();

            writeType( out, firstElement.getClass() );
            out.write( TOKEN_VEC_OPEN );
            out.write( COLLECTION_LINE_BREAK );

            writeCollectionElement( out, firstElement );

            while ( ci.hasNext() )
            {
                writeCollectionElement( out, ci.next() );
            }
            out.write( TOKEN_VEC_CLOS );
        }
    }


    private static void writeCollectionElement(Writer out, Object element) throws IOException {
        out.write( INDENT );
        writeSimple( out, element );
        out.write( TOKEN_COMMA );
        out.write(COLLECTION_LINE_BREAK);
    }


    private static void writeType( Writer out, Class valueType ) throws IOException
    {
        Integer code = ( Integer ) type2Code.get( valueType );
        if ( code != null )
        {
            out.write( ( char ) code.intValue() );
        }
    }


    private static void writeSimple( Writer out, Object value ) throws IOException
    {
        out.write( TOKEN_VAL_OPEN );
        writeQuoted( out, String.valueOf( value ) );
        out.write( TOKEN_VAL_CLOS );
    }


    private static void writeQuoted( Writer out, String simple ) throws IOException
    {
        if ( simple == null || simple.length() == 0 )
        {
            return;
        }

        char c = 0;
        int len = simple.length();
        for ( int i = 0; i < len; i++ )
        {
            c = simple.charAt( i );
            switch ( c )
            {
                case '\\':
                case TOKEN_VAL_CLOS:
                    out.write( '\\' );
                    out.write( c );
                    break;

                // well known escapes
                case '\b':
                    out.write( "\\b" );
                    break;
                case '\t':
                    out.write( "\\t" );
                    break;
                case '\n':
                    out.write( "\\n" );
                    break;
                case '\f':
                    out.write( "\\f" );
                    break;
                case '\r':
                    out.write( "\\r" );
                    break;

                // other escaping
                default:
                    if ( c < ' ' )
                    {
                        String t = "000" + Integer.toHexString( c );
                        out.write( "\\u" + t.substring( t.length() - 4 ) );
                    }
                    else
                    {
                        out.write( c );
                    }
            }
        }
    }
}
