]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/SignatureVisitor.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / classfactory / SignatureVisitor.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.binding.classfactory;
13
14 import java.util.IdentityHashMap;
15
16 import org.simantics.databoard.Datatypes;
17 import org.simantics.databoard.type.ArrayType;
18 import org.simantics.databoard.type.BooleanType;
19 import org.simantics.databoard.type.ByteType;
20 import org.simantics.databoard.type.Datatype;
21 import org.simantics.databoard.type.DoubleType;
22 import org.simantics.databoard.type.FloatType;
23 import org.simantics.databoard.type.IntegerType;
24 import org.simantics.databoard.type.LongType;
25 import org.simantics.databoard.type.MapType;
26 import org.simantics.databoard.type.OptionalType;
27 import org.simantics.databoard.type.RecordType;
28 import org.simantics.databoard.type.StringType;
29 import org.simantics.databoard.type.UnionType;
30 import org.simantics.databoard.type.VariantType;
31
32 /**
33  * Signature Visitor builds a signature string from a datatype.
34  * The argument is StringBuilder.
35  * 
36  * Signature is construtructed with the following notation.
37  * 
38  *   s                        StringType
39  *   z                        BooleanType
40  *   d                        DoubleType
41  *   f                        FloatType
42  *   i                        IntegerType
43  *   b                        ByteType
44  *   j                        LongType
45  *   R                        Referable RecordType
46  *   o*                       OptionalType, * denotes componentType
47  *   a*                       ArrayType, * denotes componentType
48  *   r**e                     RecordType, ** denotes fields
49  *   u                        UnionType, * denotes components
50  *   m**                      MapType, ** denotes keyType and valueType
51  *   t                        Datatype
52  *   
53  * For example, The signature of UUID.class is "rjje" 
54  * 
55  * @author toni.kalajainen
56  */
57 public class SignatureVisitor implements Datatype.Visitor1 {
58         
59         public StringBuilder sb = new StringBuilder();
60         public int hashcode = 0xbcbcbca;
61         public IdentityHashMap<Datatype, Boolean> visited = new IdentityHashMap<Datatype, Boolean>();
62         
63         public static String toSignature(Datatype type)
64         {
65                 SignatureVisitor sv = new SignatureVisitor();
66                 type.accept( sv, null );
67                 String sig = sv.sb.toString();
68                 return sig;
69         }       
70
71         @Override
72         public void visit(ArrayType b, Object obj) {
73                 sb.append('a');
74                 b.componentType.accept(this, obj);
75                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
76         }
77
78         @Override
79         public void visit(BooleanType b, Object obj) {
80                 sb.append('z');
81                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
82         }
83
84         @Override
85         public void visit(DoubleType b, Object obj) {
86                 sb.append('d');
87                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
88         }
89
90         @Override
91         public void visit(FloatType b, Object obj) {
92                 sb.append('f');
93                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
94         }
95
96         @Override
97         public void visit(IntegerType b, Object obj) {
98                 sb.append('i');
99                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
100         }
101
102         @Override
103         public void visit(ByteType b, Object obj) {
104                 sb.append('b');
105                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
106         }
107
108         @Override
109         public void visit(LongType b, Object obj) {
110                 sb.append('j');
111                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
112         }
113
114         @Override
115         public void visit(OptionalType b, Object obj) {
116                 sb.append('o');
117                 b.componentType.accept(this, sb);
118                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
119         }
120
121         @Override
122         public void visit(RecordType b, Object obj) {
123                 if ( wasVisited(b) ) {
124                         sb.append('R');
125                         return;
126                 }
127                 if ( b.isReferable() ) {
128                         sb.append('R');
129                         return;
130                 }
131                 
132                 sb.append('r');
133                 for (int i=0; i<b.getComponentCount(); i++) {
134                         b.getComponentType(i).accept(this, sb);
135                 }
136                 sb.append('e');
137
138                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
139                 for (int i=0; i<b.getComponentCount(); i++) {
140                         hashcode = 13*hashcode + b.getComponent(i).name.hashCode();
141                 }
142         }
143
144         @Override
145         public void visit(StringType b, Object obj) {
146                 sb.append('s');
147                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
148         }
149
150         @Override
151         public void visit(UnionType b, Object obj) {
152                 if ( b.equals( Datatypes.getDatatypeUnchecked(Datatype.class) )) {
153                         sb.append("t");
154                         return;
155                 }
156                 if ( wasVisited(b) ) {
157                         sb.append('U');
158                         return;
159                 }
160                 sb.append('u');
161                 for (int i=0; i<b.getComponentCount(); i++) {
162                         b.getComponentType(i).accept(this, sb);
163                 }
164                 sb.append('e');
165                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
166         }
167
168         @Override
169         public void visit(VariantType b, Object obj) {
170                 sb.append('v');
171                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
172         }
173
174         @Override
175         public void visit(MapType b, Object obj) {
176                 if ( wasVisited(b) ) return;
177                 sb.append('m');
178                 b.keyType.accept(this, obj);
179                 b.valueType.accept(this, obj);
180                 hashcode = 13*hashcode + b.getClass().getName().hashCode() + 133*b.metadataHashCode();
181         }
182         
183         /**
184          * Visit and return if was visited
185          * @param type
186          * @return
187          */
188         boolean wasVisited(Datatype type) {
189                 Boolean result = visited.put(type, Boolean.TRUE);
190                 return result == null ? false : result;
191         }
192 }