org.iti.structureGraph.StructureGraph.java Source code

Java tutorial

Introduction

Here is the source code for org.iti.structureGraph.StructureGraph.java

Source

/*
 *  Copyright 1999 Hagen Schink <hagen.schink@gmail.com>
 *
 *  This file is part of sql-schema-comparer.
 *
 *  sql-schema-comparer is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  sql-schema-comparer is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with sql-schema-comparer.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 */

package org.iti.structureGraph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.iti.structureGraph.nodes.IStructureElement;
import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.DefaultEdge;

public class StructureGraph implements IStructureGraph {

    private DirectedGraph<IStructureElement, DefaultEdge> graph;

    private Map<String, IStructureElement> elementsByIdentifer = new HashMap<>();
    private Map<String, DefaultEdge> pathesByIdentifer = new HashMap<>();

    public StructureGraph(DirectedGraph<IStructureElement, DefaultEdge> graph) {
        this.graph = graph;

        loadElementsByIdentifier();
        loadEdgesByIdentifier();
    }

    private void loadElementsByIdentifier() {
        for (IStructureElement element : graph.vertexSet()) {
            String identifier = getIdentifier(element);
            elementsByIdentifer.put(identifier, element);
        }
    }

    private void loadEdgesByIdentifier() {
        for (IStructureElement element : elementsByIdentifer.values()) {
            List<DefaultEdge> incomingEdges = getIncomingEdges(element);

            for (DefaultEdge incomingEdge : incomingEdges) {
                for (IStructureElement relatedElement : graph.vertexSet()) {
                    if (graph.outgoingEdgesOf(relatedElement).contains(incomingEdge)) {
                        List<IStructureElement> pathElements = new ArrayList<>();

                        pathElements.add(relatedElement);
                        pathElements.add(element);

                        pathesByIdentifer.put(getPathString(pathElements, false), incomingEdge);
                    }
                }
            }
        }
    }

    private List<IStructureElement> getElementPathElements(IStructureElement element) {
        return getElementPathElements(element, true);
    }

    private List<IStructureElement> getElementPathElements(IStructureElement element, boolean toRootElement) {
        IStructureElement currentElement = element;
        LinkedList<IStructureElement> elements = new LinkedList<>();
        int elementCount = (toRootElement) ? -1 : 2;

        while (currentElement != null && elementCount != 0) {
            elements.addFirst(currentElement);

            currentElement = getParent(currentElement);

            elementCount--;
        }

        return elements;
    }

    private IStructureElement getParent(IStructureElement element) {
        List<DefaultEdge> incomingEdges = getIncomingEdges(element);

        if (!incomingEdges.isEmpty()) {
            DefaultEdge incomingEdge = incomingEdges.get(0);

            for (IStructureElement e : graph.vertexSet()) {
                if (graph.outgoingEdgesOf(e).contains(incomingEdge)) {
                    return e;
                }
            }
        }

        return null;
    }

    private List<DefaultEdge> getIncomingEdges(IStructureElement element) {
        return new ArrayList<DefaultEdge>(graph.incomingEdgesOf(element));
    }

    private String getPathString(List<IStructureElement> pathElements) {
        return getPathString(pathElements, true);
    }

    private String getPathString(List<IStructureElement> pathElements, boolean includeLastElement) {
        StringBuilder identifier = new StringBuilder();
        int closingBracketCount = pathElements.size() - 1 - ((includeLastElement) ? 0 : 1);

        for (int x = 0; x < pathElements.size(); x++) {
            boolean isLastElement = x == pathElements.size() - 1;
            boolean isNextToLastElement = x == pathElements.size() - 2;

            if (!isLastElement || includeLastElement) {
                boolean successorExists = x + 1 < pathElements.size();
                IStructureElement element1 = pathElements.get(x);
                IStructureElement element2 = (successorExists) ? pathElements.get(x + 1) : null;
                DefaultEdge edge = (successorExists) ? getEdge(element1, element2) : null;

                identifier.append(element1.getIdentifier());

                if (successorExists) {
                    identifier.append("." + edge.getClass().getSimpleName());

                    if (!isNextToLastElement || includeLastElement) {
                        identifier.append("(");
                    }
                }
            }
        }

        identifier.append(StringUtils.repeat(")", closingBracketCount));

        return identifier.toString();
    }

    private DefaultEdge getEdge(IStructureElement element1, IStructureElement element2) {
        return graph.getAllEdges(element1, element2).iterator().next();
    }

    @Override
    public boolean containsElementWithPath(String path) {
        return elementsByIdentifer.containsKey(path);
    }

    @Override
    public IStructureElement getStructureElement(String identifier) {
        return elementsByIdentifer.get(identifier);
    }

    @Override
    public String getIdentifier(IStructureElement element) {
        List<IStructureElement> pathElements = getElementPathElements(element);

        return getPathString(pathElements);
    }

    @Override
    public String getPath(IStructureElement element) {
        List<IStructureElement> pathElements = getElementPathElements(element);

        return getPathString(pathElements, false);
    }

    @Override
    public DefaultEdge getEdge(String path) {
        return pathesByIdentifer.get(path);
    }

    @Override
    public IStructureElement getSourceElement(DefaultEdge edge) {
        return graph.getEdgeSource(edge);
    }

    @Override
    public IStructureElement getTargetElement(DefaultEdge edge) {
        return graph.getEdgeTarget(edge);
    }

    @Override
    public String getPath(IStructureElement element, boolean toRootElement) {
        List<IStructureElement> pathElements = getElementPathElements(element, toRootElement);

        return getPathString(pathElements, false);
    }

    @Override
    public List<IStructureElement> getStructureElements(String path) {
        return getStructureElements(path, false);
    }

    @Override
    public List<IStructureElement> getStructureElements(String path, boolean directAncestorsOnly) {
        Map<IStructureElement, Integer> list = new HashMap<>();

        for (IStructureElement element : elementsByIdentifer.values()) {
            if (getPath(element).startsWith(path)) {
                list.put(element, getElementPathElements(element).size());
            }
        }

        if (list.size() > 0 && directAncestorsOnly) {
            removeIndirectAncestors(list);
        }

        return new ArrayList<IStructureElement>(list.keySet());
    }

    private void removeIndirectAncestors(Map<IStructureElement, Integer> list) {
        List<IStructureElement> elementsToRemove = new ArrayList<>();
        int minimalElementsCount = Integer.MAX_VALUE;

        for (Integer i : list.values()) {
            if (minimalElementsCount > i) {
                minimalElementsCount = i;
            }
        }

        for (Entry<IStructureElement, Integer> entry : list.entrySet()) {
            if (entry.getValue() > minimalElementsCount) {
                elementsToRemove.add(entry.getKey());
            }
        }

        for (IStructureElement elementToRemove : elementsToRemove) {
            list.remove(elementToRemove);
        }
    }

    @Override
    public List<String> getIdentifiers() {
        return new ArrayList<String>(elementsByIdentifer.keySet());
    }

    @Override
    public List<String> getPathes() {
        return new ArrayList<String>(pathesByIdentifer.keySet());
    }

}