org.obeonetwork.m2doc.test.TemplateAstSerializer.java Source code

Java tutorial

Introduction

Here is the source code for org.obeonetwork.m2doc.test.TemplateAstSerializer.java

Source

/*******************************************************************************
 *  Copyright (c) 2016 Obeo. 
 *  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:
 *       Obeo - initial API and implementation
 *  
 *******************************************************************************/
package org.obeonetwork.m2doc.test;

import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.eclipse.acceleo.query.ast.Binding;
import org.eclipse.acceleo.query.ast.BooleanLiteral;
import org.eclipse.acceleo.query.ast.Call;
import org.eclipse.acceleo.query.ast.CallType;
import org.eclipse.acceleo.query.ast.CollectionTypeLiteral;
import org.eclipse.acceleo.query.ast.EnumLiteral;
import org.eclipse.acceleo.query.ast.Error;
import org.eclipse.acceleo.query.ast.Expression;
import org.eclipse.acceleo.query.ast.IntegerLiteral;
import org.eclipse.acceleo.query.ast.Lambda;
import org.eclipse.acceleo.query.ast.Let;
import org.eclipse.acceleo.query.ast.NullLiteral;
import org.eclipse.acceleo.query.ast.RealLiteral;
import org.eclipse.acceleo.query.ast.SequenceInExtensionLiteral;
import org.eclipse.acceleo.query.ast.SetInExtensionLiteral;
import org.eclipse.acceleo.query.ast.StringLiteral;
import org.eclipse.acceleo.query.ast.TypeLiteral;
import org.eclipse.acceleo.query.ast.TypeSetLiteral;
import org.eclipse.acceleo.query.ast.VarRef;
import org.eclipse.acceleo.query.ast.VariableDeclaration;
import org.eclipse.acceleo.query.ast.util.AstSwitch;
import org.eclipse.acceleo.query.runtime.IQueryBuilderEngine.AstResult;
import org.eclipse.emf.ecore.EClassifier;
import org.obeonetwork.m2doc.template.Block;
import org.obeonetwork.m2doc.template.Bookmark;
import org.obeonetwork.m2doc.template.Cell;
import org.obeonetwork.m2doc.template.Conditional;
import org.obeonetwork.m2doc.template.DocumentTemplate;
import org.obeonetwork.m2doc.template.IConstruct;
import org.obeonetwork.m2doc.template.Image;
import org.obeonetwork.m2doc.template.Link;
import org.obeonetwork.m2doc.template.Query;
import org.obeonetwork.m2doc.template.Repetition;
import org.obeonetwork.m2doc.template.Representation;
import org.obeonetwork.m2doc.template.Row;
import org.obeonetwork.m2doc.template.StaticFragment;
import org.obeonetwork.m2doc.template.Table;
import org.obeonetwork.m2doc.template.TableClient;
import org.obeonetwork.m2doc.template.Template;
import org.obeonetwork.m2doc.template.UserDoc;
import org.obeonetwork.m2doc.template.util.TemplateSwitch;

/**
 * Serialize a {@link Template}.
 * 
 * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
 */
public class TemplateAstSerializer extends TemplateSwitch<Void> {

    /**
     * Serialize a {@link Expression}.
     * 
     * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
     */
    private final class QueryAstSerializer extends AstSwitch<Void> {

        /**
         * The {@link StringBuilder} used to serialize.
         */
        private StringBuilder builder;

        /**
         * Serializes the given {@link Expression}.
         * 
         * @param expression
         *            the {@link Expression}
         * @return the serialized {@link Expression}
         */
        public String serialize(Expression expression) {
            builder = new StringBuilder();

            doSwitch(expression);

            return builder.toString();
        }

        @Override
        public Void caseBinding(Binding binding) {
            builder.append(binding.getName());
            if (binding.getType() != null) {
                builder.append(" : ");
                builder.append(doSwitch(binding.getType()));
            }
            builder.append(" = ");
            builder.append(doSwitch(binding.getValue()));
            return null;
        }

        @Override
        public Void caseBooleanLiteral(BooleanLiteral booleanLiteral) {
            builder.append(booleanLiteral.isValue());
            return null;
        }

