001/*
002 * Configurate
003 * Copyright (C) zml and Configurate contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.spongepowered.configurate.serialize;
018
019import org.checkerframework.checker.nullness.qual.Nullable;
020import org.spongepowered.configurate.ConfigurateException;
021import org.spongepowered.configurate.ConfigurationNode;
022import org.spongepowered.configurate.NodePath;
023
024import java.lang.reflect.Type;
025
026/**
027 * Exception thrown on errors encountered while using type serializers.
028 *
029 * @since 4.0.0
030 */
031public class SerializationException extends ConfigurateException {
032
033    public static final long serialVersionUID = -910568375387191784L;
034    private transient @Nullable Type expectedType;
035
036    /**
037     * Create an exception with unknown message and cause.
038     *
039     * @since 4.0.0
040     */
041    public SerializationException() {
042    }
043
044    /**
045     * Create an exception without a cause.
046     *
047     * @param message message with information about the exception
048     * @since 4.0.0
049     */
050    public SerializationException(final String message) {
051        super(message);
052    }
053
054    /**
055     * Create an exception with a cause and no additional information.
056     *
057     * @param cause wrapped causing throwable
058     * @since 4.0.0
059     */
060    public SerializationException(final Throwable cause) {
061        super(cause);
062    }
063
064    /**
065     * Create an exception without a cause.
066     *
067     * @param expectedType declared type being processed
068     * @param message message with information about the exception
069     * @since 4.0.0
070     */
071    public SerializationException(final Type expectedType, final String message) {
072        super(message);
073        this.expectedType = expectedType;
074    }
075
076    /**
077     * Create an exception with a cause and no additional information.
078     *
079     * @param expectedType declared type being processed
080     * @param cause wrapped causing throwable
081     * @since 4.0.0
082     */
083    public SerializationException(final Type expectedType, final Throwable cause) {
084        super(cause);
085        this.expectedType = expectedType;
086    }
087
088    /**
089     * Create an exception with message and wrapped cause.
090     *
091     * @param expectedType declared type being processed
092     * @param message informational message
093     * @param cause cause to be wrapped
094     * @since 4.0.0
095     */
096    public SerializationException(final Type expectedType, final String message, final Throwable cause) {
097        super(message, cause);
098        this.expectedType = expectedType;
099    }
100
101    /**
102     * Create an exception with a message and unknown cause.
103     *
104     * @param node node being processed
105     * @param message informational message
106     * @param expectedType declared type being processed
107     * @since 4.0.0
108     */
109    public SerializationException(final ConfigurationNode node, final Type expectedType, final String message) {
110        this(node, expectedType, message, null);
111    }
112
113    /**
114     * Create an exception with wrapped cause.
115     *
116     * @param node node being processed
117     * @param expectedType declared type being processed
118     * @param cause cause to be wrapped
119     * @since 4.0.0
120     */
121    public SerializationException(final ConfigurationNode node, final Type expectedType, final Throwable cause) {
122        this(node, expectedType, null, cause);
123    }
124
125    /**
126     * Create an exception with message and wrapped cause.
127     *
128     * @param node node being processed
129     * @param expectedType declared type being processed
130     * @param message informational message
131     * @param cause cause to be wrapped
132     * @since 4.0.0
133     */
134    public SerializationException(final ConfigurationNode node, final Type expectedType,
135            final @Nullable String message, final @Nullable Throwable cause) {
136        super(node, message, cause);
137        this.expectedType = expectedType;
138    }
139
140    /**
141     * Create an exception with message and wrapped cause.
142     *
143     * @param path path to node being processed
144     * @param expectedType declared type being processed
145     * @param message informational message
146     * @since 4.0.0
147     */
148    public SerializationException(final NodePath path, final Type expectedType, final String message) {
149        super(path, message, null);
150
151        this.expectedType = expectedType;
152    }
153
154    /**
155     * Get the desired type associated with the failed object mapping operation.
156     *
157     * @return type
158     * @since 4.0.0
159     */
160    public @Nullable Type expectedType() {
161        return this.expectedType;
162    }
163
164    @Override
165    public @Nullable String getMessage() {
166        if (this.expectedType == null) {
167            return super.getMessage();
168        } else {
169            return path() + " of type " + this.expectedType.getTypeName() + ": " + rawMessage();
170        }
171    }
172
173    /**
174     * Initialize the expected type.
175     *
176     * <p>If a type has already been set, it will not be overridden.</p>
177     *
178     * @param type expected type
179     * @since 4.0.0
180     */
181    public void initType(final Type type) {
182        if (this.expectedType == null) {
183            this.expectedType = type;
184        }
185    }
186
187}