/*******************************************************************************
* 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();
}
}