        @Override
        public Void caseCall(Call call) {
            if (call.getType() == CallType.COLLECTIONCALL) {
                builder.append("->");
            } else {
                builder.append(".");
            }
            builder.append(call.getServiceName());
            builder.append("(");
            final StringBuilder previousBuilder = builder;
            builder = new StringBuilder();
            for (Expression argument : call.getArguments()) {
                doSwitch(argument);
                builder.append(", ");
            }
            if (builder.length() > 0) {
                previousBuilder.append(builder.substring(0, builder.length() - 2));
            }
            builder = previousBuilder;
            builder.append(")");
            return null;
        }

        @Override
        public Void caseCollectionTypeLiteral(CollectionTypeLiteral collectionTypeLiteral) {
            if (collectionTypeLiteral.getValue() == List.class) {
                builder.append("Sequence(");
            } else if (collectionTypeLiteral.getValue() == Set.class) {
                builder.append("OrderedSet(");
            } else {
                builder.append("***invalid type of collection ***(");
            }
            doSwitch(collectionTypeLiteral.getElementType());
            builder.append("");
            return null;
        }

        @Override
        public Void caseConditional(org.eclipse.acceleo.query.ast.Conditional conditional) {
            builder.append("if (");
            doSwitch(conditional.getPredicate());
            builder.append(") then ");
            doSwitch(conditional.getTrueBranch());
            builder.append(" else ");
            doSwitch(conditional.getFalseBranch());
            builder.append(" endif ");
            return null;
        }

        @Override
        public Void caseEnumLiteral(EnumLiteral enumLiteral) {
            builder.append(enumLiteral.getLiteral().getEEnum().getEPackage().getName());
            builder.append("::");
            builder.append(enumLiteral.getLiteral().getEEnum().getName());
            builder.append("::");
            builder.append(enumLiteral.getLiteral().getName());
            return null;
        }

        @Override
        public Void caseError(Error error) {
            builder.append("***ERROR***");
            return null;
        }

        @Override
        public Void caseIntegerLiteral(IntegerLiteral object) {
            builder.append(object.getValue());
            return null;
        }

        @Override
        public Void caseLambda(Lambda lambda) {
            doSwitch(lambda.getParameters().get(0));
            builder.append(" | ");
            doSwitch(lambda.getExpression());
            return null;
        }

        @Override
        public Void caseLet(Let let) {
            builder.append("let ");
            final StringBuilder previousBuilder = builder;
            builder = new StringBuilder();
            for (Binding binding : let.getBindings()) {
                doSwitch(binding);
                builder.append(", ");
            }
            previousBuilder.append(builder.substring(0, builder.length() - 2));
            builder.append(" in ");
            doSwitch(let.getBody());
            return super.caseLet(let);
        }

        @Override
        public Void caseNullLiteral(NullLiteral nullLiteral) {
            builder.append("null");
            return null;
        }

        @Override
        public Void caseSequenceInExtensionLiteral(SequenceInExtensionLiteral sequenceInExtensionLiteral) {
            builder.append("Sequence{");
            final StringBuilder previousBuilder = builder;
            builder = new StringBuilder();
            for (Expression value : sequenceInExtensionLiteral.getValues()) {
                doSwitch(value);
                builder.append(", ");
            }
            previousBuilder.append(builder.substring(0, builder.length() - 2));
            builder.append("}");
            return null;
        }

        @Override
        public Void caseRealLiteral(RealLiteral realLiteral) {
            builder.append(realLiteral.getValue());
            return null;
        }

        @Override
        public Void caseSetInExtensionLiteral(SetInExtensionLiteral setInExtensionLiteral) {
            builder.append("OrderedSet{");
            final StringBuilder previousBuilder = builder;
            builder = new StringBuilder();
            for (Expression value : setInExtensionLiteral.getValues()) {
                doSwitch(value);
                builder.append(", ");
            }
            previousBuilder.append(builder.substring(0, builder.length() - 2));
            builder.append("}");
            return null;
        }

        @Override
        public Void caseStringLiteral(StringLiteral stringLiteral) {
            builder.append("'");
            builder.append(stringLiteral.getValue());
            builder.append("'");
            return null;
        }

