001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.util.Optional;
007
008import javax.xml.stream.Location;
009import javax.xml.stream.XMLStreamException;
010
011/**
012 * Exception for unexpected processing errors during XML stream parsing.
013 * It uses proper JOSM i18n system to translate error message, including file location.
014 * @since 10235
015 */
016public class XmlStreamParsingException extends XMLStreamException {
017
018    /**
019     * Constructs a new {@code XmlStreamParsingException}.
020     * @param msg error message
021     * @param location file location
022     */
023    public XmlStreamParsingException(String msg, Location location) {
024        super(msg); /* cannot use super(msg, location) because it messes with the message preventing localization */
025        this.location = location;
026    }
027
028    /**
029     * Constructs a new {@code XmlStreamParsingException}.
030     * @param msg error message
031     * @param location file location
032     * @param th Throwable cause
033     */
034    public XmlStreamParsingException(String msg, Location location, Throwable th) {
035        super(msg, th);
036        this.location = location;
037    }
038
039    @Override
040    public String getMessage() {
041        String msg = Optional.ofNullable(super.getMessage()).orElseGet(() -> getClass().getName());
042        if (getLocation() == null)
043            return msg;
044        StringBuilder sb = new StringBuilder(msg).append(' ')
045                .append(tr("(at line {0}, column {1})", getLocation().getLineNumber(), getLocation().getColumnNumber()));
046        int offset = getLocation().getCharacterOffset();
047        if (offset > -1) {
048            sb.append(". ").append(tr("{0} bytes have been read", offset));
049        }
050        return sb.toString();
051    }
052}