All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kevoree.modeling.ast.MModel Maven / Gradle / Ivy

The newest version!
package org.kevoree.modeling.ast;

import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.BufferedTokenStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

public class MModel {

    private String version = null;

    private String kmfVersion = null;

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getKmfVersion() {
        return kmfVersion;
    }

    public void setKmfVersion(String kmfVersion) {
        this.kmfVersion = kmfVersion;
    }

    private HashMap classifiers = new HashMap<>();

    private Integer classIndex = 0;
    private Integer enumIndex = 0;

    public Collection getClassifiers() {
        return classifiers.values();
    }

    public MModelClassifier get(String fqn) {
        return classifiers.get(fqn);
    }

    public void addClassifier(MModelClassifier classifier) {
        if (classifier instanceof MModelClass) {
            classifier.setIndex(classIndex);
            classIndex = classIndex + 1;
        } else if (classifier instanceof MModelEnum) {
            classifier.setIndex(enumIndex);
            enumIndex = enumIndex + 1;
        }
        classifiers.put(classifier.getFqn(), classifier);
    }

    public Collection getClasses() {
        ArrayList classes = new ArrayList();
        for (MModelClassifier cls : classifiers.values()) {
            if (cls instanceof MModelClass) {
                classes.add((MModelClass) cls);
            }
        }
        return classes;
    }

    public Collection getEnums() {
        ArrayList classes = new ArrayList();
        for (MModelClassifier cls : classifiers.values()) {
            if (cls instanceof MModelEnum) {
                classes.add((MModelEnum) cls);
            }
        }
        return classes;
    }

    private final static Character ESCAPE_CHAR = '\\';

    private static String cleanString(String in) {
        String cleaned = in.substring(1, in.length() - 1);
        if (cleaned.length() == 0) {
            return cleaned;
        }
        StringBuilder builder = null;
        int i = 0;
        while (i < cleaned.length()) {
            Character current = cleaned.charAt(i);
            if (current == ESCAPE_CHAR) {
                if (builder == null) {
                    builder = new StringBuilder();
                    builder.append(cleaned.substring(0, i));
                }
                i++;
                Character current2 = cleaned.charAt(i);
                switch (current2) {
                    case '"':
                        builder.append('\"');
                        break;
                    case '\\':
                        builder.append(current2);
                        break;
                    case '/':
                        builder.append(current2);
                        break;
                    case 'b':
                        builder.append('\b');
                        break;
                    case 'f':
                        builder.append('\f');
                        break;
                    case 'n':
                        builder.append('\n');
                        break;
                    case 'r':
                        builder.append('\r');
                        break;
                    case 't':
                        builder.append('\t');
                        break;
                    case '{':
                        builder.append("\\{");
                        break;
                    case '}':
                        builder.append("\\}");
                        break;
                    case '[':
                        builder.append("\\[");
                        break;
                    case ']':
                        builder.append("\\]");
                        break;
                    case ',':
                        builder.append("\\,");
                        break;
                }
            } else {
                if (builder != null) {
                    builder = builder.append(current);
                }
            }
            i++;
        }
        if (builder != null) {
            return builder.toString();
        } else {
            return cleaned;
        }
    }

