/*******************************************************************************
* 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;
import java.util.IdentityHashMap;
import java.util.Set;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.Datatypes;
import org.simantics.databoard.accessor.reference.ChildReference;
import org.simantics.databoard.adapter.AdaptException;
import org.simantics.databoard.binding.error.BindingException;
import org.simantics.databoard.binding.error.RuntimeBindingException;
import org.simantics.databoard.binding.impl.BindingPrintContext;
import org.simantics.databoard.binding.impl.ObjectVariantBinding;
import org.simantics.databoard.binding.impl.StringVariantBinding;
import org.simantics.databoard.binding.mutable.ImmutableVariantBinding;
import org.simantics.databoard.binding.mutable.MutableVariant;
import org.simantics.databoard.binding.mutable.MutableVariantBinding;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.databoard.type.Datatype;
import org.simantics.databoard.type.VariantType;
import org.simantics.databoard.util.DataValueUtil;
import org.simantics.databoard.util.IdentityPair;
/**
* This is the abstract base class for bindings of VariantType Java Objects.
* Variant is a container that has value of any Datatype.
*
* @see VariantType The Datatype
* @see ImmutableVariantBinding Binds variant to {@link Variant}
* @see MutableVariantBinding Binds variant to {@link MutableVariant}
* @see ObjectVariantBinding Binds variant to java.lang.Object
* @see StringVariantBinding Binds variant to java.lang.String (Filename and URL compatible)
* @author Toni Kalajainen
*/
public abstract class VariantBinding extends Binding {
public VariantBinding()
{
super();
this.type = Datatypes.VARIANT;
}
/**
* Get the value in the variant. The returned value may represent internal
* value of variant.
*
* @param variant the variant object to read the content from
* @param contentBinding the format of return value
* @return value variant's content
* @throws BindingException
*/
public abstract Object getContent(Object variant, Binding contentBinding)
throws BindingException;
/**
* Get the value of the variant. The value is bound with the suggested
* binding, see {@link #getContentBinding(Object)}.
*
* @param variant the variant object
* @return value variant's content
* @throws BindingException
*/
public abstract Object getContent(Object variant)
throws BindingException;
/**
* Get the data type of the content.
*
* @param variant the variant object
* @return the data type
* @throws BindingException
*/
public abstract Datatype getContentType(Object variant)
throws BindingException;
/**
* Return a suggestion for the binding of the content of this variant.
*
* @param variant variant object
* @return binding a binding
*/
public abstract Binding getContentBinding(Object variant)
throws BindingException;
/**
* Create a new variant object.
* The value argument may be included in the result.
*
* @param contentBinding the binding of the content
* @param content content
* @return new variant
* @throws BindingException
*/
public abstract Object create(Binding contentBinding, Object content)
throws BindingException;
/**
* Create a new variant object.
*
* @param contentBinding binding of the content
* @param content content
* @return new variant
* @throws RuntimeBindingException
*/
public Object createUnchecked(Binding contentBinding, Object content)
throws RuntimeBindingException {
try {
return create(contentBinding, content);
} catch (BindingException e) {
throw new RuntimeBindingException(e);
}
}
@Override
public void readFrom(Binding srcBinding, Object src, Object dst)
throws BindingException {
try {
VariantBinding sb = (VariantBinding) srcBinding;
Datatype newType = sb.getContentType(src);
Datatype oldType = getContentType(dst);
Binding scb = sb.getContentBinding(src);
Object sc = sb.getContent(src, scb);
if (newType.equals(oldType)) {
Binding dcb = getContentBinding(dst);
if (dcb.isImmutable()) {
Object dc = Bindings.clone(sc, scb, scb);
setContent(dst, scb, dc);
} else {
Object dc = getContent(dst, dcb);
dc = dcb.readFromTry(scb, sc, dc);
setContent(dst, dcb, dc);
}
} else {
Object dc = Bindings.clone(sc, scb, scb);
setContent(dst, scb, dc);
}
} catch (AdaptException e) {
throw new BindingException(e);
}
}
/**
* Set the content of an variant.
*
* @param variant variant object
* @param contentBinding content's binding
* @param content new content
* @throws BindingException
*/
public abstract void setContent(Object variant, Binding contentBinding, Object content)
throws BindingException;
@Override
public void accept(Visitor1 v, Object obj) {
v.visit(this, obj);
}
@Override
public T accept(Visitor v) {
return v.visit(this);
}
@Override
public int deepHashValue(Object value, IdentityHashMap