1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.databoard.type;
\r
14 import java.util.Iterator;
\r
15 import java.util.Map.Entry;
\r
16 import java.util.Set;
\r
17 import java.util.TreeMap;
\r
19 import org.simantics.databoard.Datatypes;
\r
20 import org.simantics.databoard.accessor.error.ReferenceException;
\r
21 import org.simantics.databoard.accessor.reference.ChildReference;
\r
22 import org.simantics.databoard.annotations.Union;
\r
23 import org.simantics.databoard.parser.unparsing.DataTypePrinter;
\r
24 import org.simantics.databoard.util.IdentityPair;
\r
26 @Union({BooleanType.class,
\r
38 VariantType.class})
\r
39 public abstract class Datatype implements Cloneable {
\r
41 public TreeMap<String, String> metadata = new TreeMap<String, String>();
\r
43 protected void collectSubtypes(Set<Datatype> subtypes, Set<Datatype> recursiveSubtypes) {
\r
47 * Get component type count
\r
48 * @return component count
\r
50 public abstract int getComponentCount();
\r
53 * Get component type
\r
54 * @param index component index
\r
57 public abstract Datatype getComponentType(int index);
\r
60 * Get component type
\r
61 * @param path child path or <tt>null</tt> to return this.
\r
63 * @throws IllegalArgumentException if path cannot be applied to this type
\r
65 public abstract Datatype getComponentType(ChildReference path);
\r
68 * Print the type in data type notation.
\r
70 * <a href="http://dev.simantics.org/index.php/Data_type_notation">Datatype Notation</a>
\r
72 * See {@link Datatypes#getDatatype(String)} to parse string to data type.
\r
77 public String toString() {
\r
78 return DataTypePrinter.toString(this, true);
\r
82 * Print the type in data type notation.
\r
84 * <a href="http://dev.simantics.org/index.php/Data_type_notation">Datatype Notation</a>
\r
86 * See {@link Datatypes#getDatatype(String)} to parse string to data type.
\r
90 public String toSingleLineString() {
\r
91 return DataTypePrinter.toString(this, false);
\r
94 public interface Visitor1 {
\r
95 void visit(ArrayType b, Object obj);
\r
96 void visit(BooleanType b, Object obj);
\r
97 void visit(DoubleType b, Object obj);
\r
98 void visit(FloatType b, Object obj);
\r
99 void visit(IntegerType b, Object obj);
\r
100 void visit(ByteType b, Object obj);
\r
101 void visit(LongType b, Object obj);
\r
102 void visit(OptionalType b, Object obj);
\r
103 void visit(RecordType b, Object obj);
\r
104 void visit(StringType b, Object obj);
\r
105 void visit(UnionType b, Object obj);
\r
106 void visit(VariantType b, Object obj);
\r
107 void visit(MapType b, Object obj);
\r
110 public abstract void accept(Visitor1 v, Object obj);
\r
112 public interface Visitor<T> {
\r
113 T visit(ArrayType b);
\r
114 T visit(BooleanType b);
\r
115 T visit(DoubleType b);
\r
116 T visit(FloatType b);
\r
117 T visit(IntegerType b);
\r
118 T visit(ByteType b);
\r
119 T visit(LongType b);
\r
120 T visit(OptionalType b);
\r
121 T visit(RecordType b);
\r
122 T visit(StringType b);
\r
123 T visit(UnionType b);
\r
124 T visit(VariantType b);
\r
125 T visit(MapType b);
\r
128 public abstract <T> T accept(Visitor<T> v);
\r
130 protected boolean hasEqualMetadata(Object obj) {
\r
131 // Check metadata is equal
\r
132 Datatype other = (Datatype) obj;
\r
133 int s1 = metadata.size(), s2 = other.metadata.size();
\r
134 if ( s1 != s2 ) return false;
\r
136 Iterator<Entry<String, String>> i1 = metadata.entrySet().iterator();
\r
137 Iterator<Entry<String, String>> i2 = other.metadata.entrySet().iterator();
\r
139 while (i1.hasNext() && i2.hasNext()) {
\r
140 if ( !i1.next().equals( i2.next() ) ) return false;
\r
147 * Deep equals-compare
\r
149 * @param obj object to compare with
\r
150 * @return true if the object is equal (incl. structurally) with this object
\r
153 public boolean equals(Object obj) {
\r
154 if (this==obj) return true;
\r
155 if (!this.getClass().isInstance(obj)) return false;
\r
156 return deepEquals(obj, null);
\r
160 public int hashCode() {
\r
161 return metadataHashCode();
\r
164 public int metadataHashCode() {
\r
166 for (Entry<String, String> e : metadata.entrySet()) {
\r
168 hash += e.hashCode();
\r
173 // public boolean isSubtypeOf(DataType type) {
\r
174 // return equals(type);
\r
177 protected abstract boolean deepEquals(Object obj, Set<IdentityPair<Datatype, Datatype>> compareHistory);
\r
180 * Get child by reference
\r
181 * @param reference type reference or null (for this instance)
\r
182 * @return the child type
\r
183 * @throws ReferenceException if child was not found
\r
185 public abstract <T extends Datatype> T getChildType( ChildReference reference ) throws ReferenceException;
\r