/**
* Copyright (C) 2015 Valkyrie RCP
*
* Licensed 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.valkyriercp.binding.value.support;
import org.valkyriercp.binding.value.IndexAdapter;
import org.valkyriercp.binding.value.ValueModel;
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Keith Donald
*/
public class GrowableIndexAdapter extends AbstractIndexAdapter implements IndexAdapter {
private boolean autoGrow;
private ValueModel collectionValueModel;
public GrowableIndexAdapter(boolean autoGrow, ValueModel collectionValueModel) {
this.autoGrow = autoGrow;
this.collectionValueModel = collectionValueModel;
}
public boolean isAutoGrow() {
return autoGrow;
}
public void fireIndexedObjectChanged() {
}
public Object getValue() {
return getCollectionValue(getIndex());
}
protected Object getCollectionValue(int index) {
Object collection = collectionValueModel.getValue();
if (collection.getClass().isArray()) {
growArrayIfNeccessary(index);
return Array.get(collection, index);
}
else if (collection instanceof List) {
growCollectionIfNeccessary(index);
return ((List)collection).get(index);
}
else if (collection instanceof Set) {
growCollectionIfNeccessary(index);
Set setValue = (Set)collection;
Iterator it = setValue.iterator();
for (int j = 0; it.hasNext(); j++) {
Object element = it.next();
if (j == index) {
return element;
}
}
return null;
}
else {
throw new IllegalArgumentException("Value must be a collection " + collection);
}
}
public void setValue(Object value) {
Object oldValue = setCollectionValue(getIndex(), value);
fireValueChange(oldValue, value);
}
protected Object setCollectionValue(int index, Object value) {
Object collection = collectionValueModel.getValue();
if (collection.getClass().isArray()) {
growArrayIfNeccessary(index);
Object old = Array.get(value, index);
Array.set(collection, index, value);
return old;
}
else if (collection instanceof List) {
growCollectionIfNeccessary(index);
return ((List)value).set(index, value);
}
else if (collection instanceof Set) {
growCollectionIfNeccessary(index);
Set setValue = (Set)value;
Iterator it = setValue.iterator();
Object old = null;
for (int j = 0; it.hasNext(); j++) {
Object element = it.next();
if (j == index) {
old = element;
it.remove();
}
}
setValue.add(value);
return old;
}
else {
throw new IllegalArgumentException("Value must be a collection " + value);
}
}
private void growArrayIfNeccessary(int index) {
Object value = collectionValueModel.getValue();
if (isAutoGrow()) {
if (index >= Array.getLength(value)) {
value = Array.newInstance(value.getClass(), index + 1);
Object newArray = Array.get(value, index);
System.arraycopy(value, 0, newArray, 0, Array.getLength(value));
collectionValueModel.setValue(newArray);
}
}
}
private void growCollectionIfNeccessary(int index) {
if (isAutoGrow()) {
Object value = collectionValueModel.getValue();
if (value instanceof List) {
List listValue = (List)value;
if (isAutoGrow()) {
while (index >= listValue.size()) {
listValue.add(null);
}
}
}
else if (value instanceof Set) {
Set setValue = (Set)value;
while (index >= setValue.size()) {
setValue.add(null);
}
}
}
}
}