001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.Arrays; 005import java.util.function.Predicate; 006import java.util.stream.Collectors; 007import java.util.stream.Stream; 008 009import org.openstreetmap.josm.command.Command; 010import org.openstreetmap.josm.data.UndoRedoHandler; 011 012/** 013 * Exception thrown when a primitive or data set does not pass its integrity checks. 014 * @since 2399 015 */ 016public class DataIntegrityProblemException extends RuntimeException { 017 018 private final String htmlMessage; 019 020 /** 021 * Constructs a new {@code DataIntegrityProblemException}. 022 * @param message the detail message 023 */ 024 public DataIntegrityProblemException(String message) { 025 this(message, null); 026 } 027 028 /** 029 * Constructs a new {@code DataIntegrityProblemException}. 030 * @param message the detail message 031 * @param htmlMessage HTML-formatted error message. Can be null 032 * @param p the primitive involved in this integrity problem (used for constructing a detailed message) 033 */ 034 public DataIntegrityProblemException(String message, String htmlMessage, OsmPrimitive... p) { 035 super(message + relevantCommands(p)); 036 this.htmlMessage = htmlMessage; 037 } 038 039 /** 040 * Returns the HTML-formatted error message. 041 * @return the HTML-formatted error message, or null 042 */ 043 public String getHtmlMessage() { 044 return htmlMessage; 045 } 046 047 private static String relevantCommands(OsmPrimitive... p) { 048 if (p == null || p.length == 0) { 049 return ""; 050 } 051 Predicate<Command> isParticipating = c -> Arrays.stream(p).anyMatch(c.getParticipatingPrimitives()::contains); 052 Stream<String> undo = UndoRedoHandler.getInstance().getUndoCommands().stream() 053 .filter(isParticipating) 054 .map(c -> "[" + c.getDescriptionText() + "]"); 055 Stream<String> redo = UndoRedoHandler.getInstance().getRedoCommands().stream() 056 .filter(isParticipating) 057 .map(c -> "[" + c.getDescriptionText() + " (undone)]"); 058 return Stream.concat(undo, redo) 059 .collect(Collectors.joining(", ", " (changed by the following commands: ", ")")); 060 } 061}