/******************************************************************************* * 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; } }