        @Override
        public Void caseTypeSetLiteral(TypeSetLiteral typeSetLiteral) {
            builder.append("{");
            final StringBuilder previousBuilder = builder;
            builder = new StringBuilder();
            for (TypeLiteral type : typeSetLiteral.getTypes()) {
                doSwitch(type);
                builder.append(" | ");
            }
            previousBuilder.append(builder.substring(0, builder.length() - 3));
            builder.append("}");
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.acceleo.query.ast.util.AstSwitch#caseTypeLiteral(org.eclipse.acceleo.query.ast.TypeLiteral)
         */
        @Override
        public Void caseTypeLiteral(TypeLiteral object) {
            if (object.getValue() instanceof Class) {
                builder.append(((Class<?>) object.getValue()).getName());
            } else if (object.getValue() instanceof EClassifier) {
                builder.append(((EClassifier) object.getValue()).getName());
            }
            return null;
        }

        @Override
        public Void caseVariableDeclaration(VariableDeclaration variableDeclaration) {
            builder.append(variableDeclaration.getName());
            if (variableDeclaration.getType() != null) {
                builder.append(" : ");
                doSwitch(variableDeclaration.getType());
            }
            builder.append(" = ");
            doSwitch(variableDeclaration.getExpression());
            return null;
        }

        @Override
        public Void caseVarRef(VarRef varRef) {
            builder.append(varRef.getVariableName());
            return null;
        }

    }

    /**
     * The {@link StringBuilder} used to serialize.
     */
    private StringBuilder builder;

    /**
     * The {@link QueryAstSerializer}.
     */
    private QueryAstSerializer querySerializer = new QueryAstSerializer();

    /**
     * Current indentation.
     */
    private String indentation;

    /**
     * Increases indentation.
     */
    protected void indent() {
        indentation = indentation + "  ";
    }

    /**
     * Decreases indentation.
     */
    protected void deindent() {
        indentation = indentation.substring(0, indentation.length() - 2);
    }

    /**
     * Serializes the given {@link DocumentTemplate}.
     * 
     * @param documentTemplate
     *            the {@link DocumentTemplate}
     * @return the serialized {@link DocumentTemplate}
     */
    public String serialize(DocumentTemplate documentTemplate) {
        builder = new StringBuilder();
        indentation = "";

        doSwitch(documentTemplate);

        return builder.toString();
    }

