001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.List;
009import java.util.Stack;
010import java.util.stream.Collectors;
011
012/**
013 * This is an exception that is thrown if the user attempts to upload a list of relations with a cyclic dependency in them
014 * @since 12673 (moved from {@code action.upload} package)
015 */
016public class CyclicUploadDependencyException extends Exception {
017    private final List<Relation> cycle;
018
019    /**
020     * Creates a new {@link CyclicUploadDependencyException}
021     * @param cycle The cycle that was found
022     */
023    public CyclicUploadDependencyException(Stack<Relation> cycle) {
024        this.cycle = new ArrayList<>(cycle);
025    }
026
027    protected String formatRelation(Relation r) {
028        StringBuilder sb = new StringBuilder();
029        if (r.getName() != null) {
030            sb.append('\'').append(r.getName()).append('\'');
031        } else if (!r.isNew()) {
032            sb.append(r.getId());
033        } else {
034            sb.append("relation@").append(r.hashCode());
035        }
036        return sb.toString();
037    }
038
039    @Override
040    public String getMessage() {
041        return cycle.stream().map(this::formatRelation)
042                .collect(Collectors.joining(",", tr("Cyclic dependency between relations:") + '[', "]"));
043    }
044
045    /**
046     * Gets the cycle
047     * @return The cycle that was detected
048     */
049    public List<Relation> getCyclicUploadDependency() {
050        return Collections.unmodifiableList(cycle);
051    }
052}