001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 the ConQAT Project                                   |
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 eu.cqse.check.framework.shallowparser.util;
018
019import org.conqat.lib.commons.string.StringUtils;
020
021import eu.cqse.check.framework.shallowparser.ShallowParserException;
022
023/**
024 * Exception for parsing errors in the {@link EntitySelectionExpressionParser}.
025 */
026public class EntitySelectionExpressionParsingException extends ShallowParserException {
027
028        /** Version for serialization. */
029        private static final long serialVersionUID = 1;
030
031        /** The message identifier. */
032        private final EParsingExceptionMessage messageIdentifier;
033
034        /**
035         * Constructor.
036         * 
037         * @param expression
038         *            the expression being parsed.
039         * @param position
040         *            the current parsing position in the message.
041         * 
042         */
043        public EntitySelectionExpressionParsingException(EParsingExceptionMessage messageIdentifier, String expression,
044                        int position) {
045                super(createMessage(messageIdentifier, expression, position, null));
046                this.messageIdentifier = messageIdentifier;
047        }
048
049        /**
050         * Constructor.
051         * 
052         * @param expression
053         *            the expression being parsed.
054         * @param position
055         *            the current parsing position in the message.
056         * @param cause
057         *            may not be null.
058         * 
059         */
060        public EntitySelectionExpressionParsingException(EParsingExceptionMessage messageIdentifier, String expression,
061                        int position, Throwable cause) {
062                super(createMessage(messageIdentifier, expression, position, cause), cause);
063                this.messageIdentifier = messageIdentifier;
064        }
065
066        /** Creates the message for this exception. */
067        private static String createMessage(EParsingExceptionMessage messageIdentifier, String expression, int position,
068                        Throwable cause) {
069
070                String message = messageIdentifier.getMessage();
071                if (cause != null) {
072                        message += ": " + cause.getMessage();
073                }
074
075                if (!StringUtils.endsWithOneOf(message, ".", "!")) {
076                        message += ".";
077                }
078
079                String details = "The error occurred at or before the position marked with a caret: "
080                                + expression.substring(0, position) + "^" + expression.substring(position);
081                return message + " " + details;
082        }
083
084        /** Returns the message identifier. */
085        public EParsingExceptionMessage getMessageIdentifier() {
086                return messageIdentifier;
087        }
088
089        /**
090         * Enumeration of valid messages for this exception. This is both to reduce
091         * redundancy and to simplify testing.
092         */
093        public static enum EParsingExceptionMessage {
094
095                /** Message. */
096                EXPECTED_EXPRESSION("Expected an expression before or at this position."),
097
098                /** Message. */
099                EXPECTED_BINARY_OPERATOR("Expected a binary operator such as & or |."),
100
101                /** Message. */
102                PREDICATE_CONSTRUCTION_FAILED("Failed to construct predicate"),
103
104                /** Message. */
105                PARAMETER_MISSING("Must provide parameter for this predicate!"),
106
107                /** Message. */
108                UNSUPPORTED_PARAMETER("May not provide parameter for this predicate!"),
109
110                /** Message. */
111                PREDICATE_NOT_FOUND("No matching predicate found!"),
112
113                /** Message. */
114                MISSING_CLOSING_PARENTHESIS("Missing closing parenthesis!"),
115
116                /** Message. */
117                MISPLACED_CLOSING_PARENTHESIS("Misplaced closing parenthesis."),
118
119                /** Message. */
120                UNEXPECTED_CHARACTER("Unexpected character.");
121
122                /** The message for the exception. */
123                private final String message;
124
125                /** Constructor. */
126                private EParsingExceptionMessage(String message) {
127                        this.message = message;
128                }
129
130                /** Returns the message for the exception. */
131                public String getMessage() {
132                        return message;
133                }
134        }
135}