/*
 * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6187118
 * @summary Tests encoding of immutable list that creates itself
 * @run main/othervm Test6187118
 * @author Sergey Malenkov
 */

import java.beans.Encoder;
import java.beans.Expression;
import java.beans.PersistenceDelegate;
import java.beans.XMLEncoder;

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

public final class Test6187118 extends AbstractTest {
    public static void main(String[] args) {
        new Test6187118().test();
    }

    protected ImmutableList<String> getObject() {
        return new ImmutableList<String>();
    }

    protected ImmutableList<String> getAnotherObject() {
        return new ImmutableList<String>().add("1").add("2").add("3").add("4");
    }

    protected void initialize(XMLEncoder encoder) {
        encoder.setPersistenceDelegate(
                ImmutableList.class,
                new PersistenceDelegate() {
                    protected boolean mutatesTo(Object oldInstance, Object newInstance) {
                        return oldInstance.equals(newInstance);
                    }

                    protected Expression instantiate(Object oldInstance, Encoder out) {
                        ImmutableList list = (ImmutableList) oldInstance;
                        if (!list.hasEntries()) {
                            return getExpression(oldInstance, ImmutableList.class, "new");
                        }
                        Object object = list.getLast();
                        ImmutableList shortenedList = list.removeLast();
                        return getExpression(oldInstance, shortenedList, "add", object);
                    }

                    private Expression getExpression(Object value, Object target, String method, Object... args) {
                        return new Expression(value, target, method, args);
                    }
                }
        );
    }

    public static final class ImmutableList<T> implements Iterable {
        private final List<T> list = new ArrayList<T>();

        public ImmutableList() {
        }

        private ImmutableList(Iterable<T> iterable) {
            for (T object : iterable) {
                this.list.add(object);
            }
        }

        public Iterator<T> iterator() {
            return Collections.unmodifiableList(this.list).iterator();
        }

        public ImmutableList<T> add(T object) {
            ImmutableList<T> list = new ImmutableList<T>(this.list);
            list.list.add(object);
            return list;
        }

        public ImmutableList<T> removeLast() {
            ImmutableList<T> list = new ImmutableList<T>(this.list);
            int size = list.list.size();
            if (0 < size) {
                list.list.remove(size - 1);
            }
            return list;
        }

        public T getLast() {
            int size = this.list.size();
            return (0 < size)
                    ? this.list.get(size - 1)
                    : null;
        }

        public boolean hasEntries() {
            return 0 < this.list.size();
        }

        public boolean equals(Object object) {
            if (object instanceof ImmutableList) {
                ImmutableList list = (ImmutableList) object;
                return this.list.equals(list.list);
            }
            return false;
        }

        public int hashCode() {
            return this.list.hashCode();
        }

        public String toString() {
            return this.list.toString();
        }
    }
}
