package com.johnuckele.vivarium.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

public class HierarchicalListParser
{

    public static String generateString(List<Object> list)
    {
        if (list == null)
        {
            return "";
        }
        else
        {
            StringBuilder builder = new StringBuilder();
            builder.append('[');
            innerGenerate(list, builder);
            builder.append(']');
            return builder.toString();
        }
    }

    private static void innerGenerate(List<Object> list, StringBuilder builder)
    {
        Iterator<Object> it = list.iterator();
        while (it.hasNext())
        {
            Object o = it.next();
            if (o instanceof List)
            {
                @SuppressWarnings("unchecked")
                List<Object> innerList = (List<Object>) o;
                builder.append('[');
                innerGenerate(innerList, builder);
                builder.append(']');
            }
            else
            {
                builder.append(o);
            }

            if (it.hasNext())
            {
                builder.append(',');
            }
        }
    }

    public static List<Object> parseList(String listString)
    {
        listString = listString.trim();
        if (listString.length() == 0)
        {
            return null;
        }
        else if (listString.charAt(0) == '[' && listString.charAt(listString.length() - 1) == ']')
        {
            StringTokenizer tokenizer = new StringTokenizer(listString, "[,]", true);
            tokenizer.nextToken(); // Pops off the first [ so that the innerParse returns when it hits the last ]
            ArrayList<Object> list = new ArrayList<Object>();
            innerParse(list, tokenizer);
            return list;
        }
        else
        {
            throw new IllegalArgumentException(
                    "String " + listString + " is not in the expected format, lists should be enclosed in brackets");
        }
    }

    private static void innerParse(List<Object> list, StringTokenizer tokenizer)
    {
        boolean emptyString = true;
        while (tokenizer.hasMoreTokens())
        {
            String token = tokenizer.nextToken();
            if (token.equals("["))
            {
                ArrayList<Object> innerList = new ArrayList<Object>();
                list.add(innerList);
                innerParse(innerList, tokenizer);
                emptyString = false;
            }
            else if (token.equals(","))
            {
                if (emptyString)
                {
                    list.add("");
                }
                emptyString = true;
                continue;
            }
            else if (token.equals("]"))
            {
                emptyString = false;
                return;
            }
            else
            {
                emptyString = false;
                list.add(token.trim());
            }
        }
        throw new IllegalStateException("Mismatched braces");
    }
}

@@ -56,24 +56,49 @@
 .ArrayList;%0A
+import java.util.Arrays;%0A
 import java.
@@ -129,16 +129,22 @@
 va.util.
+Linked
 List;%0Aim
@@ -158,31 +158,20 @@
 va.util.
-StringTokenizer
+List
 ;%0A%0Apubli
@@ -1589,195 +1589,987 @@
     
-StringTokenizer tokenizer = new StringTokenizer(listString
+// Replace 'delimiter' tokens with extra characters to use as actual delimiters%0A            listString = listString.replace(%22%5B%22, %22%5B~%22);%0A            listString = listString.replace(%22,%22, %22~,~%22);%0A            listString = listString.replace(%22%5D%22, %22~%5D%22);%0A            listString = listString.replace(%22%5B~~%5D%22
 , %22%5B
-,%5D%22, true);%0A            tokenizer.nextToken(); // Pops off the first %5B so that the innerParse returns when it hits the last %5D
+~%5D%22); // Remove this particular double delimiter%0A            // Remove the first and last trash delimiters to avoid getting empty strings at the start and end%0A            // listString = listString.substring(1, listString.length() - 1);%0A            // Split the strings into tokens, including entries for the token delimiters above%0A            List%3CString%3E tokenList = new LinkedList%3CString%3E(Arrays.asList(listString.split(%22~%22)));%0A            // Discard the first token, which is always a '%5B' so that when the recursive function sees the last '%5D', it%0A            // can return correctly%0A            tokenList.remove(0);%0A            // Parse the token list into the object list
 %0A   
@@ -2595,17 +2595,23 @@
 Object%3E 
-l
+objectL
 ist = ne
@@ -2656,17 +2656,23 @@
 erParse(
-l
+objectL
 ist, tok
@@ -2665,36 +2665,36 @@
 bjectList, token
-izer
+List
 );%0A            r
@@ -2699,17 +2699,23 @@
  return 
-l
+objectL
 ist;%0A   
@@ -2985,33 +2985,30 @@
 st, 
+List%3C
 String
-Tokenizer
+%3E
  token
-izer
+List
 )%0A  
@@ -3071,28 +3071,23 @@
 oken
-izer.hasMoreTokens()
+List.size() %3E 0
 )%0A  
@@ -3130,23 +3130,21 @@
 oken
-izer.nextToken(
+List.remove(0
 );%0A 
@@ -3346,12 +3346,12 @@
 oken
-izer
+List
 );%0A 

Remove of StringTokenizer for GWT support