/* * Copyright 2017 TNG Technology Consulting GmbH * * 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 com.tngtech.archunit.library.dependencies; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import static com.google.common.collect.Iterables.getLast; class Path<T, ATTACHMENT> { private final List<Edge<T, ATTACHMENT>> edges; Path() { this(Collections.<Edge<T, ATTACHMENT>>emptyList()); } Path(Path<T, ATTACHMENT> other) { this(other.getEdges()); } Path(Edge<T, ATTACHMENT> edge) { this(Collections.singletonList(edge)); } Path(List<Edge<T, ATTACHMENT>> edges) { this.edges = new ArrayList<>(edges); validateEdgesConnect(); } private void validateEdgesConnect() { if (edges.isEmpty()) { return; } Object expectedFrom = edges.get(0).getFrom(); for (Edge<T, ?> edge : edges) { verifyEdgeFromMatches(expectedFrom, edge); expectedFrom = edge.getTo(); } } private void verifyEdgeFromMatches(Object expectedFrom, Edge<T, ?> edge) { if (!expectedFrom.equals(edge.getFrom())) { throw new IllegalArgumentException("Edges are not connected: " + edges); } } List<Edge<T, ATTACHMENT>> getEdges() { return ImmutableList.copyOf(edges); } Set<Edge<T, ATTACHMENT>> getSetOfEdges() { return ImmutableSet.copyOf(edges); } Path<T, ATTACHMENT> append(Edge<T, ATTACHMENT> edge) { if (!edges.isEmpty()) { verifyEdgeFromMatches(getLast(edges).getTo(), edge); } edges.add(edge); return this; } boolean isEmpty() { return edges.isEmpty(); } T getStart() { if (edges.isEmpty()) { throw new NoSuchElementException("Empty path has no start"); } return edges.get(0).getFrom(); } T getEnd() { if (edges.isEmpty()) { throw new NoSuchElementException("Empty path has no end"); } return edges.get(edges.size() - 1).getTo(); } public boolean isCycle() { return !isEmpty() && getStart().equals(getEnd()); } @Override public int hashCode() { return Objects.hash(edges); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } final Path<?, ?> other = (Path<?, ?>) obj; return Objects.equals(this.edges, other.edges); } @Override public String toString() { return "Path{" + edgesToString() + '}'; } String edgesToString() { return "edges=" + edges; } }