    public static MModel build(File mmFile) throws IOException {
        MModel model = new MModel();
        ANTLRFileStream fileStream = new ANTLRFileStream(mmFile.getAbsolutePath());
        BufferedTokenStream tokens = new CommonTokenStream(new org.kevoree.modeling.ast.MetaModelLexer(fileStream));
        org.kevoree.modeling.ast.MetaModelParser parser = new org.kevoree.modeling.ast.MetaModelParser(tokens);
        org.kevoree.modeling.ast.MetaModelParser.MetamodelContext mmctx = parser.metamodel();
        //first we do version
        for (org.kevoree.modeling.ast.MetaModelParser.AnnotationDeclrContext annotationDeclrContext : mmctx.annotationDeclr()) {
            if (annotationDeclrContext.IDENT().getText().toLowerCase().equals("version") && annotationDeclrContext.STRING() != null) {
                model.setVersion(cleanString(annotationDeclrContext.STRING().getText()));
            }
            if (annotationDeclrContext.IDENT().getText().toLowerCase().equals("kmfversion") && annotationDeclrContext.STRING() != null) {
                model.setKmfVersion(cleanString(annotationDeclrContext.STRING().getText()));
            }
        }
        //Second we do enum mapping
        for (org.kevoree.modeling.ast.MetaModelParser.DeclContext decl : mmctx.decl()) {
            if (decl.enumDeclr() != null) {
                org.kevoree.modeling.ast.MetaModelParser.EnumDeclrContext enumDeclrContext = decl.enumDeclr();
                String enumFqn = enumDeclrContext.TYPE_NAME().getText();
                final MModelEnum enumClass = model.getOrAddEnum(enumFqn);
                for (TerminalNode literal : enumDeclrContext.IDENT()) {
                    enumClass.addLitteral(literal.getText());
                }
            }
        }
        //thirdly we do classDeclr
        for (org.kevoree.modeling.ast.MetaModelParser.DeclContext decl : mmctx.decl()) {
            if (decl.classDeclr() != null) {
                org.kevoree.modeling.ast.MetaModelParser.ClassDeclrContext classDeclrContext = decl.classDeclr();
                String classFqn = classDeclrContext.TYPE_NAME().getText();
                final MModelClass newClass = model.getOrAddClass(classFqn);
                for (org.kevoree.modeling.ast.MetaModelParser.AttributeDeclarationContext attDecl : classDeclrContext.attributeDeclaration()) {
                    String name = attDecl.IDENT().getText();
                    org.kevoree.modeling.ast.MetaModelParser.AttributeTypeContext attType = attDecl.attributeType();
                    String value;
                    if (attType.TYPE_NAME() != null) {
                        value = attType.TYPE_NAME().getText();
                    } else {
                        value = attType.getText();
                    }
                    final MModelAttribute attribute = new MModelAttribute(name, value);
                    for (org.kevoree.modeling.ast.MetaModelParser.AnnotationDeclrContext annotDecl : attDecl.annotationDeclr()) {
                        if (annotDecl.IDENT().getText().toLowerCase().equals("precision") && annotDecl.NUMBER() != null) {
                            attribute.setPrecision(Double.parseDouble(annotDecl.NUMBER().getText()));
                        }
                        if (annotDecl.IDENT().getText().toLowerCase().equals("index")) {
                            attribute.setIndexed();
                        }
                    }
                    newClass.addAttribute(attribute);
                }
                for (org.kevoree.modeling.ast.MetaModelParser.ReferenceDeclarationContext refDecl : classDeclrContext.referenceDeclaration()) {
                    final MModelClass refType = model.getOrAddClass(refDecl.TYPE_NAME().getText());
                    MModelRelation reference = model.getOrAddReference(newClass, refDecl.IDENT().getText(), refType);
                    for (org.kevoree.modeling.ast.MetaModelParser.AnnotationDeclrContext annotDecl : refDecl.annotationDeclr()) {
                        if (annotDecl.IDENT().getText().toLowerCase().equals("opposite") && annotDecl.STRING() != null) {
                            reference.setOpposite(cleanString(annotDecl.STRING().getText()));
                            MModelRelation oppRef = model.getOrAddReference(refType, reference.getOpposite(), newClass);
                            oppRef.setVisible(true);
                            oppRef.setOpposite(reference.getName());
                        }
                        if (annotDecl.IDENT().getText().toLowerCase().equals("maxbound") && annotDecl.NUMBER() != null) {
                            reference.setMaxBound(Integer.parseInt(annotDecl.NUMBER().getText()));
                        }
                    }
                    newClass.addReference(reference);
                }

                for (org.kevoree.modeling.ast.MetaModelParser.DependencyDeclarationContext dependencyDeclarationContext : classDeclrContext.dependencyDeclaration()) {
                    final MModelClass depType = model.getOrAddClass(dependencyDeclarationContext.TYPE_NAME().getText());
                    MModelDependency dependency = new MModelDependency(dependencyDeclarationContext.IDENT().getText(), depType);
                    newClass.addDependency(dependency);
                }
                for (org.kevoree.modeling.ast.MetaModelParser.InputDeclarationContext inputDeclarationContext : classDeclrContext.inputDeclaration()) {
                    MModelInput input = new MModelInput(inputDeclarationContext.IDENT().getText(), cleanString(inputDeclarationContext.STRING().getText()));
                    newClass.addInput(input);
                }
                for (org.kevoree.modeling.ast.MetaModelParser.OutputDeclarationContext outputDeclarationContext : classDeclrContext.outputDeclaration()) {
                    org.kevoree.modeling.ast.MetaModelParser.AttributeTypeContext attType = outputDeclarationContext.attributeType();
                    String typeName;
                    if (attType.TYPE_NAME() != null) {
                        typeName = attType.TYPE_NAME().getText();
                    } else {
                        typeName = attType.getText();
                    }
                    MModelOutput output = new MModelOutput(outputDeclarationContext.IDENT().getText(), typeName);
                    newClass.addOutput(output);
                }
                if (classDeclrContext.classParentDeclr() != null) {
                    org.kevoree.modeling.ast.MetaModelParser.ClassParentDeclrContext parentDeclrContext = classDeclrContext.classParentDeclr();
                    for (TerminalNode tt : parentDeclrContext.TYPE_NAME()) {
                        final MModelClass newClassTT = model.getOrAddClass(tt.getText());
                        newClass.addParent(newClassTT);
                    }
                }
                for (org.kevoree.modeling.ast.MetaModelParser.AnnotationDeclrContext annotDecl : classDeclrContext.annotationDeclr()) {
                    if (annotDecl.IDENT().getText().toLowerCase().equals("temporalLimit") && annotDecl.NUMBER() != null) {
                        newClass.setTemporalLimit(Long.parseLong(annotDecl.NUMBER().getText()));
                    }
                    if (annotDecl.IDENT().getText().toLowerCase().equals("temporalResolution") && annotDecl.NUMBER() != null) {
                        newClass.setTemporalResolution(Long.parseLong(annotDecl.NUMBER().getText()));
                    }
                    if (annotDecl.IDENT().getText().toLowerCase().equals("inference") && annotDecl.STRING() != null) {
                        newClass.setInference(cleanString(annotDecl.STRING().getText()));
                    }
                    if(annotDecl.IDENT().getText().toLowerCase().equals("instantiation") && annotDecl.STRING() != null){
                        String value = cleanString(annotDecl.STRING().getText().toLowerCase());
                        if(value.equals("true") || value.equals("false")) {
                            newClass.setCanHaveInstance(Boolean.valueOf(value));
                        } else {
                            throw new RuntimeException("The instantiation value must be a boolean : \"true\" or \"false\". " + value);
                        }
                    }
                }
                for (org.kevoree.modeling.ast.MetaModelParser.FunctionDeclarationContext functionDeclarationContext : classDeclrContext.functionDeclaration()) {
                    MModelOperation operation = new MModelOperation(functionDeclarationContext.IDENT().getText());
                    if (functionDeclarationContext.functionDeclarationReturnType() != null) {
                        operation.returnType = functionDeclarationContext.functionDeclarationReturnType().attributeType().getText();
                        if (functionDeclarationContext.functionDeclarationReturnType().functionDeclarationMultiplicity() != null) {
                            operation.returnTypeIsArray = true;
                        }
                    }
                    if (functionDeclarationContext.functionDeclarationParameters() != null) {
                        for (org.kevoree.modeling.ast.MetaModelParser.FunctionDeclarationParameterContext param : functionDeclarationContext.functionDeclarationParameters().functionDeclarationParameter()) {
                            MModelOperationParam newParam = new MModelOperationParam();
                            newParam.name = param.IDENT().getText();
                            newParam.type = param.attributeType().getText();
                            operation.inputParams.add(newParam);
                            if (param.functionDeclarationMultiplicity() != null) {
                                newParam.isArray = true;
                            }
                        }
                    }
                    newClass.addOperation(operation);
                }
            }
        }
        //opposite completion
        model.completeOppositeReferences();
        model.consolidateIndexes();
        model.consolidateTypeIds();
        return model;
    }

