/******************************************************************************* * Copyright (c) 2010 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.parser.unparsing; import java.util.List; import org.simantics.databoard.parser.StringEscapeUtils; import org.simantics.databoard.parser.ast.type.AstArrayType; import org.simantics.databoard.parser.ast.type.AstAttribute; import org.simantics.databoard.parser.ast.type.AstComponent; import org.simantics.databoard.parser.ast.type.AstRecordType; import org.simantics.databoard.parser.ast.type.AstTupleType; import org.simantics.databoard.parser.ast.type.AstType; import org.simantics.databoard.parser.ast.type.AstTypeDefinition; import org.simantics.databoard.parser.ast.type.AstTypeReference; import org.simantics.databoard.parser.ast.type.AstUnionType; import org.simantics.databoard.parser.repository.DataTypeRepository; import org.simantics.databoard.type.Datatype; /** * Converts abstract syntax tree of data type to string. * * @author Hannu Niemistö */ public class DataTypePrinter { StringBuilder stringBuilder; int indentation = 0; boolean linefeed = true; /** Optional data type repository. If null refered types are inlined */ DataTypeRepository repo; public DataTypePrinter(StringBuilder stringBuilder) { this.stringBuilder = stringBuilder; } public DataTypeRepository getDataTypeRepository() { return repo; } public void setDataTypeRepository(DataTypeRepository repo) { this.repo = repo; } public StringBuilder getStringBuilder() { return stringBuilder; } public void setStringBuilder(StringBuilder stringBuilder) { this.stringBuilder = stringBuilder; } private void indent() { for(int i=0;i clazz = type.getClass(); if(clazz == AstArrayType.class) visit((AstArrayType)type); else if(clazz == AstRecordType.class) visit((AstRecordType)type); else if(clazz == AstTupleType.class) visit((AstTupleType)type); else if(clazz == AstTypeReference.class) visit((AstTypeReference)type); else if(clazz == AstUnionType.class) visit((AstUnionType)type); else throw new AssertionError("Unhandled abstract syntax tree node type."); } public void visit(AstArrayType type) { visit(type.componentType); if(type.minLength == null) { if(type.maxLength == null) stringBuilder.append("[]"); else { stringBuilder.append("[.."); stringBuilder.append(type.maxLength); stringBuilder.append(']'); } } else { if(type.maxLength == null) { stringBuilder.append('['); stringBuilder.append(type.minLength); stringBuilder.append("..]"); } else { stringBuilder.append('['); if(type.minLength.equals(type.maxLength)) stringBuilder.append(type.minLength); else { stringBuilder.append(type.minLength); stringBuilder.append(".."); stringBuilder.append(type.maxLength); } stringBuilder.append(']'); } } } public void visit(AstAttribute attribute) { stringBuilder.append(attribute.key); stringBuilder.append("=\""); stringBuilder.append(StringEscapeUtils.escape(attribute.value)); stringBuilder.append('"'); } public void visit(AstComponent component) { stringBuilder.append(component.name); stringBuilder.append(" : "); visit(component.type); } public void visit(AstRecordType type) { if(type.referable) stringBuilder.append("referable "); if(type.components.isEmpty()) { stringBuilder.append("{}"); } else { stringBuilder.append('{'); if (linefeed) stringBuilder.append('\n'); indentation += 2; for(int i=0;i 0) stringBuilder.append(", "); visit(type.components.get(i)); } stringBuilder.append(')'); } public void visit(AstTypeReference type) { stringBuilder.append(type.name); if(!type.parameters.isEmpty() || !type.attributes.isEmpty()) { stringBuilder.append('('); boolean first = true; for(AstType parameter : type.parameters) { if(first) first = false; else stringBuilder.append(", "); visit(parameter); } for(AstAttribute attribute : type.attributes) { if(first) first = false; else stringBuilder.append(", "); visit(attribute); } stringBuilder.append(')'); } } public void visit(AstUnionType type) { if(type.components.size() == 1) { stringBuilder.append("| "); stringBuilder.append(type.components.get(0).name); stringBuilder.append(' '); visit(type.components.get(0).type); } else { ++indentation; for(AstComponent component : type.components) { if (linefeed) stringBuilder.append('\n'); indent(); stringBuilder.append("| "); stringBuilder.append(component.name); stringBuilder.append(' '); ++indentation; visit(component.type); --indentation; } } --indentation; } /** * Print type * @param type */ public void print(Datatype type) { DataTypeToAst converter = new DataTypeToAst(new DataTypeRepository()); AstType astType = converter.visit(type); visit(astType); } /** * Print type definitions and definitions of referred types * @param type */ public void printDefinitions(Datatype type) { DataTypeToAst converter = new DataTypeToAst(new DataTypeRepository()); visit(converter.visit(type)); List definitions = converter.getTypeDefinitions(); for(AstTypeDefinition def : definitions) visit(def); } @Override public String toString() { return stringBuilder.toString(); } /** * Converts a data type to string. * * @param dataType * @param linefeed if true add line feed * @return data type as string */ public static String toString(Datatype dataType, boolean linefeed) { DataTypePrinter printer = new DataTypePrinter( new StringBuilder() ); printer.setLinefeed( linefeed ); printer.print(dataType); return printer.toString(); } }