001/* Copyright 2016-2017 Clifton Labs
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 * http://www.apache.org/licenses/LICENSE-2.0
006 * Unless required by applicable law or agreed to in writing, software
007 * distributed under the License is distributed on an "AS IS" BASIS,
008 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
009 * See the License for the specific language governing permissions and
010 * limitations under the License. */
011package org.json.simple;
012
013/** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization.
014 * @since 2.0.0 */
015public class DeserializationException extends Exception{
016        /** The kinds of exceptions that can trigger a DeserializationException. */
017        public enum Problems{
018                @SuppressWarnings("javadoc")
019                DISALLOWED_TOKEN,
020                /** @since 2.3.0 to consolidate exceptions that occur during deserialization. */
021                IOEXCEPTION,
022                @SuppressWarnings("javadoc")
023                UNEXPECTED_CHARACTER,
024                @SuppressWarnings("javadoc")
025                UNEXPECTED_EXCEPTION,
026                @SuppressWarnings("javadoc")
027                UNEXPECTED_TOKEN;
028        }
029
030        private static final long       serialVersionUID        = 1L;
031        private final int                       position;
032        private final Problems          problemType;
033        private final Object            unexpectedObject;
034
035        /** Instantiates a DeserializationException without assumptions.
036         * @param position where the exception occurred.
037         * @param problemType how the exception occurred.
038         * @param unexpectedObject what caused the exception. */
039        public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject){
040                this.position = position;
041                this.problemType = problemType;
042                this.unexpectedObject = unexpectedObject;
043                if(Problems.IOEXCEPTION.equals(problemType) || Problems.UNEXPECTED_EXCEPTION.equals(problemType)){
044                        if(unexpectedObject instanceof Throwable){
045                                this.initCause((Throwable)unexpectedObject);
046                        }
047                }
048        }
049
050        @Override
051        public String getMessage(){
052                final StringBuilder sb = new StringBuilder();
053                switch(this.problemType){
054                        case DISALLOWED_TOKEN:
055                                sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again.");
056                                break;
057                        case IOEXCEPTION:
058                                sb.append("An IOException was encountered, ensure the reader is properly instantiated, isn't closed, or that it is ready before trying again.\n").append(this.unexpectedObject);
059                                break;
060                        case UNEXPECTED_CHARACTER:
061                                sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". Fix the parsable string and try again.");
062                                break;
063                        case UNEXPECTED_TOKEN:
064                                sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position).append(". Fix the parsable string and try again.");
065                                break;
066                        case UNEXPECTED_EXCEPTION:
067                                sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ").append(this.position).append(":\n").append(this.unexpectedObject);
068                                break;
069                        default:
070                                sb.append("Please report this to the library's maintainer. An error at position ").append(this.position).append(" occurred. There are no recovery recommendations available.");
071                                break;
072                }
073                return sb.toString();
074        }
075
076        /** Helps debug the location of a problem.
077         * @return an index of the string character the error type occurred at. */
078        public int getPosition(){
079                return this.position;
080        }
081
082        /** Helps find an appropriate solution for a problem.
083         * @return the enumeration for how the exception occurred. */
084        public Problems getProblemType(){
085                return this.problemType;
086        }
087
088        /** Helps identify the problem.
089         * @return a representation of what caused the exception. */
090        public Object getUnexpectedObject(){
091                return this.unexpectedObject;
092        }
093}