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

graphql.schema.diffing.SchemaDiffing Maven / Gradle / Ivy

There is a newer version: 230521-nf-execution
Show newest version
package graphql.schema.diffing;

import graphql.Internal;
import graphql.schema.GraphQLSchema;
import graphql.schema.diffing.ana.EditOperationAnalysisResult;
import graphql.schema.diffing.ana.EditOperationAnalyzer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static graphql.Assert.assertTrue;
import static graphql.schema.diffing.EditorialCostForMapping.editorialCostForMapping;
import static java.util.Collections.singletonList;

@Internal
public class SchemaDiffing {



    SchemaGraph sourceGraph;
    SchemaGraph targetGraph;

    public List diffGraphQLSchema(GraphQLSchema graphQLSchema1, GraphQLSchema graphQLSchema2) throws Exception {
        sourceGraph = new SchemaGraphFactory("source-").createGraph(graphQLSchema1);
        targetGraph = new SchemaGraphFactory("target-").createGraph(graphQLSchema2);
        return diffImpl(sourceGraph, targetGraph).listOfEditOperations.get(0);
    }

    public EditOperationAnalysisResult diffAndAnalyze(GraphQLSchema graphQLSchema1, GraphQLSchema graphQLSchema2) throws Exception {
        sourceGraph = new SchemaGraphFactory("source-").createGraph(graphQLSchema1);
        targetGraph = new SchemaGraphFactory("target-").createGraph(graphQLSchema2);
        DiffImpl.OptimalEdit optimalEdit = diffImpl(sourceGraph, targetGraph);
        EditOperationAnalyzer editOperationAnalyzer = new EditOperationAnalyzer(graphQLSchema1, graphQLSchema1, sourceGraph, targetGraph);
        return editOperationAnalyzer.analyzeEdits(optimalEdit.listOfEditOperations.get(0),optimalEdit.mappings.get(0));
    }

    public DiffImpl.OptimalEdit diffGraphQLSchemaAllEdits(GraphQLSchema graphQLSchema1, GraphQLSchema graphQLSchema2) throws Exception {
        sourceGraph = new SchemaGraphFactory("source-").createGraph(graphQLSchema1);
        targetGraph = new SchemaGraphFactory("target-").createGraph(graphQLSchema2);
        return diffImpl(sourceGraph, targetGraph);
    }


    private DiffImpl.OptimalEdit diffImpl(SchemaGraph sourceGraph, SchemaGraph targetGraph) throws Exception {
        int sizeDiff = targetGraph.size() - sourceGraph.size();
        System.out.println("graph diff: " + sizeDiff);
        FillupIsolatedVertices fillupIsolatedVertices = new FillupIsolatedVertices(sourceGraph, targetGraph);
        fillupIsolatedVertices.ensureGraphAreSameSize();
        FillupIsolatedVertices.IsolatedVertices isolatedVertices = fillupIsolatedVertices.isolatedVertices;

        assertTrue(sourceGraph.size() == targetGraph.size());
//        if (sizeDiff != 0) {
//            SortSourceGraph.sortSourceGraph(sourceGraph, targetGraph, isolatedVertices);
//        }
        Mapping fixedMappings = isolatedVertices.mapping;
        System.out.println("fixed mappings: " + fixedMappings.size() + " vs " + sourceGraph.size());
        if (fixedMappings.size() == sourceGraph.size()) {
            List result = new ArrayList<>();
            editorialCostForMapping(fixedMappings, sourceGraph, targetGraph, result);
            return new DiffImpl.OptimalEdit(singletonList(fixedMappings), singletonList(result), result.size());
        }
        DiffImpl diffImpl = new DiffImpl(sourceGraph, targetGraph, isolatedVertices);
        List nonMappedSource = new ArrayList<>(sourceGraph.getVertices());
        nonMappedSource.removeAll(fixedMappings.getSources());
//        for(Vertex vertex: nonMappedSource) {
//            System.out.println("non mapped: " + vertex);
//        }
//        for (List context : isolatedVertices.contexts.rowKeySet()) {
//            Map, Set> row = isolatedVertices.contexts.row(context);
//            System.out.println("context: " + context + " from " + row.keySet().iterator().next().size() + " to " + row.values().iterator().next().size());
//        }

        List nonMappedTarget = new ArrayList<>(targetGraph.getVertices());
        nonMappedTarget.removeAll(fixedMappings.getTargets());

        sortListBasedOnPossibleMapping(nonMappedSource, isolatedVertices);

        // the non mapped vertices go to the end
        List sourceVertices = new ArrayList<>();
        sourceVertices.addAll(fixedMappings.getSources());
        sourceVertices.addAll(nonMappedSource);

        List targetGraphVertices = new ArrayList<>();
        targetGraphVertices.addAll(fixedMappings.getTargets());
        targetGraphVertices.addAll(nonMappedTarget);


        DiffImpl.OptimalEdit optimalEdit = diffImpl.diffImpl(fixedMappings, sourceVertices, targetGraphVertices);
//        System.out.println("different edit counts: " + optimalEdit.listOfEditOperations.size());
//        for (int i = 0; i < optimalEdit.listOfEditOperations.size(); i++) {
//            System.out.println("--------------");
//            System.out.println("edit: " + i);
//            System.out.println("--------------");
//            for (EditOperation editOperation : optimalEdit.listOfEditOperations.get(i)) {
//                System.out.println(editOperation);
//            }
//            System.out.println("--------------");
//            System.out.println("--------------");
//        }
        return optimalEdit;
    }

    private void sortListBasedOnPossibleMapping(List sourceVertices, FillupIsolatedVertices.IsolatedVertices isolatedVertices) {
        Collections.sort(sourceVertices, (v1, v2) ->
        {
            int v2Count = isolatedVertices.possibleMappings.get(v2).size();
            int v1Count = isolatedVertices.possibleMappings.get(v1).size();
            return Integer.compare(v2Count, v1Count);
        });

//        for (Vertex vertex : sourceGraph.getVertices()) {
//            System.out.println("c: " + isolatedVertices.possibleMappings.get(vertex).size() + " v: " + vertex);
//        }
    }


    private List calcEdgeOperations(Mapping mapping) {
        List edges = sourceGraph.getEdges();
        List result = new ArrayList<>();
        // edge deletion or relabeling
        for (Edge sourceEdge : edges) {
            Vertex target1 = mapping.getTarget(sourceEdge.getFrom());
            Vertex target2 = mapping.getTarget(sourceEdge.getTo());
            Edge targetEdge = targetGraph.getEdge(target1, target2);
            if (targetEdge == null) {
                result.add(EditOperation.deleteEdge("Delete edge " + sourceEdge, sourceEdge));
            } else if (!sourceEdge.getLabel().equals(targetEdge.getLabel())) {
                result.add(EditOperation.changeEdge("Change " + sourceEdge + " to " + targetEdge, sourceEdge, targetEdge));
            }
        }

        //TODO: iterates over all edges in the target Graph
        for (Edge targetEdge : targetGraph.getEdges()) {
            // only subgraph edges
            Vertex sourceFrom = mapping.getSource(targetEdge.getFrom());
            Vertex sourceTo = mapping.getSource(targetEdge.getTo());
            if (sourceGraph.getEdge(sourceFrom, sourceTo) == null) {
                result.add(EditOperation.insertEdge("Insert edge " + targetEdge, targetEdge));
            }
        }
        return result;
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy