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

guru.nidi.graphviz.model.MutableGraph Maven / Gradle / Ivy

There is a newer version: 0.18.1
Show newest version
/*
 * Copyright © 2015 Stefan Niederhauser ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package guru.nidi.graphviz.model;

import guru.nidi.graphviz.attribute.*;

import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;

import static java.util.Arrays.asList;

public class MutableGraph implements LinkSource, LinkTarget {
    private static final SafeRecursion RECURSION = new SafeRecursion<>();
    protected boolean strict;
    protected boolean directed;
    protected boolean cluster;
    protected Label name;
    protected final Set nodes;
    protected final Set subgraphs;
    protected final LinkList links;
    protected final MutableAttributed nodeAttrs;
    protected final MutableAttributed linkAttrs;
    protected final MutableAttributed graphAttrs;

    MutableGraph() {
        this(false, false, false, Label.of(""), new LinkedHashSet<>(), new LinkedHashSet<>(), new ArrayList<>(),
                null, null, null);
        CreationContext.current().ifPresent(ctx -> graphAttrs().add(ctx.graphAttrs()));
    }

    protected MutableGraph(boolean strict, boolean directed, boolean cluster, Label name,
                           LinkedHashSet nodes, LinkedHashSet subgraphs, List links,
                           @Nullable Attributes nodeAttrs,
                           @Nullable Attributes linkAttrs,
                           @Nullable Attributes graphAttrs) {
        this.strict = strict;
        this.directed = directed;
        this.cluster = cluster;
        this.name = name;
        this.nodes = nodes;
        this.subgraphs = subgraphs;
        this.links = new LinkList(this, links);
        this.nodeAttrs = new SimpleMutableAttributed<>(this, nodeAttrs);
        this.linkAttrs = new SimpleMutableAttributed<>(this, linkAttrs);
        this.graphAttrs = new SimpleMutableAttributed<>(this, graphAttrs);
    }

    public MutableGraph copy() {
        return new MutableGraph(strict, directed, cluster, name,
                new LinkedHashSet<>(nodes), new LinkedHashSet<>(subgraphs), links,
                nodeAttrs, linkAttrs, graphAttrs);
    }

    public Graph toImmutable() {
        return ImmutableGraph.copyOfMut(this);
    }

    public MutableGraph use(ThrowingBiConsumer actions) {
        return CreationContext.use(this, ctx -> {
            actions.accept(this, ctx);
            return this;
        });
    }

    public MutableGraph setStrict(boolean strict) {
        this.strict = strict;
        return this;
    }

    public MutableGraph setDirected(boolean directed) {
        this.directed = directed;
        return this;
    }

    public MutableGraph setCluster(boolean cluster) {
        this.cluster = cluster;
        return this;
    }

    public MutableGraph setName(String name) {
        this.name = Label.of(name);
        return this;
    }

    public MutableGraph add(LinkSource... sources) {
        return add(asList(sources));
    }

    public MutableGraph add(List sources) {
        for (final LinkSource source : sources) {
            add(source);
        }
        return this;
    }

    public MutableGraph add(LinkSource source) {
        source.addTo(this);
        return this;
    }

    public MutableGraph addLink(LinkTarget... targets) {
        for (final LinkTarget target : targets) {
            addLink(target);
        }
        return this;
    }

    public MutableGraph addLink(LinkTarget target) {
        links.add(linkTo(target));
        return this;
    }

    @Override
    public Link linkTo(LinkTarget target) {
        final Link link = target.linkTo();
        return Link.between(this, link.to).with(link.attributes);
    }

    @Override
    public Link linkTo() {
        return Link.to(this);
    }

    @Override
    public void addTo(MutableGraph graph) {
        graph.subgraphs.add(this);
    }

    @Override
    public LinkTarget asLinkTarget() {
        return this;
    }

    @Override
    public LinkSource asLinkSource() {
        return this;
    }

    public Collection rootNodes() {
        return nodes;
    }

    public Collection nodes() {
        return collectNodes(new HashSet<>(), new HashSet<>()).getKey();
    }

    public Collection graphs() {
        return subgraphs;
    }

    public List links() {
        return links;
    }

    public Collection rootEdges() {
        return links;
    }

    public Collection edges() {
        return collectNodes(new HashSet<>(), new HashSet<>()).getValue();
    }

    private Entry, Set> collectNodes(Set nodes, Set links) {
        for (final MutableGraph graph : subgraphs) {
            graph.collectNodes(nodes, links);
        }
        for (final MutableNode node : this.nodes) {
            collectNodes(node, nodes, links);
        }
        collectLinks(this.links, nodes, links);
        return new AbstractMap.SimpleEntry<>(nodes, links);
    }

    private void collectNodes(MutableNode node, Set nodes, Set links) {
        if (!nodes.contains(node)) {
            nodes.add(node);
            collectLinks(node.links(), nodes, links);
        }
    }

    private void collectLinks(List edges, Set nodes, Set links) {
        for (final Link link : edges) {
            links.add(link);
            if (link.to instanceof ImmutablePortNode) {
                collectNodes(((ImmutablePortNode) link.to).node(), nodes, links);
            }
            //TODO link.to is graph
        }
    }

    public boolean isStrict() {
        return strict;
    }

    public boolean isDirected() {
        return directed;
    }

    public boolean isCluster() {
        return cluster;
    }

    public Label name() {
        return name;
    }

    public MutableAttributed nodeAttrs() {
        return nodeAttrs;
    }

    public MutableAttributed linkAttrs() {
        return linkAttrs;
    }

    public MutableAttributed graphAttrs() {
        return graphAttrs;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final MutableGraph that = (MutableGraph) o;
        return RECURSION.recurse(this, true, () -> strict == that.strict
                && directed == that.directed
                && cluster == that.cluster
                && Objects.equals(name, that.name)
                && Objects.equals(nodes, that.nodes)
                && Objects.equals(subgraphs, that.subgraphs)
                && Objects.equals(links, that.links)
                && Objects.equals(nodeAttrs, that.nodeAttrs)
                && Objects.equals(linkAttrs, that.linkAttrs)
                && Objects.equals(graphAttrs, that.graphAttrs));
    }

    @Override
    public int hashCode() {
        return RECURSION.recurse(this, 0, () -> Objects.hash(
                strict, directed, cluster, name, nodes, subgraphs, links, nodeAttrs, linkAttrs, graphAttrs));
    }

    @Override
    public String toString() {
        return new Serializer(this).serialize();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy