1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.parser.unparsing;
14 import gnu.trove.set.hash.THashSet;
16 import java.util.ArrayList;
17 import java.util.List;
19 import org.simantics.databoard.parser.ast.type.AstArrayType;
20 import org.simantics.databoard.parser.ast.type.AstComponent;
21 import org.simantics.databoard.parser.ast.type.AstRecordType;
22 import org.simantics.databoard.parser.ast.type.AstTupleType;
23 import org.simantics.databoard.parser.ast.type.AstType;
24 import org.simantics.databoard.parser.ast.type.AstTypeDefinition;
25 import org.simantics.databoard.parser.ast.type.AstTypeReference;
26 import org.simantics.databoard.parser.ast.type.AstUnionType;
27 import org.simantics.databoard.parser.repository.DataTypeRepository;
28 import org.simantics.databoard.type.ArrayType;
29 import org.simantics.databoard.type.BooleanType;
30 import org.simantics.databoard.type.ByteType;
31 import org.simantics.databoard.type.Component;
32 import org.simantics.databoard.type.Datatype;
33 import org.simantics.databoard.type.Datatype.Visitor;
34 import org.simantics.databoard.type.DoubleType;
35 import org.simantics.databoard.type.FloatType;
36 import org.simantics.databoard.type.IntegerType;
37 import org.simantics.databoard.type.LongType;
38 import org.simantics.databoard.type.MapType;
39 import org.simantics.databoard.type.NumberType;
40 import org.simantics.databoard.type.OptionalType;
41 import org.simantics.databoard.type.RecordType;
42 import org.simantics.databoard.type.StringType;
43 import org.simantics.databoard.type.UnionType;
44 import org.simantics.databoard.type.VariantType;
47 * Converts data type to abstract syntax tree.
49 * @author Hannu Niemistö
51 public class DataTypeToAst implements Visitor<AstType> {
53 List<AstTypeDefinition> typeDefinitions = new ArrayList<AstTypeDefinition>();
54 DataTypeRepository repo = new DataTypeRepository();
55 THashSet<Datatype> underConstruction = new THashSet<Datatype>();
59 public DataTypeToAst(DataTypeRepository repo) {
63 private String freshTypeName() {
64 return "Temp" + (++id);
67 public AstType addDefinition(String name, Datatype type) {
69 AstType ast = type.accept(this);
70 typeDefinitions.add(new AstTypeDefinition(name, type.accept(this)));
74 public AstType visit(Datatype type) {
75 if(repo.contains(type))
76 return new AstTypeReference(repo.get(type));
77 if(underConstruction.contains(type)) {
78 String name = repo.get(type);
80 name = freshTypeName();
83 underConstruction.remove(type);
84 return new AstTypeReference(name);
87 underConstruction.add(type);
88 AstType ast = type.accept(this);
89 if(!underConstruction.remove(type)) {
90 String name = repo.get(type);
91 typeDefinitions.add(new AstTypeDefinition(name, ast));
92 return new AstTypeReference(name);
100 public AstType visit(ArrayType b) {
101 return new AstArrayType(visit(b.componentType),
102 b.getLength()==null ? null : b.getLength().getLower().smallestIncludedInteger(),
103 b.getLength()==null ? null : b.getLength().getUpper().greatestIncludedInteger());
107 public AstType visit(BooleanType b) {
108 return new AstTypeReference("Boolean");
112 public AstType visit(DoubleType b) {
113 AstTypeReference ref = new AstTypeReference("Double");
115 if( b.metadata.containsKey( NumberType.KEY_RANGE ) )
116 ref.addAttribute("range", b.metadata.get( NumberType.KEY_RANGE ) );
117 if( b.metadata.containsKey( NumberType.KEY_UNIT ) )
118 ref.addAttribute("unit", b.metadata.get( NumberType.KEY_UNIT ));
123 public AstType visit(FloatType b) {
124 AstTypeReference ref = new AstTypeReference("Float");
126 if( b.metadata.containsKey( NumberType.KEY_RANGE ) )
127 ref.addAttribute("range", b.metadata.get( NumberType.KEY_RANGE ) );
128 if( b.metadata.containsKey( NumberType.KEY_UNIT ) )
129 ref.addAttribute("unit", b.metadata.get( NumberType.KEY_UNIT ));
134 public AstType visit(IntegerType b) {
135 AstTypeReference ref = new AstTypeReference("Integer");
137 if( b.metadata.containsKey( NumberType.KEY_RANGE ) )
138 ref.addAttribute("range", b.metadata.get( NumberType.KEY_RANGE ) );
139 if( b.metadata.containsKey( NumberType.KEY_UNIT ) )
140 ref.addAttribute("unit", b.metadata.get( NumberType.KEY_UNIT ));
145 public AstType visit(ByteType b) {
146 return new AstTypeReference("Byte");
150 public AstType visit(LongType b) {
151 AstTypeReference ref = new AstTypeReference("Long");
153 if( b.metadata.containsKey( NumberType.KEY_RANGE ) )
154 ref.addAttribute("range", b.metadata.get( NumberType.KEY_RANGE ) );
155 if( b.metadata.containsKey( NumberType.KEY_UNIT ) )
156 ref.addAttribute("unit", b.metadata.get( NumberType.KEY_UNIT ));
161 public AstType visit(OptionalType b) {
162 return new AstTypeReference("Optional", visit(b.getComponentType()));
166 public AstType visit(RecordType b) {
167 if(b.isTupleType()) {
168 AstTupleType tuple = new AstTupleType(new ArrayList<AstType>(b.getComponentCount()));
169 for(Component component : b.getComponents())
170 tuple.addComponent(visit(component.type));
174 AstRecordType record = new AstRecordType(b.isReferable(), new ArrayList<AstComponent>(b.getComponentCount()));
175 for(Component component : b.getComponents())
176 record.addComponent(component.name, visit(component.type));
182 public AstType visit(StringType b) {
183 AstTypeReference ref = new AstTypeReference("String");
185 if( b.metadata.containsKey( StringType.KEY_MIMETYPE ) )
186 ref.addAttribute("mimeType", b.metadata.get( StringType.KEY_MIMETYPE ));
187 if( b.metadata.containsKey( StringType.KEY_LENGTH ) )
188 ref.addAttribute("length", b.metadata.get( StringType.KEY_LENGTH ));
189 if( b.metadata.containsKey( StringType.KEY_PATTERN ))
190 ref.addAttribute("pattern", b.metadata.get( StringType.KEY_PATTERN ));
195 public AstType visit(UnionType b) {
196 AstUnionType union = new AstUnionType(new ArrayList<AstComponent>(b.components.length));
197 for(Component component : b.components)
198 union.addComponent(component.name, visit(component.type));
203 public AstType visit(VariantType b) {
204 AstTypeReference ref = new AstTypeReference("Variant");
208 public List<AstTypeDefinition> getTypeDefinitions() {
209 return typeDefinitions;
213 public AstType visit(MapType b) {
214 AstTypeReference ref = new AstTypeReference("Map", visit(b.keyType), visit(b.valueType));