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.AnnotatedType;
025import java.lang.reflect.Type;
026
027/**
028 * Exception thrown on errors encountered while using type serializers.
029 *
030 * @since 4.0.0
031 */
032public class SerializationException extends ConfigurateException {
033
034    public static final long serialVersionUID = -910568375387191784L;
035    private transient @Nullable Type expectedType;
036
037    /**
038     * Create an exception with unknown message and cause.
039     *
040     * @since 4.0.0
041     */
042    public SerializationException() {
043    }
044
045    /**
046     * Create an exception without a cause.
047     *
048     * @param message message with information about the exception
049     * @since 4.0.0
050     */
051    public SerializationException(final String message) {
052        super(message);
053    }
054
055    /**
056     * Create an exception with a cause and no additional information.
057     *
058     * @param cause wrapped causing throwable
059     * @since 4.0.0
060     */
061    public SerializationException(final Throwable cause) {
062        super(cause);
063    }
064
065    /**
066     * Create an exception without a cause.
067     *
068     * @param expectedType declared type being processed
069     * @param message message with information about the exception
070     * @since 4.0.0
071     */
072    public SerializationException(final Type expectedType, final String message) {
073        super(message);
074        this.expectedType = expectedType;
075    }
076
077    /**
078     * Create an exception without a cause.
079     *
080     * @param expectedType declared type being processed
081     * @param message message with information about the exception
082     * @since 4.2.0
083     */
084    public SerializationException(final AnnotatedType expectedType, final String message) {
085        super(message);
086        this.expectedType = expectedType.getType();
087    }
088
089    /**
090     * Create an exception with a cause and no additional information.
091     *
092     * @param expectedType declared type being processed
093     * @param cause wrapped causing throwable
094     * @since 4.0.0
095     */
096    public SerializationException(final Type expectedType, final Throwable cause) {
097        super(cause);
098        this.expectedType = expectedType;
099    }
100
101    /**
102     * Create an exception with a cause and no additional information.
103     *
104     * @param expectedType declared type being processed
105     * @param cause wrapped causing throwable
106     * @since 4.2.0
107     */
108    public SerializationException(final AnnotatedType expectedType, final Throwable cause) {
109        super(cause);
110        this.expectedType = expectedType.getType();
111    }
112
113    /**
114     * Create an exception with message and wrapped cause.
115     *
116     * @param expectedType declared type being processed
117     * @param message informational message
118     * @param cause cause to be wrapped
119     * @since 4.0.0
120     */
121    public SerializationException(final Type expectedType, final String message, final Throwable cause) {
122        super(message, cause);
123        this.expectedType = expectedType;
124    }
125
126    /**
127     * Create an exception with message and wrapped cause.
128     *
129     * @param expectedType declared type being processed
130     * @param message informational message
131     * @param cause cause to be wrapped
132     * @since 4.2.0
133     */
134    public SerializationException(final AnnotatedType expectedType, final String message, final Throwable cause) {
135        super(message, cause);
136        this.expectedType = expectedType.getType();
137    }
138
139    /**
140     * Create an exception with a message and unknown cause.
141     *
142     * @param node node being processed
143     * @param message informational message
144     * @param expectedType declared type being processed
145     * @since 4.0.0
146     */
147    public SerializationException(final ConfigurationNode node, final Type expectedType, final String message) {
148        this(node, expectedType, message, null);
149    }
150
151    /**
152     * Create an exception with a message and unknown cause.
153     *
154     * @param node node being processed
155     * @param message informational message
156     * @param expectedType declared type being processed
157     * @since 4.2.0
158     */
159    public SerializationException(final ConfigurationNode node, final AnnotatedType expectedType, final String message) {
160        this(node, expectedType, message, null);
161    }
162
163    /**
164     * Create an exception with wrapped cause.
165     *
166     * @param node node being processed
167     * @param expectedType declared type being processed
168     * @param cause cause to be wrapped
169     * @since 4.0.0
170     */
171    public SerializationException(final ConfigurationNode node, final Type expectedType, final Throwable cause) {
172        this(node, expectedType, null, cause);
173    }
174
175    /**
176     * Create an exception with wrapped cause.
177     *
178     * @param node node being processed
179     * @param expectedType declared type being processed
180     * @param cause cause to be wrapped
181     * @since 4.2.0
182     */
183    public SerializationException(final ConfigurationNode node, final AnnotatedType expectedType, final Throwable cause) {
184        this(node, expectedType, null, cause);
185    }
186
187    /**
188     * Create an exception with message and wrapped cause.
189     *
190     * @param node node being processed
191     * @param expectedType declared type being processed
192     * @param message informational message
193     * @param cause cause to be wrapped
194     * @since 4.0.0
195     */
196    public SerializationException(final ConfigurationNode node, final Type expectedType,
197            final @Nullable String message, final @Nullable Throwable cause) {
198        super(node, message, cause);
199        this.expectedType = expectedType;
200    }
201
202    /**
203     * Create an exception with message and wrapped cause.
204     *
205     * @param node node being processed
206     * @param expectedType declared type being processed
207     * @param message informational message
208     * @param cause cause to be wrapped
209     * @since 4.2.0
210     */
211    public SerializationException(final ConfigurationNode node, final AnnotatedType expectedType,
212            final @Nullable String message, final @Nullable Throwable cause) {
213        super(node, message, cause);
214        this.expectedType = expectedType.getType();
215    }
216
217    /**
218     * Create an exception with message and wrapped cause.
219     *
220     * @param path path to node being processed
221     * @param expectedType declared type being processed
222     * @param message informational message
223     * @since 4.0.0
224     */
225    public SerializationException(final NodePath path, final Type expectedType, final String message) {
226        super(path, message, null);
227
228        this.expectedType = expectedType;
229    }
230
231    /**
232     * Create an exception with message and wrapped cause.
233     *
234     * @param path path to node being processed
235     * @param expectedType declared type being processed
236     * @param message informational message
237     * @since 4.2.0
238     */
239    public SerializationException(final NodePath path, final AnnotatedType expectedType, final String message) {
240        super(path, message, null);
241        this.expectedType = expectedType.getType();
242    }
243
244    /**
245     * Get the desired type associated with the failed object mapping operation.
246     *
247     * @return type
248     * @since 4.0.0
249     */
250    public @Nullable Type expectedType() {
251        return this.expectedType;
252    }
253
254    @Override
255    public @Nullable String getMessage() {
256        if (this.expectedType == null) {
257            return super.getMessage();
258        } else {
259            return this.path() + " of type " + this.expectedType.getTypeName() + ": " + this.rawMessage();
260        }
261    }
262
263    /**
264     * Initialize the expected type.
265     *
266     * <p>If a type has already been set, it will not be overridden.</p>
267     *
268     * @param type expected type
269     * @since 4.0.0
270     */
271    public void initType(final Type type) {
272        if (this.expectedType == null) {
273            this.expectedType = type;
274        }
275    }
276
277    /**
278     * Initialize the expected type.
279     *
280     * <p>If a type has already been set, it will not be overridden.</p>
281     *
282     * @param type expected type
283     * @since 4.2.0
284     */
285    public final void initType(final AnnotatedType type) {
286        if (this.expectedType == null) {
287            this.expectedType = type.getType();
288        }
289    }
290
291}