X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Futil%2FBean.java;h=258adf2425a9f6ebc63933e145eeb1c0a8cc5724;hb=77921feee3f8331ab54796ff0832921405bea874;hp=bf47f76937774c46c5a31e9423e58e00789d1273;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Bean.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Bean.java index bf47f7693..258adf242 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Bean.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Bean.java @@ -1,640 +1,640 @@ -/******************************************************************************* - * Copyright (c) 2007, 2011 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.util; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.Random; - -import org.simantics.databoard.Bindings; -import org.simantics.databoard.Files; -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.adapter.RuntimeAdaptException; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.OptionalBinding; -import org.simantics.databoard.binding.RecordBinding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.binding.error.RuntimeBindingException; -import org.simantics.databoard.binding.util.RandomValue; -import org.simantics.databoard.parser.repository.DataTypeSyntaxError; -import org.simantics.databoard.parser.repository.DataValueRepository; -import org.simantics.databoard.serialization.Serializer; -import org.simantics.databoard.serialization.SerializerConstructionException; -import org.simantics.databoard.type.Component; -import org.simantics.databoard.type.Datatype; - -/** - * Record classes enable databoard features by sub-classing Bean. - * - * Instructions, the fields must be public, or have public get/setters. - * Sub-class gains the following services: - * - * toString #toString() - * string #print() / #parse() - * Hash-Equals #hashCode() / #equals() - * Comparable #compareTo() - * Serialization #serialize()/#deserialize(), #readObject()/#writeObject(), #readFile()/#writeFile() - * Cloning #clone() / #readFrom() - * Initialization #init() / #setToDefault() / #setToRandom() - * - * The class must be compatible with databoard's type system. - * - * See BeanExample for example. - * - * The identify of this class is composed from all the fields. The identity - * affects to the behavior how hash and equals are counted. - * - * If only some fields compose the hash-equals-compareTo identity, use {@link Bean.Id} instead. - * In this case the identifying fields have @Identity annotation. - * - * Example: - * - * public class MyClass extends Bean.Id { - * public @Identify String id; - * ... - * } - * - * @author toni.kalajainen - */ -public class Bean implements Cloneable, /*Serializable, */Comparable { - - transient protected RecordBinding binding; - - protected Bean() { - this.binding = Bindings.getBindingUnchecked( getClass() ); - } - - protected Bean(Binding binding) { - this.binding = (RecordBinding) binding; - } - - /** - * Return datatype binding to this class. - * - * @return record binding - */ - public RecordBinding getBinding() { - return binding; - } - - /** - * Read all field values from another object. All fields are deep-cloned, - * except immutable values which are referenced. - * - * @param other - */ - public void readFrom(Bean other) { - binding.readFromUnchecked(other.binding, other, this); - } - - public void readAvailableFields(Bean other) { - if ( other.binding instanceof RecordBinding == false ) return; - Component components[] = binding.type().getComponents(); - for (int i=0; i=0; - } - - /** - * Get binding of a field - * - * @param fieldName - * @return binding or null of field does not exist - * @throws BindingException - */ - public Binding getFieldBinding(String fieldName) throws BindingException { - int index = binding.getComponentIndex(fieldName); - if ( index<0 ) return null; - Binding r = binding.getComponentBinding(index); - if ( r!=null && r instanceof OptionalBinding ) { - r = ((OptionalBinding)r).componentBinding; - } - return r; - } - - /** - * Get value of a field - * @param fieldName - * @return value or null if field does not exist - * @throws BindingException - */ - public Object getField(String fieldName) throws BindingException { - int index = binding.type().getComponentIndex2(fieldName); - if (index<0) return null; - return binding.getComponent(this, index); - } - - /** - * Get value of a field - * @param fieldName - * @return value or null if field does not exist - * @throws BindingException - */ - public Object getField(int fieldIndex) throws BindingException { - return binding.getComponent(this, fieldIndex); - } - - /** - * Get value of a field - * @param fieldName - * @param binding requested binding - * @return value or null if field does not exist - * @throws BindingException - */ - public Object getField(String fieldName, Binding binding) throws BindingException { - int index = this.binding.type().getComponentIndex2(fieldName); - if (index<0) return null; - Object obj = this.binding.getComponent(this, index); - if ( obj == null ) return null; - Binding fieldBinding = this.binding.getComponentBinding(index); - if ( fieldBinding instanceof OptionalBinding ) { - fieldBinding = ((OptionalBinding)fieldBinding).componentBinding; - } - try { - return Bindings.adapt(obj, fieldBinding, binding); - } catch (AdaptException e) { - if ( e.getCause() !=null && e.getCause() instanceof BindingException ) throw (BindingException) e.getCause(); - throw new BindingException(e); - } - } - - /** - * Get value of a field - * @param fieldName - * @return value or null if field does not exist - * @throws RuntimeBindingException - */ - public Object getFieldUnchecked(String fieldName) throws RuntimeBindingException { - int index = binding.type().getComponentIndex2(fieldName); - if (index<0) return null; - try { - return binding.getComponent(this, index); - } catch (BindingException e) { - throw new RuntimeBindingException(e); - } - } - - /** - * Get value of a field - * @param fieldName - * @return value or null if field does not exist - * @throws RuntimeBindingException - */ - public Object getFieldUnchecked(int fieldIndex) throws RuntimeBindingException { - try { - return binding.getComponent(this, fieldIndex); - } catch (BindingException e) { - throw new RuntimeBindingException(e); - } - } - - /** - * Get identifier binding. Use @Identifier annotation to indicate which - * fields compose the identifier of the record. - * - * @return idenfitier binding. - * @throws BindingException there is no identifier - */ - public Binding getIdentifierBinding() throws BindingException { - Datatype idType = binding.type().getIdentifierType(); - if (idType == null) throw new BindingException("There is are no @Identifier fields in the bean"); - return Bindings.getBinding( idType ); - } - - /** - * Get identifier of the object. Use @Identifier annotation to indicate which - * fields compose the identifier of the record. - * - * @return identifier - * @throws BindingException - */ - public Object getIdentifier() throws BindingException - { - int ids[] = binding.type().getIdentifiers(); - if (ids.length == 0) throw new BindingException("There is are no @Identifier fields in the bean"); - if (ids.length == 1) return binding.getComponent(this, ids[0]); - RecordBinding rb = (RecordBinding) getIdentifierBinding(); - Object result = rb.createPartial(); - int ix = 0; - for (int i : ids) { - rb.setComponent(result, ix++, binding.getComponent(this, i)); - } - return result; - } - - /** - * In this version of the bean, the hash/equals compares to identifiers. - * Identifier is a field with @Idenfitier annotation. - */ - public static class Id extends Bean { - protected Id() {} - protected Id(Binding binding) { - super(binding); - } - - @Override - public int hashCode() { - int hash = 0; - try { - for (int index : binding.type().getIdentifiers()) - { - Object c = binding.getComponent(this, index); - Binding cb = binding.getComponentBinding(index); - hash = 13*hash + cb.hashValue(c); - } - } catch (BindingException e) { - } - return hash; - } - - /** - * Compare to another bean of same datatype for equal identifier. (Can be different binding) - */ - @Override - public boolean equals(Object obj) { - if (obj==null) return false; - if (obj==this) return true; - if ( obj instanceof Bean == false ) return false; - Bean other = (Bean) obj; - try { - if (other.binding==binding) { - - for (int index : binding.type().getIdentifiers()) - { - Object tc = binding.getComponent(this, index); - Object oc = binding.getComponent(other, index); - Binding cb = binding.getComponentBinding(index); - if ( !cb.equals(tc, oc) ) return false; - } - - } else { - - for (int index : binding.type().getIdentifiers()) - { - Object tc = binding.getComponent(this, index); - Object oc = binding.getComponent(other, index); - Binding tcb = binding.getComponentBinding(index); - Binding ocb = other.binding.getComponentBinding(index); - if ( !Bindings.equals(tcb, tc, ocb, oc) ) return false; - } - } - return true; - } catch (BindingException e) { - throw new RuntimeBindingException(e); - } - } - - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2011 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.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.util.Random; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.Files; +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.adapter.RuntimeAdaptException; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.OptionalBinding; +import org.simantics.databoard.binding.RecordBinding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.error.RuntimeBindingException; +import org.simantics.databoard.binding.util.RandomValue; +import org.simantics.databoard.parser.repository.DataTypeSyntaxError; +import org.simantics.databoard.parser.repository.DataValueRepository; +import org.simantics.databoard.serialization.Serializer; +import org.simantics.databoard.serialization.SerializerConstructionException; +import org.simantics.databoard.type.Component; +import org.simantics.databoard.type.Datatype; + +/** + * Record classes enable databoard features by sub-classing Bean. + * + * Instructions, the fields must be public, or have public get/setters. + * Sub-class gains the following services: + * + * toString #toString() + * string #print() / #parse() + * Hash-Equals #hashCode() / #equals() + * Comparable #compareTo() + * Serialization #serialize()/#deserialize(), #readObject()/#writeObject(), #readFile()/#writeFile() + * Cloning #clone() / #readFrom() + * Initialization #init() / #setToDefault() / #setToRandom() + * + * The class must be compatible with databoard's type system. + * + * See BeanExample for example. + * + * The identify of this class is composed from all the fields. The identity + * affects to the behavior how hash and equals are counted. + * + * If only some fields compose the hash-equals-compareTo identity, use {@link Bean.Id} instead. + * In this case the identifying fields have @Identity annotation. + * + * Example: + * + * public class MyClass extends Bean.Id { + * public @Identify String id; + * ... + * } + * + * @author toni.kalajainen + */ +public class Bean implements Cloneable, /*Serializable, */Comparable { + + transient protected RecordBinding binding; + + protected Bean() { + this.binding = Bindings.getBindingUnchecked( getClass() ); + } + + protected Bean(Binding binding) { + this.binding = (RecordBinding) binding; + } + + /** + * Return datatype binding to this class. + * + * @return record binding + */ + public RecordBinding getBinding() { + return binding; + } + + /** + * Read all field values from another object. All fields are deep-cloned, + * except immutable values which are referenced. + * + * @param other + */ + public void readFrom(Bean other) { + binding.readFromUnchecked(other.binding, other, this); + } + + public void readAvailableFields(Bean other) { + if ( other.binding instanceof RecordBinding == false ) return; + Component components[] = binding.type().getComponents(); + for (int i=0; i=0; + } + + /** + * Get binding of a field + * + * @param fieldName + * @return binding or null of field does not exist + * @throws BindingException + */ + public Binding getFieldBinding(String fieldName) throws BindingException { + int index = binding.getComponentIndex(fieldName); + if ( index<0 ) return null; + Binding r = binding.getComponentBinding(index); + if ( r!=null && r instanceof OptionalBinding ) { + r = ((OptionalBinding)r).componentBinding; + } + return r; + } + + /** + * Get value of a field + * @param fieldName + * @return value or null if field does not exist + * @throws BindingException + */ + public Object getField(String fieldName) throws BindingException { + int index = binding.type().getComponentIndex2(fieldName); + if (index<0) return null; + return binding.getComponent(this, index); + } + + /** + * Get value of a field + * @param fieldName + * @return value or null if field does not exist + * @throws BindingException + */ + public Object getField(int fieldIndex) throws BindingException { + return binding.getComponent(this, fieldIndex); + } + + /** + * Get value of a field + * @param fieldName + * @param binding requested binding + * @return value or null if field does not exist + * @throws BindingException + */ + public Object getField(String fieldName, Binding binding) throws BindingException { + int index = this.binding.type().getComponentIndex2(fieldName); + if (index<0) return null; + Object obj = this.binding.getComponent(this, index); + if ( obj == null ) return null; + Binding fieldBinding = this.binding.getComponentBinding(index); + if ( fieldBinding instanceof OptionalBinding ) { + fieldBinding = ((OptionalBinding)fieldBinding).componentBinding; + } + try { + return Bindings.adapt(obj, fieldBinding, binding); + } catch (AdaptException e) { + if ( e.getCause() !=null && e.getCause() instanceof BindingException ) throw (BindingException) e.getCause(); + throw new BindingException(e); + } + } + + /** + * Get value of a field + * @param fieldName + * @return value or null if field does not exist + * @throws RuntimeBindingException + */ + public Object getFieldUnchecked(String fieldName) throws RuntimeBindingException { + int index = binding.type().getComponentIndex2(fieldName); + if (index<0) return null; + try { + return binding.getComponent(this, index); + } catch (BindingException e) { + throw new RuntimeBindingException(e); + } + } + + /** + * Get value of a field + * @param fieldName + * @return value or null if field does not exist + * @throws RuntimeBindingException + */ + public Object getFieldUnchecked(int fieldIndex) throws RuntimeBindingException { + try { + return binding.getComponent(this, fieldIndex); + } catch (BindingException e) { + throw new RuntimeBindingException(e); + } + } + + /** + * Get identifier binding. Use @Identifier annotation to indicate which + * fields compose the identifier of the record. + * + * @return idenfitier binding. + * @throws BindingException there is no identifier + */ + public Binding getIdentifierBinding() throws BindingException { + Datatype idType = binding.type().getIdentifierType(); + if (idType == null) throw new BindingException("There is are no @Identifier fields in the bean"); + return Bindings.getBinding( idType ); + } + + /** + * Get identifier of the object. Use @Identifier annotation to indicate which + * fields compose the identifier of the record. + * + * @return identifier + * @throws BindingException + */ + public Object getIdentifier() throws BindingException + { + int ids[] = binding.type().getIdentifiers(); + if (ids.length == 0) throw new BindingException("There is are no @Identifier fields in the bean"); + if (ids.length == 1) return binding.getComponent(this, ids[0]); + RecordBinding rb = (RecordBinding) getIdentifierBinding(); + Object result = rb.createPartial(); + int ix = 0; + for (int i : ids) { + rb.setComponent(result, ix++, binding.getComponent(this, i)); + } + return result; + } + + /** + * In this version of the bean, the hash/equals compares to identifiers. + * Identifier is a field with @Idenfitier annotation. + */ + public static class Id extends Bean { + protected Id() {} + protected Id(Binding binding) { + super(binding); + } + + @Override + public int hashCode() { + int hash = 0; + try { + for (int index : binding.type().getIdentifiers()) + { + Object c = binding.getComponent(this, index); + Binding cb = binding.getComponentBinding(index); + hash = 13*hash + cb.hashValue(c); + } + } catch (BindingException e) { + } + return hash; + } + + /** + * Compare to another bean of same datatype for equal identifier. (Can be different binding) + */ + @Override + public boolean equals(Object obj) { + if (obj==null) return false; + if (obj==this) return true; + if ( obj instanceof Bean == false ) return false; + Bean other = (Bean) obj; + try { + if (other.binding==binding) { + + for (int index : binding.type().getIdentifiers()) + { + Object tc = binding.getComponent(this, index); + Object oc = binding.getComponent(other, index); + Binding cb = binding.getComponentBinding(index); + if ( !cb.equals(tc, oc) ) return false; + } + + } else { + + for (int index : binding.type().getIdentifiers()) + { + Object tc = binding.getComponent(this, index); + Object oc = binding.getComponent(other, index); + Binding tcb = binding.getComponentBinding(index); + Binding ocb = other.binding.getComponentBinding(index); + if ( !Bindings.equals(tcb, tc, ocb, oc) ) return false; + } + } + return true; + } catch (BindingException e) { + throw new RuntimeBindingException(e); + } + } + + } + +}