    public static void main(String[] args) throws IOException {
        System.out.println(build(new File("/Users/duke/Documents/dev/kevoree-modeling/framework/org.kevoree.modeling.ast/src/main/exemples/cloud.mm")));
    }

    private MModelRelation getOrAddReference(MModelClass owner, String refName, MModelClass refType) {
        for (MModelRelation registeredRef : owner.getReferences()) {
            if (registeredRef.getName().equals(refName)) {
                return registeredRef;
            }
        }
        MModelRelation reference = new MModelRelation(refName, refType);
        owner.addReference(reference);
        return reference;
    }

    private MModelEnum getOrAddEnum(String clazz) {
        MModelClassifier resolved = get(clazz);
        if (resolved == null) {
            String relationTypePackage = clazz.substring(0, clazz.lastIndexOf("."));
            String relationTypeName = clazz.substring(clazz.lastIndexOf(".") + 1);
            resolved = new MModelEnum(relationTypeName);
            resolved.setPack(relationTypePackage);
            addClassifier(resolved);
            return (MModelEnum) resolved;
        } else {
            if (resolved instanceof MModelEnum) {
                return (MModelEnum) resolved;
            } else {
                throw new RuntimeException("Naming conflict for " + clazz + ", cannot merge an enum and a class declaration");
            }
        }
    }

