1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.binding.reflection;
14 import java.lang.reflect.Array;
15 import java.util.Iterator;
17 import org.simantics.databoard.Bindings;
18 import org.simantics.databoard.adapter.AdaptException;
19 import org.simantics.databoard.adapter.Adapter;
20 import org.simantics.databoard.adapter.AdapterConstructionException;
21 import org.simantics.databoard.binding.ArrayBinding;
22 import org.simantics.databoard.binding.Binding;
23 import org.simantics.databoard.binding.error.BindingException;
24 import org.simantics.databoard.binding.error.UnsupportedOperationException;
25 import org.simantics.databoard.type.ArrayType;
28 * ReflectionArrayBinding binds T[]
30 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
32 public class GenericArrayBinding extends ArrayBinding {
35 Class<?> componentClass;
37 public GenericArrayBinding(Class<?> clazz, ArrayType type, Binding componentBinding) {
38 super(type, componentBinding);
41 this.componentClass = clazz.getComponentType();
45 public Object create() {
46 return Array.newInstance(componentClass, 0);
50 public Object create(int length, Iterator<Object> values) {
51 Object result = Array.newInstance(componentClass, length);
52 for (int i=0; i<length; i++)
53 Array.set(result, i, values.next());
58 public Object create(Object[] array) throws BindingException {
59 int length = array.length;
60 Object result = Array.newInstance(componentClass, length);
61 System.arraycopy(array, 0, result, 0, length);
66 public void readFrom(Binding srcBinding, Object src, Object dst)
67 throws BindingException {
69 ArrayBinding sb = (ArrayBinding) srcBinding;
70 Binding scb = sb.getComponentBinding();
71 Binding dcb = getComponentBinding();
72 Adapter cloner = dcb.isImmutable() ? Bindings.adapterFactory.getAdapter(scb, dcb, false, true) : null;
73 int length = Array.getLength(dst);
74 if (length != sb.size(src)) throw new BindingException(clazz.getName()+" is length immutable");
76 for (int i=0; i<length; i++) {
77 if (dcb.isImmutable()) {
78 Object sc = sb.get(src, i);
79 Object dc = cloner.adapt(sc);
82 Object dc = Array.get(dst, i);
83 Object sc = sb.get(src, i);
84 dc = dcb.readFromTry(scb, sc, dc);
85 Array.set(dst, i, dc);
88 } catch (AdaptException e) {
89 throw new BindingException(e);
90 } catch (AdapterConstructionException e) {
91 throw new BindingException(e);
96 public Object readFromTry(Binding srcBinding, Object src, Object dst)
97 throws BindingException {
99 ArrayBinding sb = (ArrayBinding) srcBinding;
100 Binding scb = sb.getComponentBinding();
101 Binding dcb = getComponentBinding();
102 Adapter cloner = Bindings.adapterFactory.getAdapter(scb, dcb, false, true);
103 int length = Array.getLength(dst);
104 int srcSize = sb.size(src);
106 if (length != srcSize || dcb.isImmutable()) {
107 d = Array.newInstance(componentClass, srcSize);
108 if (dcb.isImmutable()) {
109 for (int i=0; i<srcSize; i++) {
110 Object sc = sb.get(src, i);
111 Object dc = cloner.adapt(sc);
115 int X = Math.min(Array.getLength(dst), srcSize);
116 for (int i=0; i<X; i++) {
117 Object dc = Array.get(dst, i);
118 Object sc = sb.get(src, i);
119 dc = dcb.readFromTry(scb, sc, dc);
122 for (int i=X; i<srcSize; i++) {
123 Object sc = sb.get(src, i);
124 Object dc = cloner.adapt(sc);
130 if (dcb.isImmutable()) {
131 for (int i=0; i<length; i++) {
132 Object sc = sb.get(src, i);
133 Object dc = cloner.adapt(sc);
137 for (int i=0; i<length; i++) {
138 Object dc = Array.get(dst, i);
139 Object sc = sb.get(src, i);
140 dc = dcb.readFromTry(scb, sc, dc);
147 } catch (AdaptException e) {
148 throw new BindingException(e);
149 } catch (AdapterConstructionException e) {
150 throw new BindingException(e);
155 public Object get(Object array, int index) throws BindingException {
156 if (!isInstance(array)) throw new BindingException("Unexpected class "+array.getClass().getSimpleName()+", "+clazz.getSimpleName()+" expected");
157 return Array.get(array, index);
161 public void getAll(Object array, Object[] result) throws BindingException {
162 int length = Array.getLength(array);
163 System.arraycopy(array, 0, result, 0, length);
167 public void set(Object array, int index, Object value)
168 throws BindingException {
169 if (index<0 || index>Array.getLength(array))
170 throw new BindingException("Index out of bounds");
171 Array.set(array, index, value);
175 public int size(Object array) throws BindingException {
176 if (!isInstance(array)) {
178 throw new BindingException("Tried to calculate the size of a null array.");
179 throw new BindingException("Unexpected class "+array.getClass().getSimpleName()+", "+clazz.getSimpleName()+" expected");
181 return Array.getLength(array);
184 public boolean isInstance(Object obj) {
185 return clazz.isInstance(obj);
189 public boolean isImmutable() {
194 public void add(Object array, int index, Object element)
195 throws BindingException, IndexOutOfBoundsException {
196 throw new UnsupportedOperationException();
200 public void remove(Object array, int index, int count)
201 throws BindingException, IndexOutOfBoundsException {
202 throw new UnsupportedOperationException();
206 public void setSize(Object array, int newSize) throws BindingException {
207 int oldSize = Array.getLength(array);
208 if (oldSize==newSize) return;
209 throw new BindingException(clazz.getName()+" is length immutable");
213 public boolean isResizable() {
218 protected boolean baseEquals(Object obj) {
219 return super.baseEquals(obj) && ((GenericArrayBinding)obj).clazz.equals(clazz);
223 public int baseHashCode() {
224 return super.baseHashCode() + 13 * clazz.hashCode();