]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/type/Datatype.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / type / Datatype.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\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
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.type;\r
13 \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
18 \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
25 \r
26 @Union({BooleanType.class,\r
27         ByteType.class,\r
28         IntegerType.class,       \r
29         LongType.class,\r
30         FloatType.class,\r
31         DoubleType.class,\r
32         StringType.class,\r
33         RecordType.class,\r
34         ArrayType.class,\r
35         MapType.class,\r
36         OptionalType.class,\r
37         UnionType.class,\r
38         VariantType.class}) \r
39 public abstract class Datatype implements Cloneable {\r
40         \r
41         public TreeMap<String, String> metadata = new TreeMap<String, String>();\r
42         \r
43         protected void collectSubtypes(Set<Datatype> subtypes, Set<Datatype> recursiveSubtypes) {               \r
44         }\r
45 \r
46         /** \r
47          * Get component type count\r
48          * @return component count\r
49          */\r
50         public abstract int getComponentCount();\r
51         \r
52         /**\r
53          * Get component type\r
54          * @param index component index\r
55          * @return datatype\r
56          */\r
57     public abstract Datatype getComponentType(int index);\r
58     \r
59     /**\r
60      * Get component type\r
61      * @param path child path or <tt>null</tt> to return this.\r
62      * @return datatype\r
63      * @throws IllegalArgumentException if path cannot be applied to this type \r
64      */\r
65     public abstract Datatype getComponentType(ChildReference path);\r
66         \r
67         /**\r
68          * Print the type in data type notation.\r
69          * \r
70          * <a href="http://dev.simantics.org/index.php/Data_type_notation">Datatype Notation</a>\r
71          * \r
72          * See {@link Datatypes#getDatatype(String)} to parse string to data type.\r
73          * \r
74          * @return type\r
75          */\r
76         @Override\r
77         public String toString() {\r
78                 return DataTypePrinter.toString(this, true);\r
79         }\r
80 \r
81         /**\r
82          * Print the type in data type notation.\r
83          * \r
84          * <a href="http://dev.simantics.org/index.php/Data_type_notation">Datatype Notation</a>\r
85          * \r
86          * See {@link Datatypes#getDatatype(String)} to parse string to data type.\r
87          * \r
88          * @return type\r
89          */\r
90         public String toSingleLineString() {\r
91                 return DataTypePrinter.toString(this, false);\r
92         }\r
93         \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
108     }\r
109         \r
110     public abstract void accept(Visitor1 v, Object obj);\r
111     \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
126     }\r
127     \r
128     public abstract <T> T accept(Visitor<T> v); \r
129 \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
135                 if ( s1>0 ) {\r
136                         Iterator<Entry<String, String>> i1 = metadata.entrySet().iterator();\r
137                         Iterator<Entry<String, String>> i2 = other.metadata.entrySet().iterator();\r
138                         \r
139                         while (i1.hasNext() && i2.hasNext()) {\r
140                                 if ( !i1.next().equals( i2.next() ) ) return false;\r
141                         }\r
142                 }                   \r
143                 return true;\r
144     }\r
145     \r
146     /**\r
147      * Deep equals-compare\r
148      * \r
149      * @param obj object to compare with\r
150      * @return true if the object is equal (incl. structurally) with this object\r
151      */\r
152         @Override\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
157         }\r
158         \r
159         @Override\r
160         public int hashCode() {\r
161                 return metadataHashCode();\r
162         }\r
163         \r
164         public int metadataHashCode() {\r
165                 int hash = 13;\r
166                 for (Entry<String, String> e : metadata.entrySet()) {\r
167                         hash *= 13; \r
168                         hash += e.hashCode();\r
169                 }\r
170                 return hash;\r
171         }\r
172         \r
173 //      public boolean isSubtypeOf(DataType type) {\r
174 //              return equals(type);\r
175 //      }\r
176     \r
177     protected abstract boolean deepEquals(Object obj, Set<IdentityPair<Datatype, Datatype>> compareHistory);    \r
178     \r
179     /**\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
184      */\r
185     public abstract <T extends Datatype> T getChildType( ChildReference reference ) throws ReferenceException;\r
186     \r
187 }\r
188 \r