/* * Copyright 2014 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; import static org.springframework.xd.module.ModuleType.processor; import static org.springframework.xd.module.ModuleType.sink; import static org.springframework.xd.module.ModuleType.source; import org.springframework.xd.module.ModuleType; /** * Captures the context in which a parse operation is made. * * @author Eric Bottard */ public enum ParsingContext { /** * A full stream definition, which ought to start with a source (or channel) and end with a sink (or channel). */ stream(true, true, source, processor, sink), /** * A composed module, which starts or ends on a processor. */ // Read these vertically: either [source, processor, processor] or [processor, processor, sink] module(true, false, new ModuleType[] { source, processor }, new ModuleType[] { processor /* ,processsor */}, new ModuleType[] { processor, sink }), /** * A job definition. */ job(true, false, ModuleType.job, null, null), /** * For the purpose of DSL completion only, a (maybe unfinished) stream definition. */ partial_stream(false, true, new ModuleType[] { source }, new ModuleType[] { processor }, new ModuleType[] { processor, sink }), /** * For the purpose of DSL completion only, a (maybe unfinished) composed module definition. */ partial_module(false, false, new ModuleType[] { source, processor }, new ModuleType[] { processor }, new ModuleType[] { processor, sink }), /** * For the purpose of DSL completion only, a (maybe unfinished) job definition. */ partial_job(false, false, ModuleType.job, null, null); /** * Represents the position of a module in an XD DSL declaration. * * @author Eric Bottard */ public static enum Position { // Do not mess with the order of those! start, middle, end; /** * Return the position instance for a module appearing at {@code index} inside a stream made of [0..lastIndex] * (inclusive). */ public static Position of(int index, int lastIndex) { if (index < 0) { throw new IllegalArgumentException("index can't be negative"); } else if (index == 0) { return start; } else if (index < lastIndex) { return middle; } else if (index == lastIndex) { return end; } else { throw new IllegalArgumentException("index can't be greater than lastIndex"); } } } /** * Return the kinds of modules that may appear at some position in the current parsing context. */ ModuleType[] allowed(Position position) { ModuleType[] result = allowed[position.ordinal()]; if (result == null) { throw new IllegalArgumentException(String.format("A %s can't have a module at position '%s'", this.name(), position.name())); } return result; } public boolean shouldBindAndValidate() { return bindAndValidate; } public boolean supportsNamedChannels() { return supportsNamedChannels; } private ParsingContext(boolean bindAndValidate, boolean supportsNamedChannels, ModuleType atStart, ModuleType atMiddle, ModuleType atEnd) { this(bindAndValidate, supportsNamedChannels, new ModuleType[] { atStart }, new ModuleType[] { atMiddle }, new ModuleType[] { atEnd }); } private ParsingContext(boolean bindAndValidate, boolean supportsNamedChannels, ModuleType[] atStart, ModuleType[] atMiddle, ModuleType[] atEnd) { this.bindAndValidate = bindAndValidate; this.supportsNamedChannels = supportsNamedChannels; allowed[0] = atStart; allowed[1] = atMiddle; allowed[2] = atEnd; } private final ModuleType[][] allowed = new ModuleType[Position.values().length][]; /** * Whether to apply binding and validation to module options. * * <p> * Actual deployments will want this, while partials typically don't contain all required options yet, so we don't * want to fail with a validation exception. */ private final boolean bindAndValidate; private final boolean supportsNamedChannels; }