/* * Copyright 2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.xd.dirt.stream.dsl; import static org.springframework.xd.dirt.stream.dsl.XDDSLMessages.Kind.ERROR; import java.text.MessageFormat; /** * Contains all the messages that can be produced during Spring XD DSL parsing. Each message has a kind (info, warn, * error) and a code number. Tests can be written to expect particular code numbers rather than particular text, * enabling the message text to more easily be modified and the tests to run successfully in different locales. * <p> * When a message is formatted, it will have this kind of form * * <pre class="code"> * XD105E: (pos 34): Expected an argument value but was ' ' * </pre> * * </code> The prefix captures the code and the error kind, whilst the position is included if it is known. * * @author Andy Clement */ public enum XDDSLMessages { UNEXPECTED_DATA_AFTER_STREAMDEF(ERROR, 100, "Found unexpected data after stream definition: ''{0}''"), // NO_WHITESPACE_BEFORE_ARG_NAME(ERROR, 101, "No whitespace allowed between '--' and option name"), // NO_WHITESPACE_BEFORE_ARG_EQUALS(ERROR, 102, "No whitespace allowed after argument name and before '='"), // NO_WHITESPACE_BEFORE_ARG_VALUE(ERROR, 103, "No whitespace allowed after '=' and before option value"), // MORE_INPUT(ERROR, 104, "After parsing a valid stream, there is still more data: ''{0}''"), EXPECTED_ARGUMENT_VALUE( ERROR, 105, "Expected an argument value but was ''{0}''"), NON_TERMINATING_DOUBLE_QUOTED_STRING(ERROR, 106, "Cannot find terminating \" for string"), // NON_TERMINATING_QUOTED_STRING(ERROR, 107, "Cannot find terminating '' for string"), // MISSING_CHARACTER(ERROR, 108, "missing expected character ''{0}''"), NOT_EXPECTED_TOKEN(ERROR, 111, "Unexpected token. Expected ''{0}'' but was ''{1}''"), OOD(ERROR, 112, "Unexpectedly ran out of input"), // UNEXPECTED_ESCAPE_CHAR(ERROR, 114, "unexpected escape character."), // UNEXPECTED_DATA(ERROR, 115, "unexpected data in stream definition ''{0}''"), // UNRECOGNIZED_STREAM_REFERENCE(ERROR, 116, "unrecognized stream reference ''{0}''"), // UNRECOGNIZED_MODULE_REFERENCE(ERROR, 117, "unrecognized module reference ''{0}''"), // EXPECTED_MODULENAME(ERROR, 118, "expected module name but found ''{0}''"), // EXPECTED_WHITESPACE_AFTER_MODULE_BEFORE_ARGUMENT(ERROR, 119, "expected whitespace after module name and before argument"), // EXPECTED_CHANNEL_QUALIFIER(ERROR, 120, "expected channel reference '':<channel>'' but found ''{0}''"), // EXPECTED_CHANNEL_NAME(ERROR, 121, "expected channel name but found ''{0}''"), // ILLEGAL_STREAM_NAME(ERROR, 122, "illegal name for a stream ''{0}''"), // MISSING_VALUE_FOR_VARIABLE(ERROR, 125, "no value specified for variable ''{0}'' when using substream"), // VARIABLE_NOT_TERMINATED(ERROR, 126, "unable to find variable terminator ''}'' in argument ''{0}''"), // AMBIGUOUS_MODULE_NAME(ERROR, 129, "ambiguous module name ''{0}'' in stream named ''{1}'', appears at both position {2} and {3}"), // STREAM_NAME_MATCHING_MODULE_NAME(ERROR, 130, "Stream name ''{0}'' same as that of its modules' names is not allowed."), // CHANNEL_INDEXING_NOT_ALLOWED(ERROR, 131, "Channel does not support indexing"), // ONLY_A_TAP_ON_A_STREAM_OR_JOB_CAN_BE_INDEXED(ERROR, 132, "Only a tap on a stream or job can be indexed"), // EXPECTED_CHANNEL_PREFIX_QUEUE_TOPIC(ERROR, 133, "Expected channel prefix of ''queue'' or ''topic'' but found ''{0}''"), // EXPECTED_CHANNEL_PREFIX_QUEUE_TOPIC_TAP(ERROR, 134, "Expected channel prefix of ''queue'', ''topic'' or ''tap'' but found ''{0}''"), // CANNOT_USE_COMPOSEDMODULE_HERE_AS_IT_DEFINES_SOURCE_CHANNEL(ERROR, 135, "cannot use composed module ''{0}'' here because it defines a source channel"), // CANNOT_USE_COMPOSEDMODULE_HERE_AS_IT_DEFINES_SINK_CHANNEL(ERROR, 136, "cannot use composed module ''{0}'' here because it defines a sink channel"), // CANNOT_USE_COMPOSEDMODULE_HERE_ALREADY_HAS_SOURCE_CHANNEL(ERROR, 137, "cannot use composed module ''{0}'' here, both that composed module and this stream define a source channel"), // CANNOT_USE_COMPOSEDMODULE_HERE_ALREADY_HAS_SINK_CHANNEL(ERROR, 138, "cannot use composed module ''{0}'' here, both that composed module and this stream define a sink channel"), // NO_WHITESPACE_IN_CHANNEL_DEFINITION(ERROR, 139, "no whitespace allowed between components in a channel name"), // NO_WHITESPACE_BETWEEN_LABEL_NAME_AND_COLON(ERROR, 140, "no whitespace allowed between label name and colon"), // TAP_NEEDS_THREE_COMPONENTS(ERROR, 141, "a tap needs at least three components (tap:queue:[name], tap:topic:[name], tap:stream:[streamname] or tap:job:[jobname])"), // NOT_ALLOWED_TO_TAP_THAT(ERROR, 142, "tapping only allowed on 'stream', 'topic', 'job' or 'queue'. Not allowed on ''{0}''"), // DUPLICATE_LABEL(ERROR, 143, "Label ''{0}'' should be unique but module ''{1}'' (at position {2}) and module ''{3}'' (at position {4}) both use it"), // MODULE_REFERENCE_NOT_UNIQUE(ERROR, 144, "Reference to ''{0}'' is not unique in the target stream ''{1}'', please label the relevant module and use the label, or use a suffix index to indicate which occurrence of the module, e.g. ''{0}.0''"), // NO_WHITESPACE_IN_DOTTED_NAME(ERROR, 145, "No whitespace is allowed between dot and components of a name"), NAMED_CHANNELS_UNSUPPORTED_HERE(ERROR, 146, "A named channel is not supported in this kind of definition"), ; private Kind kind; private int code; private String message; private XDDSLMessages(Kind kind, int code, String message) { this.kind = kind; this.code = code; this.message = message; } /** * Produce a complete message including the prefix, the position (if known) and with the inserts applied to the * message. * * @param pos the position, if less than zero it is ignored and not included in the message * @param inserts the inserts to put into the formatted message * @return a formatted message */ public String formatMessage(int pos, Object... inserts) { StringBuilder formattedMessage = new StringBuilder(); formattedMessage.append("XD").append(code); // switch (kind) { // case WARNING: // formattedMessage.append("W"); // break; // case INFO: // formattedMessage.append("I"); // break; // case ERROR: formattedMessage.append("E"); // break; // } formattedMessage.append(":"); if (pos != -1) { formattedMessage.append("(pos ").append(pos).append("): "); } formattedMessage.append(MessageFormat.format(message, inserts)); return formattedMessage.toString(); } public Kind getKind() { return kind; } public static enum Kind { INFO, WARNING, ERROR } }