    /**
     * Creates a new line with the right indentation.
     */
    protected void newLine() {
        builder.append("\n" + indentation);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.obeonetwork.m2doc.template.util.TemplateSwitch#caseDocumentTemplate(org.obeonetwork.m2doc.template.DocumentTemplate)
     */
    @Override
    public Void caseDocumentTemplate(DocumentTemplate documentTemplate) {
        newLine();
        builder.append("=== HEADER ===");
        newLine();
        for (Template header : documentTemplate.getHeaders()) {
            doSwitch(header);
        }
        newLine();
        builder.append("=== BODY ===");
        newLine();
        doSwitch(documentTemplate.getBody());
        newLine();
        builder.append("=== FOOTER ===");
        newLine();
        for (Template footer : documentTemplate.getFooters()) {
            doSwitch(footer);
        }

        return null;
    }

    @Override
    public Void caseTemplate(Template template) {
        builder.append(String.format("template %s", template.getTemplateName()));
        doSwitch(template.getBody());
        return null;
    }

    @Override
    public Void caseStaticFragment(StaticFragment staticFragment) {
        for (XWPFRun run : staticFragment.getRuns()) {
            builder.append(run.text().replaceAll("\r\n", "\n" + indentation).replaceAll("\r", "\n" + indentation));
        }
        return null;
    }

    @Override
    public Void caseQuery(Query query) {
        builder.append(String.format("[query: %s | %s]", querySerializer.serialize(query.getQuery().getAst()),
                query.getBehavior()));

        return null;
    }

    @Override
    public Void caseRepetition(Repetition repetition) {
        newLine();
        builder.append("for ");
        builder.append(repetition.getIterationVar());
        builder.append(" | ");
        builder.append(querySerializer.serialize(repetition.getQuery().getAst()));
        builder.append(" do");
        doSwitch(repetition.getBody());
        newLine();
        builder.append("endfor");
        newLine();
        return null;

    }

    @Override
    public Void caseUserDoc(UserDoc userDoc) {
        newLine();
        builder.append("userdoc ");
        builder.append(querySerializer.serialize(userDoc.getId().getAst()));
        builder.append(" do");
        indent();
        newLine();
        doSwitch(userDoc.getBody());
        deindent();
        newLine();
        builder.append("enduserdoc");
        newLine();
        return null;
    }

    @Override
    public Void caseConditional(Conditional conditional) {
        newLine();
        builder.append("if ");
        builder.append(querySerializer.serialize(conditional.getCondition().getAst()));
        builder.append(" then");
        doSwitch(conditional.getThen());
        if (conditional.getElse() != null) {
            newLine();
            builder.append("else");
            doSwitch(conditional.getElse());
        }
        newLine();
        builder.append("endif");
        newLine();

        return null;
    }

    @Override
    public Void caseBlock(Block block) {
        indent();
        for (IConstruct construct : block.getStatements()) {
            newLine();
            doSwitch(construct);
        }
        deindent();

        return null;
    }

    @Override
    public Void caseTable(Table table) {
        builder.append("table");
        indent();
        newLine();
        for (Row row : table.getRows()) {
            doSwitch(row);
            newLine();
        }
        deindent();

        return null;
    }

    @Override
    public Void caseRow(Row row) {
        builder.append("row");
        indent();
        newLine();
        for (Cell cell : row.getCells()) {
            doSwitch(cell);
            newLine();
        }
        deindent();

        return null;
    }

    @Override
    public Void caseCell(Cell cell) {
        doSwitch(cell.getTemplate());

        return null;
    }

    @Override
    public Void caseImage(Image image) {
        newLine();
        builder.append("image ");
        builder.append(image.getFileName());
        builder.append(" provider ");
        if (image.getProvider() != null) {
            builder.append(image.getProvider().getClass().getName());
        } else {
            builder.append("null");
        }
        builder.append(" height ");
        builder.append(image.getHeight());
        builder.append(" width ");
        builder.append(image.getWidth());
        builder.append(" legend ");
        builder.append(image.getLegend());
        builder.append(" legendpos ");
        builder.append(image.getLegendPOS().getName());
        for (Entry<String, Object> entry : image.getOptionValueMap().entrySet()) {
            // TODO the value will not be consistent between serializations...
            if (entry.getValue() instanceof AstResult) {
                builder.append(String.format(" %s %s ", entry.getKey(),
                        querySerializer.serialize(((AstResult) entry.getValue()).getAst())));
            } else {
                builder.append(String.format(" %s %s ", entry.getKey(), entry.getValue()));
            }
        }
        newLine();
        return null;
    }

    @Override
    public Void caseRepresentation(Representation representation) {
        newLine();
        builder.append("representation ");
        builder.append(representation.getRepresentationId());
        builder.append(" title ");
        builder.append(representation.getRepresentationTitle());
        builder.append(" provider ");
        if (representation.getProvider() != null) {
            builder.append(representation.getProvider().getClass().getName());
        } else {
            builder.append("null");
        }
        builder.append(" height ");
        builder.append(representation.getHeight());
        builder.append(" width ");
        builder.append(representation.getWidth());
        builder.append(" legend ");
        builder.append(representation.getLegend());
        builder.append(" legendpos ");
        builder.append(representation.getLegendPOS().getName());
        for (Entry<String, Object> entry : representation.getOptionValueMap().entrySet()) {
            // TODO the value will not be consistent between serializations...
            if (entry.getValue() instanceof AstResult) {
                builder.append(String.format(" %s %s ", entry.getKey(),
                        querySerializer.serialize(((AstResult) entry.getValue()).getAst())));
            } else {
                builder.append(String.format(" %s %s ", entry.getKey(), entry.getValue()));
            }
        }
        newLine();
        return null;
    }

    @Override
    public Void caseTableClient(TableClient tableClient) {
        newLine();
        builder.append("table client ");
        builder.append(tableClient.getProvider().getClass().getName());
        for (Entry<String, Object> entry : tableClient.getOptionValueMap().entrySet()) {
            // TODO the value will not be consistent between serializations...
            if (entry.getValue() instanceof AstResult) {
                builder.append(String.format(" %s %s ", entry.getKey(),
                        querySerializer.serialize(((AstResult) entry.getValue()).getAst())));
            } else {
                builder.append(String.format(" %s %s ", entry.getKey(), entry.getValue()));
            }
        }
        newLine();
        return null;
    }

    @Override
    public Void caseBookmark(Bookmark bookmark) {
        newLine();
        builder.append("bookmark ");
        builder.append(querySerializer.serialize(bookmark.getName().getAst()));
        doSwitch(bookmark.getBody());
        newLine();
        builder.append("endbookmark");
        newLine();
        return null;
    }

    @Override
    public Void caseLink(Link link) {
        newLine();
        builder.append("link ");
        builder.append(querySerializer.serialize(link.getName().getAst()));
        builder.append(" ");
        builder.append(querySerializer.serialize(link.getText().getAst()));
        builder.append(" endlink");
        newLine();
        return null;
    }

}