com.synflow.cx.internal.instantiation.DependencySolver.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.cx.internal.instantiation.DependencySolver.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Synflow SAS.
 * 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:
 *    Matthieu Wipliez - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.synflow.cx.internal.instantiation;

import static com.synflow.models.util.SwitchUtil.DONE;
import static com.synflow.models.util.SwitchUtil.visit;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;

import com.google.common.collect.Iterables;
import com.synflow.cx.CxUtil;
import com.synflow.cx.cx.CxType;
import com.synflow.cx.cx.ExpressionVariable;
import com.synflow.cx.cx.TypeRef;
import com.synflow.cx.cx.Typedef;
import com.synflow.cx.cx.VarRef;
import com.synflow.cx.cx.Variable;
import com.synflow.cx.internal.services.VoidCxSwitch;
import com.synflow.models.graph.Edge;
import com.synflow.models.graph.Graph;
import com.synflow.models.graph.GraphFactory;
import com.synflow.models.graph.Vertex;
import com.synflow.models.graph.visit.ReversePostOrder;
import com.synflow.models.util.Void;

/**
 * This class defines a solver of dependency between variables.
 * 
 * @author Matthieu Wipliez
 *
 */
public class DependencySolver extends VoidCxSwitch {

    private static class VertexAdapter extends AdapterImpl {

        private final EObject contents;

        public VertexAdapter(EObject contents) {
            Objects.requireNonNull(contents);
            this.contents = contents;
        }

        @SuppressWarnings("unchecked")
        public <T extends EObject> T getContent() {
            return (T) contents;
        }

        @Override
        public boolean isAdapterForType(Object type) {
            return type == getClass();
        }

        @Override
        public String toString() {
            return contents.toString();
        }

    }

    private static VertexAdapter getVertexAdapter(EObject eObject) {
        return (VertexAdapter) EcoreUtil.getAdapter(eObject.eAdapters(), VertexAdapter.class);
    }

    private Vertex declaration;

    private List<EObject> eObjects;

    private Graph graph;

    public DependencySolver() {
        eObjects = new ArrayList<>();
    }

    public void add(Variable variable) {
        eObjects.add(variable);
    }

    public void addAll(Iterable<? extends EObject> iterable) {
        Iterables.addAll(eObjects, iterable);
    }

    @Override
    public Void caseExpressionVariable(ExpressionVariable expr) {
        super.caseExpressionVariable(expr);
        return visit(this, expr.getSource());
    }

    @Override
    public Void caseTypeRef(TypeRef ref) {
        Typedef typedef = ref.getTypeDef();
        return handle(typedef);
    }

    @Override
    public Void caseVariable(Variable variable) {
        CxType type = CxUtil.getType(variable);
        visit(this, type);
        return super.caseVariable(variable);
    }

    @Override
    public Void caseVarRef(VarRef ref) {
        Variable variable = ref.getVariable();
        return handle(variable);
    }

    public void computeOrder() {
        graph = GraphFactory.eINSTANCE.createGraph();
        for (EObject eObject : eObjects) {
            Vertex vertex = GraphFactory.eINSTANCE.createVertex();
            vertex.eAdapters().add(new VertexAdapter(eObject));
            eObject.eAdapters().add(new VertexAdapter(vertex));
            graph.add(vertex);
        }

        for (EObject eObject : eObjects) {
            declaration = getVertexAdapter(eObject).getContent();
            visit(this, eObject);
        }
    }

    public Iterable<EObject> getObjects() {
        List<EObject> ordered = new ArrayList<>(eObjects.size());
        for (Vertex vertex : new ReversePostOrder(graph)) {
            ordered.add(getVertexAdapter(vertex).getContent());
        }

        // remove adapters from objects
        // very important in the case of bundles, whose constants are used in many places
        for (EObject eObject : eObjects) {
            VertexAdapter adapter = getVertexAdapter(eObject);
            eObject.eAdapters().remove(adapter);
        }

        return ordered;
    }

    private Void handle(EObject eObject) {
        VertexAdapter adapter = getVertexAdapter(eObject);
        if (adapter == null) {
            // type not in current entity
            return DONE;
        }

        Edge edge = GraphFactory.eINSTANCE.createEdge();

        Vertex vertex = adapter.getContent();
        edge.setSource(vertex);
        edge.setTarget(declaration);
        graph.add(edge);
        return DONE;
    }

}