X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fbinding%2FRecordBinding.java;fp=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fbinding%2FRecordBinding.java;h=416abf8290846ba64dfbef960ccc5f41d89982e2;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/RecordBinding.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/RecordBinding.java new file mode 100644 index 000000000..416abf829 --- /dev/null +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/RecordBinding.java @@ -0,0 +1,420 @@ +/******************************************************************************* + * 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.HashSet; +import java.util.IdentityHashMap; +import java.util.Set; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.accessor.reference.ChildReference; +import org.simantics.databoard.accessor.reference.IndexReference; +import org.simantics.databoard.accessor.reference.LabelReference; +import org.simantics.databoard.accessor.reference.NameReference; +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.type.Component; +import org.simantics.databoard.type.RecordType; +import org.simantics.databoard.util.IdentityHashSet; +import org.simantics.databoard.util.IdentityPair; + + +/** + * This is a binding of a Record Type and a Java Object. + * + * @see RecordType + * @author Hannu Niemisto + * @author Toni Kalajainen + */ +public abstract class RecordBinding extends Binding { + + public Binding[] componentBindings; + + /** + * Get binding by field name + * @param fieldName + * @return binding or null + */ + public Binding getComponentBinding(String fieldName) { + int fieldIndex = type().getComponentIndex2(fieldName); + if (fieldIndex<0) return null; + return getComponentBinding(fieldIndex); + } + + public Object getComponentObject(Object obj, String fieldName) throws BindingException { + int fieldIndex = type().getComponentIndex2(fieldName); + if (fieldIndex<0) return null; + return getComponent(obj, fieldIndex); + } + + public int getComponentIndex(String fieldName) { + return type().getComponentIndex2(fieldName); + } + + public Binding getComponentBinding(int fieldIndex) { + return componentBindings[fieldIndex]; + } + + public Binding[] getComponentBindings() { + return componentBindings; + } + + protected void setComponentBindings(Binding[] componentBindings) { + this.componentBindings = componentBindings; + } + + @Override + public RecordType type() { + return (RecordType) type; + } + + public int getComponentCount() { + return type().getComponentCount(); + } + + public abstract Object getComponent(Object obj, int index) + throws BindingException; + + /** + * Create a record using values. + * + * Note! values may be consumed (used in the result) + * + * @param values + * @return new record + * @throws BindingException + */ + public abstract Object create(Object ... values) + throws BindingException; + + /** + * Creates partial and most likely invalid instance. + * This is used in two-phase construction of recursive instances. + * + * @return instance. + */ + public abstract Object createPartial() throws BindingException; + + public abstract void setComponents(Object obj, Object ... value) throws BindingException; + public abstract void setComponent(Object obj, int index, Object value) throws BindingException; + + public void setComponent(Object obj, String fieldName, Object value) throws BindingException + { + int fieldIndex = type().getComponentIndex2(fieldName); + if ( fieldIndex<0 ) throw new BindingException("Field "+fieldName+" does not exist."); + setComponent(obj, fieldIndex, value); + } + + @Override + public void readFrom(Binding srcBinding, Object src, Object dst) + throws BindingException { + RecordBinding sb = (RecordBinding) srcBinding; + int len = getComponentCount(); + if (sb.getComponentCount()!=len) throw new BindingException("field count mismatch"); + try { + for (int i=0; i T accept(Visitor v) { + return v.visit(this); + } + + /** + * Assert obj is valid Record Type + * + * This asserts all fields are valid. + * + * @throws BindingException + */ + @Override + public void assertInstaceIsValid(Object obj, Set validInstances) throws BindingException { + if (!isInstance(obj)) + throw new BindingException("The object ("+obj+") is not correct instance."); + RecordType type = type(); + int length = type.getComponentCount(); + + if (type.isReferable()) { + if (validInstances==null) { + validInstances = new IdentityHashSet(); + } + if (validInstances.contains(obj)) return; + validInstances.add(obj); + } + + for (int i=0; i hashedObjects) throws BindingException { + if (type().isReferable()) { + if (hashedObjects==null) { + hashedObjects = new IdentityHashMap(1); + } + if (hashedObjects.containsKey(value)) { + return 0; + } else { + hashedObjects.put(value, null); + } + } + + int result = 3; + int len = componentBindings.length; + for (int i=0; i> compareHistory) + throws BindingException { + RecordType rt = (RecordType) type(); + + // Compare History is used to prevent infinite loops + if (rt.isReferable()) { + if (compareHistory==null) { + compareHistory = new HashSet>(); + } + IdentityPair p = new IdentityPair(o1, o2); + if (compareHistory.contains(p)) return 0; + compareHistory.add(p); + } + + int len = rt.getComponentCount(); + for (int i=0; i> compareHistory) { + RecordBinding o = (RecordBinding)obj; + if (!super.deepEquals( obj, compareHistory )) + return false; + + if (componentBindings.length != o.componentBindings.length) return false; + + for (int i = 0; i < componentBindings.length; i++) + if (!componentBindings[i].equals(o.componentBindings[i], compareHistory)) + return false; + + return true; + } + + @Override + public int deepHashCode(IdentityHashMap hashedObjects) { + int code = super.deepHashCode(hashedObjects); + for (int i = 0; i < componentBindings.length; i++) + code = 17 * code + componentBindings[i].hashCode(hashedObjects); + return code; + } +}