    private MModelClass getOrAddClass(String clazz) {
        MModelClassifier resolved = get(clazz);
        if (resolved == null) {
            String relationTypePackage = clazz.substring(0, clazz.lastIndexOf("."));
            String relationTypeName = clazz.substring(clazz.lastIndexOf(".") + 1);
            resolved = new MModelClass(relationTypeName);
            resolved.setPack(relationTypePackage);
            addClassifier(resolved);
            return (MModelClass) resolved;
        } else {
            if (resolved instanceof MModelClass) {
                return (MModelClass) resolved;
            } else {
                throw new RuntimeException("Naming conflict for " + clazz + ", cannot merge an enum and a class declaration");
            }
        }
    }

    private void completeOppositeReferences() {
        for (MModelClass classDecl : getClasses()) {
            for (MModelRelation ref : classDecl.getReferences().toArray(new MModelRelation[classDecl.getReferences().size()])) {
                if (ref.getOpposite() == null) {
                    //Create opposite relation

                    MModelRelation op_ref = getOrAddReference(ref.getType(), "op_" + classDecl.getName() + "_" + ref.getName(), classDecl);
                    op_ref.setVisible(false);
                    op_ref.setOpposite(ref.getName());

                    //add the relation on  the other side
                    ref.getType().addReference(op_ref);
                    ref.setOpposite(op_ref.getName());
                }
            }
        }
    }

    public void consolidateIndexes() {
        for (MModelClass decl : getClasses()) {
            internal_consolidate(decl);
        }
    }

    public void consolidateTypeIds() {
        for (MModelClass decl : getClasses()) {
            for (MModelAttribute att : decl.getAttributes()) {
                if (MMTypeHelper.isPrimitiveTYpe(att.getType())) {
                    att.typeId = MMTypeHelper.toId(att.getType());
                } else {
                    for (MModelEnum en : getEnums()) {
                        if (en.getFqn().endsWith(att.getType())) {
                            att.typeId = en.index;
                        }
                    }
                }
            }
            for (MModelOutput out : decl.getOutputs()) {
                if (MMTypeHelper.isPrimitiveTYpe(out.getType())) {
                    out.typeId = MMTypeHelper.toId(out.getType());
                } else {
                    for (MModelEnum en : getEnums()) {
                        if (en.getFqn().endsWith(out.getType())) {
                            out.typeId = en.index;
                        }
                    }
                }
            }
            for (MModelOperation out : decl.getOperations()) {
                if (out.getReturnType() != null) {
                    if (MMTypeHelper.isPrimitiveTYpe(out.getReturnType())) {
                        out.returnTypeId = MMTypeHelper.toId(out.getReturnType());
                    } else {
                        for (MModelEnum en : getEnums()) {
                            if (en.getFqn().endsWith(out.getReturnType())) {
                                out.returnTypeId = en.index;
                            }
                        }
                    }
                }
                for (MModelOperationParam param : out.inputParams) {
                    if (MMTypeHelper.isPrimitiveTYpe(param.getType())) {
                        param.typeId = MMTypeHelper.toId(param.getType());
                    } else {
                        for (MModelEnum en : getEnums()) {
                            if (en.getFqn().endsWith(param.getType())) {
                                param.typeId = en.index;
                            }
                        }
                    }
                }
            }

        }
    }

    private void internal_consolidate(MModelClass classRelDecls) {
        int globalIndex = 0;
        for (MModelAttribute att : classRelDecls.getAttributes()) {
            att.setIndex(globalIndex);
            globalIndex++;
        }
        for (MModelRelation ref : classRelDecls.getReferences()) {
            ref.setIndex(globalIndex);
            globalIndex++;
        }
        for (MModelOperation op : classRelDecls.getOperations()) {
            op.setIndex(globalIndex);
            globalIndex++;
        }
        for (MModelInput inp : classRelDecls.getInputs()) {
            inp.setIndex(globalIndex);
            globalIndex++;
        }
        for (MModelOutput out : classRelDecls.getOutputs()) {
            out.setIndex(globalIndex);
            globalIndex++;
        }
        if (classRelDecls.dependencies() != null) {
            classRelDecls.dependencies().setIndex(globalIndex);
            globalIndex++;
            int localIndex = 0;
            for (MModelDependency dep : classRelDecls.dependencies().dependencies.values()) {
                dep.setIndex(localIndex);
                localIndex++;
            }
        }
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (MModelClassifier cl : classifiers.values()) {
            builder.append(cl.toString());
        }
        return builder.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy