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; 010 011/** 012 * This is an exception that is thrown if the user attempts to upload a list of relations with a cyclic dependency in them 013 * @since 12673 (moved from {@code action.upload} package) 014 */ 015public class CyclicUploadDependencyException extends Exception { 016 private final List<Relation> cycle; 017 018 /** 019 * Creates a new {@link CyclicUploadDependencyException} 020 * @param cycle The cycle that was found 021 */ 022 public CyclicUploadDependencyException(Stack<Relation> cycle) { 023 this.cycle = new ArrayList<>(cycle); 024 } 025 026 protected String formatRelation(Relation r) { 027 StringBuilder sb = new StringBuilder(); 028 if (r.getName() != null) { 029 sb.append('\'').append(r.getName()).append('\''); 030 } else if (!r.isNew()) { 031 sb.append(r.getId()); 032 } else { 033 sb.append("relation@").append(r.hashCode()); 034 } 035 return sb.toString(); 036 } 037 038 @Override 039 public String getMessage() { 040 StringBuilder sb = new StringBuilder(); 041 sb.append(tr("Cyclic dependency between relations:")) 042 .append('['); 043 for (int i = 0; i < cycle.size(); i++) { 044 if (i > 0) { 045 sb.append(','); 046 } 047 sb.append(formatRelation(cycle.get(i))); 048 } 049 sb.append(']'); 050 return sb.toString(); 051 } 052 053 /** 054 * Gets the cycle 055 * @return The cycle that was detected 056 */ 057 public List<Relation> getCyclicUploadDependency() { 058 return Collections.unmodifiableList(cycle); 059 } 060}