/*******************************************************************************
* Copyright (c) 2010 Association for Decentralized Information Management in
* Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.databoard.binding.impl;
import java.util.Objects;
import java.util.Set;
import org.simantics.databoard.adapter.AdaptException;
import org.simantics.databoard.adapter.AdapterFactory;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.RecordBinding;
import org.simantics.databoard.binding.UnionBinding;
import org.simantics.databoard.binding.VariantBinding;
import org.simantics.databoard.binding.error.BindingConstructionException;
import org.simantics.databoard.binding.error.BindingException;
import org.simantics.databoard.binding.factory.BindingRepository;
import org.simantics.databoard.binding.reflection.BindingRequest;
import org.simantics.databoard.binding.reflection.ClassBindingFactory;
import org.simantics.databoard.binding.reflection.VoidBinding;
import org.simantics.databoard.type.Datatype;
import org.simantics.databoard.type.RecordType;
import org.simantics.databoard.type.UnionType;
/**
* ObjectVariantBinding binds VariantType and Object.class.
* The implementation is immutable as Object.class is not a container, it is
* a value.
*
* ObjectVariantBinding understands many classes
* Collections: ArrayList, List, LinkedList, int[], .., other arrays [], Map, TreeMap, HashMap, Set, HashSet, TreeSet,
* Strings: String
* immutable primitives: Integer, Boolean, ...
* mutable primitives: MutableInteger, MutableBoolean, ...
* classes: Record-classes, Bean-Classes, Immutable-Classes
* null
is bound to a void.
*
* @author Toni Kalajainen
*/
public class ObjectVariantBinding extends VariantBinding {
ClassBindingFactory bindingFactory;
AdapterFactory adapterFactory;
public ObjectVariantBinding(ClassBindingFactory bindingFactory, AdapterFactory adapterFactory) {
this.bindingFactory = bindingFactory;
this.adapterFactory = adapterFactory;
}
public ClassBindingFactory getBindingFactory() {
return bindingFactory;
}
public BindingRepository getRepository() {
return bindingFactory.getRepository();
}
@Override
public Object create(Binding srcBinding, Object value) throws BindingException {
if (srcBinding instanceof VoidBinding) return null;
return value;
/* try {
//Annotation[] annotations = new Annotation[ srcBinding.getComponentCount() ];
BindingRequest request = new BindingRequest( value.getClass() );
//request.componentBinding = srcBinding.getComponentCount()>0?srcBinding.getComponentBinding(0):null;
Binding dstBinding = bindingFactory.getBinding( request );
return adapterFactory.adapt(value, srcBinding, dstBinding);
} catch (BindingConstructionException e) {
throw new BindingException(e);
} catch (AdaptException e) {
throw new BindingException(e);
}*/
}
@Override
public Binding getContentBinding(Object variant) throws BindingException {
try {
if (variant==null) return VoidBinding.VOID_BINDING;
BindingRequest request = new BindingRequest(variant.getClass());
return bindingFactory.construct(request);
} catch (BindingConstructionException e) {
throw new BindingException(e);
}
}
@Override
public Datatype getContentType(Object variant) throws BindingException {
return getContentBinding(variant).type();
}
@Override
public Object getContent(Object variant, Binding binding)
throws BindingException {
try {
Binding binding1 = getContentBinding(variant);
Object value1 = variant;
Binding binding2 = binding;
Object value2 = adapterFactory.adapt(value1, binding1, binding2);
return value2;
} catch (AdaptException e) {
throw new BindingException(e);
}
}
@Override
public Object getContent(Object variant)
throws BindingException {
return variant;
}
@Override
public void setContent(Object variant, Binding binding, Object value)
throws BindingException {
if (variant==value) return;
try {
Binding binding1 = getContentBinding(variant);
Datatype type1 = binding1.type();
Binding binding2 = binding;
Datatype type2 = binding2.type();
// New value cannot be assigned to Object from different data type
if (!type1.equals(type2)) {
throw new BindingException("Cannot assign "+value.getClass()+" to "+variant.getClass());
}
// Can only assing to union or record of previous type
if (type1 instanceof RecordType) {
RecordType recordType = (RecordType) type1;
int count = recordType.getComponentCount();
RecordBinding rb1 = (RecordBinding) binding1;
RecordBinding rb2 = (RecordBinding) binding2;
Object resultValues[] = new Object[count];
for (int i=0; i validInstances) throws BindingException {
getContentBinding(obj).assertInstaceIsValid(obj);
}
@Override
public boolean isInstance(Object obj) {
return true;
}
@Override
public boolean isImmutable() {
return true;
}
@Override
protected boolean baseEquals(Object obj) {
ObjectVariantBinding o = (ObjectVariantBinding)obj;
return super.baseEquals( obj ) && o.adapterFactory == adapterFactory && o.bindingFactory == bindingFactory;
}
@Override
public boolean equals(Object o1, Object o2) {
return Objects.equals(o1, o2);
}
}