/*
 * $Id$ [23-Apr-2004]
 *
 * Copyright (c) 2004, Ben Fortuna
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  o Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 *  o Neither the name of Ben Fortuna nor the names of any other contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package net.fortuna.ical4j.model;

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

/**
 * Defines a list of iCalendar categories.
 * 
 * @author Ben Fortuna
 */
public class CategoryList implements Serializable {
    
    private static final long serialVersionUID = 4387692697196974638L;

    private List categories;

    /**
     * Default constructor.
     */
    public CategoryList() {
        categories = new ArrayList();
    }

    /**
     * Parses the specified string representation to create
     * a list of categories.
     * @param aValue a string representation of a list of
     * categories
     */
    public CategoryList(final String aValue) {
        categories = new ArrayList();

        for (StringTokenizer t = new StringTokenizer(aValue, ","); t
                .hasMoreTokens();) {
            categories.add(t.nextToken());
        }
    }

    /**
     * @see java.util.AbstractCollection#toString()
     */
    public final String toString() {

        StringBuffer b = new StringBuffer();

        for (Iterator i = categories.iterator(); i.hasNext();) {

            b.append(i.next());

            if (i.hasNext()) {
                b.append(',');
            }
        }

        return b.toString();
    }

    /**
     * Add an address to the list.
     * @param category the category to add
     * @return true
     * @see List#add(java.lang.Object)
     */
    public final boolean add(final String category) {
        return categories.add(category);
    }

    /**
     * @return boolean indicates if the list is empty
     * @see List#isEmpty()
     */
    public final boolean isEmpty() {
        return categories.isEmpty();
    }

    /**
     * @return an iterator
     * @see List#iterator()
     */
    public final Iterator iterator() {
        return categories.iterator();
    }

    /**
     * Remove a category from the list.
     * @param category the category to remove
     * @return true if the list contained the specified category
     * @see List#remove(java.lang.Object)
     */
    public final boolean remove(final String category) {
        return categories.remove(category);
    }

    /**
     * @return the number of categories in the list
     * @see List#size()
     */
    public final int size() {
        return categories.size();
    }
}

@@ -1045,17 +1045,16 @@
 CLAIMED.
- 
  IN NO E
@@ -1744,31 +1744,102 @@
 va.util.
-StringTokenizer
+regex.Matcher;%0Aimport java.util.regex.Pattern;%0A%0Aimport net.fortuna.ical4j.util.Strings
 ;%0A%0A/**%0A 
@@ -1884,12 +1884,8 @@
 es.%0A
- * %0A
  * @
@@ -1959,20 +1959,16 @@
 zable %7B%0A
-    
 %0A    pri
@@ -2246,23 +2246,16 @@
 o create
-%0A     *
  a list 
@@ -2326,23 +2326,16 @@
  list of
-%0A     *
  categor
@@ -2444,68 +2444,275 @@
     
-for (StringTokenizer t = new StringTokenizer(aValue, %22,%22); t
+Pattern pattern = Pattern.compile(%22(%5B%5E%5C%5C%5C%5C%5D(%5C%5C%5C%5C)%7B2%7D?),%22);%0A        Matcher matcher = pattern.matcher(aValue);%0A        String%5B%5D categoryValues = null;%0A%0A        if (matcher.find()) %7B%0A            categoryValues = matcher.replaceAll(%22$1&quot;%22).split(%22&quot;%22);%0A        %7D
 %0A   
@@ -2716,24 +2716,31 @@
         
+else %7B%0A
         
 .hasMore
@@ -2735,68 +2735,178 @@
     
-.hasMoreTokens();) %7B%0A            categories.add(t.nextToken(
+    categoryValues = aValue.split(%22,%22);%0A        %7D%0A%0A        for (int i = 0; i %3C categoryValues.length; i++) %7B%0A            categories.add(Strings.unescape(categoryValues%5Bi%5D
 ));%0A
@@ -3069,25 +3069,24 @@
 ngBuffer();%0A
-%0A
         for 
@@ -3134,25 +3134,24 @@
 sNext();) %7B%0A
-%0A
             
@@ -3159,16 +3159,40 @@
 .append(
+Strings.escape((String) 
 i.next()
@@ -3192,18 +3192,18 @@
 .next())
+)
 ;
-%0A
 %0A       
@@ -3273,33 +3273,32 @@
     %7D%0A        %7D%0A
-%0A
         return b

Use regular expressions to parse category list