/*
 * 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.jackrabbit.mk.json.fast;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.apache.jackrabbit.mk.json.JsopBuilder;
import org.apache.jackrabbit.mk.json.JsopTokenizer;

/**
 * An array of objects.
 */
public class JsopArray extends Jsop implements List<Object> {

    private static final ArrayList<String> EMPTY_LIST = new ArrayList<String>();

    private ArrayList<String> list;
    private JsopTokenizer tokenizer;

    public JsopArray(String jsop, int start, int end) {
        super(jsop, start, end);
    }

    public JsopArray() {
        super(null, 0, 0);
        list = new ArrayList<String>();
    }

    public Object get(int index) {
        init();
        String s = load(index);
        if (s == null) {
            throw new IndexOutOfBoundsException(index + " (size: " + list.size() + ")");
        }
        return Jsop.parse(s);
    }

    private String load(int index) {
        if (index < list.size()) {
            return list.get(index);
        }
        while (tokenizer != null) {
            String v = tokenizer.readRawValue();
            list.add(v);
            if (tokenizer.matches(']')) {
                tokenizer = null;
            } else {
                tokenizer.read(',');
            }
            if (index < list.size()) {
                return v;
            }
        }
        return null;
    }

    private void init() {
        if (list != null) {
            return;
        }
        tokenizer = new JsopTokenizer(jsop, start);
        tokenizer.read('[');
        if (tokenizer.matches(']')) {
            list = EMPTY_LIST;
            tokenizer = null;
        } else {
            list = new ArrayList<String>();
        }
    }

    public boolean isEmpty() {
        init();
        return list == EMPTY_LIST;
    }

    public int size() {
        init();
        load(Integer.MAX_VALUE);
        return list.size();
    }

    public String toString() {
        if (jsop == null) {
            JsopBuilder w = new JsopBuilder();
            w.array();
            for (String e : list) {
                w.encodedValue(e);
            }
            w.endArray();
            jsop = w.toString();
            start = 0;
        }
        return jsop.substring(start);
    }

    public boolean add(Object e) {
        initWrite();
        list.add(toString(e));
        return true;
    }

    public void clear() {
        initWrite();
        list.clear();
    }

    private void initWrite() {
        readAll();
        jsop = null;
    }

    private void readAll() {
        load(Integer.MAX_VALUE);
    }

    public void add(int index, Object element) {
        throw new UnsupportedOperationException();
    }

    public boolean addAll(Collection<? extends Object> c) {
        throw new UnsupportedOperationException();
    }

    public boolean addAll(int index, Collection<? extends Object> c) {
        throw new UnsupportedOperationException();
    }

    public boolean contains(Object o) {
        throw new UnsupportedOperationException();
    }

    public boolean containsAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    public int indexOf(Object o) {
        throw new UnsupportedOperationException();
    }

    public Iterator<Object> iterator() {
        throw new UnsupportedOperationException();
    }

    public int lastIndexOf(Object o) {
        throw new UnsupportedOperationException();
    }

    public ListIterator<Object> listIterator() {
        throw new UnsupportedOperationException();
    }

    public ListIterator<Object> listIterator(int index) {
        throw new UnsupportedOperationException();
    }

    public boolean remove(Object o) {
        throw new UnsupportedOperationException();
    }

    public Object remove(int index) {
        throw new UnsupportedOperationException();
    }

    public boolean removeAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    public boolean retainAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    public Object set(int index, Object element) {
        throw new UnsupportedOperationException();
    }

    public List<Object> subList(int fromIndex, int toIndex) {
        throw new UnsupportedOperationException();
    }

    public Object[] toArray() {
        throw new UnsupportedOperationException();
    }

    public <T> T[] toArray(T[] a) {
        throw new UnsupportedOperationException();
    }

}

@@ -4179,32 +4179,386 @@
 t%3E iterator() %7B%0A
+        return new Iterator%3CObject%3E() %7B%0A%0A            int index;%0A%0A            @Override%0A            public boolean hasNext() %7B%0A                return index %3C size();%0A            %7D%0A%0A            @Override%0A            public Object next() %7B%0A                return get(index++);%0A            %7D%0A%0A            @Override%0A            public void remove() %7B%0A        
         throw ne
@@ -4584,32 +4584,58 @@
 ionException();%0A
+            %7D%0A%0A        %7D;%0A
     %7D%0A%0A    publi

Support JsopArray.iterator() (as per Dominiques request :-)