001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
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, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.binding.value.support;
017    
018    import java.lang.reflect.Array;
019    import java.util.Iterator;
020    import java.util.List;
021    import java.util.Set;
022    
023    import org.springframework.binding.value.IndexAdapter;
024    import org.springframework.binding.value.ValueModel;
025    
026    /**
027     * @author Keith Donald
028     */
029    public class GrowableIndexAdapter extends AbstractIndexAdapter implements IndexAdapter {
030    
031        private boolean autoGrow;
032    
033        private ValueModel collectionValueModel;
034    
035        public GrowableIndexAdapter(boolean autoGrow, ValueModel collectionValueModel) {
036            this.autoGrow = autoGrow;
037            this.collectionValueModel = collectionValueModel;
038        }
039    
040        public boolean isAutoGrow() {
041            return autoGrow;
042        }
043    
044        public void fireIndexedObjectChanged() {
045        }
046    
047        public Object getValue() {
048            return getCollectionValue(getIndex());
049        }
050    
051        protected Object getCollectionValue(int index) {
052            Object collection = collectionValueModel.getValue();
053            if (collection.getClass().isArray()) {
054                growArrayIfNeccessary(index);
055                return Array.get(collection, index);
056            }
057            else if (collection instanceof List) {
058                growCollectionIfNeccessary(index);
059                return ((List)collection).get(index);
060            }
061            else if (collection instanceof Set) {
062                growCollectionIfNeccessary(index);
063                Set setValue = (Set)collection;
064                Iterator it = setValue.iterator();
065                for (int j = 0; it.hasNext(); j++) {
066                    Object element = it.next();
067                    if (j == index) {
068                        return element;
069                    }
070                }
071                return null;
072            }
073            else {
074                throw new IllegalArgumentException("Value must be a collection " + collection);
075            }
076        }
077    
078        public void setValue(Object value) {
079            Object oldValue = setCollectionValue(getIndex(), value);
080            fireValueChange(oldValue, value);
081        }
082    
083        protected Object setCollectionValue(int index, Object value) {
084            Object collection = collectionValueModel.getValue();
085            if (collection.getClass().isArray()) {
086                growArrayIfNeccessary(index);
087                Object old = Array.get(value, index);
088                Array.set(collection, index, value);
089                return old;
090            }
091            else if (collection instanceof List) {
092                growCollectionIfNeccessary(index);
093                return ((List)value).set(index, value);
094            }
095            else if (collection instanceof Set) {
096                growCollectionIfNeccessary(index);
097                Set setValue = (Set)value;
098                Iterator it = setValue.iterator();
099                Object old = null;
100                for (int j = 0; it.hasNext(); j++) {
101                    Object element = it.next();
102                    if (j == index) {
103                        old = element;
104                        it.remove();
105                    }
106                }
107                setValue.add(value);
108                return old;
109            }
110            else {
111                throw new IllegalArgumentException("Value must be a collection " + value);
112            }
113        }
114    
115        private void growArrayIfNeccessary(int index) {
116            Object value = collectionValueModel.getValue();
117            if (isAutoGrow()) {
118                if (index >= Array.getLength(value)) {
119                    value = Array.newInstance(value.getClass(), index + 1);
120                    Object newArray = Array.get(value, index);
121                    System.arraycopy(value, 0, newArray, 0, Array.getLength(value));
122                    collectionValueModel.setValue(newArray);
123                }
124            }
125        }
126    
127        private void growCollectionIfNeccessary(int index) {
128            if (isAutoGrow()) {
129                Object value = collectionValueModel.getValue();
130                if (value instanceof List) {
131                    List listValue = (List)value;
132                    if (isAutoGrow()) {
133                        while (index >= listValue.size()) {
134                            listValue.add(null);
135                        }
136                    }
137                }
138                else if (value instanceof Set) {
139                    Set setValue = (Set)value;
140                    while (index >= setValue.size()) {
141                        setValue.add(null);
142                    }
143                }
144            }
145        }
146    }