spring Command 源码

  • 2022-08-12
  • 浏览 (396)

springboot Command 代码

文件路径:/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/main/java/org/springframework/boot/jarmode/layertools/Command.java

/*
 * Copyright 2012-2020 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
 *
 *      https://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.boot.jarmode.layertools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * A command that can be launched from the layertools jarmode.
 *
 * @author Phillip Webb
 * @author Scott Frederick
 */
abstract class Command {

	private final String name;

	private final String description;

	private final Options options;

	private final Parameters parameters;

	/**
	 * Create a new {@link Command} instance.
	 * @param name the name of the command
	 * @param description a description of the command
	 * @param options the command options
	 * @param parameters the command parameters
	 */
	Command(String name, String description, Options options, Parameters parameters) {
		this.name = name;
		this.description = description;
		this.options = options;
		this.parameters = parameters;
	}

	/**
	 * Return the name of this command.
	 * @return the command name
	 */
	String getName() {
		return this.name;
	}

	/**
	 * Return the description of this command.
	 * @return the command description
	 */
	String getDescription() {
		return this.description;
	}

	/**
	 * Return options that this command accepts.
	 * @return the command options
	 */
	Options getOptions() {
		return this.options;
	}

	/**
	 * Return parameters that this command accepts.
	 * @return the command parameters
	 */
	Parameters getParameters() {
		return this.parameters;
	}

	/**
	 * Run the command by processing the remaining arguments.
	 * @param args a mutable deque of the remaining arguments
	 */
	final void run(Deque<String> args) {
		List<String> parameters = new ArrayList<>();
		Map<Option, String> options = new HashMap<>();
		while (!args.isEmpty()) {
			String arg = args.removeFirst();
			Option option = this.options.find(arg);
			if (option != null) {
				options.put(option, option.claimArg(args));
			}
			else {
				parameters.add(arg);
			}
		}
		run(options, parameters);
	}

	/**
	 * Run the actual command.
	 * @param options any options extracted from the arguments
	 * @param parameters any parameters extracted from the arguments
	 */
	protected abstract void run(Map<Option, String> options, List<String> parameters);

	/**
	 * Static method that can be used to find a single command from a collection.
	 * @param commands the commands to search
	 * @param name the name of the command to find
	 * @return a {@link Command} instance or {@code null}.
	 */
	static Command find(Collection<? extends Command> commands, String name) {
		for (Command command : commands) {
			if (command.getName().equals(name)) {
				return command;
			}
		}
		return null;
	}

	/**
	 * Parameters that the command accepts.
	 */
	protected static final class Parameters {

		private final List<String> descriptions;

		private Parameters(String[] descriptions) {
			this.descriptions = Collections.unmodifiableList(Arrays.asList(descriptions));
		}

		/**
		 * Return the parameter descriptions.
		 * @return the descriptions
		 */
		List<String> getDescriptions() {
			return this.descriptions;
		}

		@Override
		public String toString() {
			return this.descriptions.toString();
		}

		/**
		 * Factory method used if there are no expected parameters.
		 * @return a new {@link Parameters} instance
		 */
		protected static Parameters none() {
			return of();
		}

		/**
		 * Factory method used to create a new {@link Parameters} instance with specific
		 * descriptions.
		 * @param descriptions the parameter descriptions
		 * @return a new {@link Parameters} instance with the given descriptions
		 */
		protected static Parameters of(String... descriptions) {
			return new Parameters(descriptions);
		}

	}

	/**
	 * Options that the command accepts.
	 */
	protected static final class Options {

		private final Option[] values;

		private Options(Option[] values) {
			this.values = values;
		}

		private Option find(String arg) {
			if (arg.startsWith("--")) {
				String name = arg.substring(2);
				for (Option candidate : this.values) {
					if (candidate.getName().equals(name)) {
						return candidate;
					}
				}
				throw new UnknownOptionException(name);
			}
			return null;
		}

		/**
		 * Return if this options collection is empty.
		 * @return if there are no options
		 */
		boolean isEmpty() {
			return this.values.length == 0;
		}

		/**
		 * Return a stream of each option.
		 * @return a stream of the options
		 */
		Stream<Option> stream() {
			return Arrays.stream(this.values);
		}

		/**
		 * Factory method used if there are no expected options.
		 * @return a new {@link Options} instance
		 */
		protected static Options none() {
			return of();
		}

		/**
		 * Factory method used to create a new {@link Options} instance with specific
		 * values.
		 * @param values the option values
		 * @return a new {@link Options} instance with the given values
		 */
		protected static Options of(Option... values) {
			return new Options(values);
		}

	}

	/**
	 * An individual option that the command can accepts. Can either be an option with a
	 * value (e.g. {@literal --log debug}) or a flag (e.g. {@literal
	 * --verbose}).
	 */
	protected static final class Option {

		private final String name;

		private final String valueDescription;

		private final String description;

		private Option(String name, String valueDescription, String description) {
			this.name = name;
			this.description = description;
			this.valueDescription = valueDescription;
		}

		/**
		 * Return the name of the option.
		 * @return the options name
		 */
		String getName() {
			return this.name;
		}

		/**
		 * Return the description of the expected argument value or {@code null} if this
		 * option is a flag/switch.
		 * @return the option value description
		 */
		String getValueDescription() {
			return this.valueDescription;
		}

		/**
		 * Return the name and the value description combined.
		 * @return the name and value description
		 */
		String getNameAndValueDescription() {
			return this.name + ((this.valueDescription != null) ? " " + this.valueDescription : "");
		}

		/**
		 * Return a description of the option.
		 * @return the option description
		 */
		String getDescription() {
			return this.description;
		}

		private String claimArg(Deque<String> args) {
			if (this.valueDescription != null) {
				if (args.isEmpty()) {
					throw new MissingValueException(this.name);
				}
				return args.removeFirst();
			}
			return null;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj) {
				return true;
			}
			if (obj == null || getClass() != obj.getClass()) {
				return false;
			}
			return this.name.equals(((Option) obj).name);
		}

		@Override
		public int hashCode() {
			return this.name.hashCode();
		}

		@Override
		public String toString() {
			return this.name;
		}

		/**
		 * Factory method to create a flag/switch option.
		 * @param name the name of the option
		 * @param description a description of the option
		 * @return a new {@link Option} instance
		 */
		protected static Option flag(String name, String description) {
			return new Option(name, null, description);
		}

		/**
		 * Factory method to create value option.
		 * @param name the name of the option
		 * @param valueDescription a description of the expected value
		 * @param description a description of the option
		 * @return a new {@link Option} instance
		 */
		protected static Option of(String name, String valueDescription, String description) {
			return new Option(name, valueDescription, description);
		}

	}

}

相关信息

spring 源码目录

相关文章

spring Context 源码

spring ExtractCommand 源码

spring HelpCommand 源码

spring IndexedLayers 源码

spring LayerToolsJarMode 源码

spring Layers 源码

spring ListCommand 源码

spring MissingValueException 源码

spring UnknownOptionException 源码

spring package-info 源码

0  赞