001/*
002 * Copyright 2007 The Kuali Foundation
003 * 
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 * http://www.opensource.org/licenses/ecl2.php
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.ole.module.purap.util;
017
018import java.beans.Beans;
019import java.lang.reflect.InvocationTargetException;
020import java.util.ArrayList;
021
022/**
023 * This class is setup to allow an argument to a created ArrayList (it could be a
024 * possible extension to the other ArrayList
025 */
026public class PurApArrayList extends ArrayList {
027    // private static final long serialVersionUID = 6238521951259126730L;
028    private final Class listObjectType;
029    private final Class[] argumentClasses;
030    private final Object[] arguments;
031
032    /**
033     * Default Constructor
034     *
035     * @param listObjectType the class
036     */
037    public PurApArrayList(Class listObjectType) {
038        this(listObjectType, null, null);
039    }
040
041    /**
042     * Constructor
043     *
044     * @param listObjectType  the object type
045     * @param methodClasses   classes
046     * @param methodArguments arguments
047     */
048    public PurApArrayList(Class listObjectType, Class[] methodClasses, Object[] methodArguments) {
049        super();
050
051        Class[] assignArgumentClasses = null;
052        Object[] assignArguments = null;
053
054        if (listObjectType == null) {
055            throw new RuntimeException("class type for list is required.");
056        }
057
058        // attempt to get an instance of the class to check it has a visible default constructor
059        if (methodClasses == null && methodArguments == null) {
060            try {
061
062                Object listObj = listObjectType.newInstance();
063            } catch (InstantiationException e) {
064                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
065            } catch (IllegalAccessException e) {
066                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
067            }
068        } else {
069            try {
070                listObjectType.getConstructor(methodClasses).newInstance(methodArguments);
071            } catch (SecurityException e) {
072                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
073            } catch (NoSuchMethodException e) {
074                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
075            } catch (IllegalArgumentException e) {
076                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
077            } catch (InstantiationException e) {
078                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
079            } catch (IllegalAccessException e) {
080                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
081            } catch (InvocationTargetException e) {
082                throw new RuntimeException("unable to get instance of class" + listObjectType.getName());
083            }
084            assignArgumentClasses = methodClasses;
085            assignArguments = methodArguments;
086        }
087
088        this.listObjectType = listObjectType;
089        this.argumentClasses = assignArgumentClasses;
090        this.arguments = assignArguments;
091    }
092
093    /**
094     * @see java.util.List#add(int, java.lang.Object)
095     */
096    public void add(int index, Object element) {
097        checkType(element);
098        super.add(index, element);
099    }
100
101    /**
102     * @see java.util.Collection#add(java.lang.Object)
103     */
104    public boolean add(Object o) {
105        checkType(o);
106        return super.add(o);
107    }
108
109    /**
110     * @see java.util.List#get(int)
111     */
112    public Object get(int index) {
113        growArray(index);
114        return super.get(index);
115    }
116
117    /**
118     * @see java.util.List#set(int, java.lang.Object)
119     */
120    public Object set(int index, Object element) {
121        growArray(index);
122        return super.set(index, element);
123    }
124
125
126    /**
127     * Adds new instances of type listObjectType to the arraylist until the size of the list is greater than the index required.
128     *
129     * @param index the index to grow to
130     */
131    private void growArray(int index) {
132        if (index < 0) {
133            throw new IndexOutOfBoundsException("Index must be positive.");
134        }
135        // ensureCapacity(index); // Increments modCount
136
137        while (size() <= index) {
138            try {
139                if (this.arguments == null && this.argumentClasses == null) {
140                    super.add(listObjectType.newInstance());
141                } else {
142                    super.add(listObjectType.getConstructor(argumentClasses).newInstance(arguments));
143                }
144            } catch (InstantiationException e) {
145                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
146            } catch (IllegalAccessException e) {
147                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
148            } catch (IllegalArgumentException e) {
149                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
150            } catch (SecurityException e) {
151                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
152            } catch (InvocationTargetException e) {
153                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
154            } catch (NoSuchMethodException e) {
155                throw new RuntimeException("Cannot get new instance of class " + listObjectType.getName());
156            }
157        }
158    }
159
160
161    /**
162     * Checks the type of an element matches the underlying list type.
163     */
164    private void checkType(Object element) {
165        if (element != null) {
166            if (!Beans.isInstanceOf(element, listObjectType)) {
167                throw new RuntimeException("element is not of correct type.");
168            }
169        }
170    }
171
172    public Class getListObjectType() {
173        return listObjectType;
174    }
175
176}