Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.zodiac.sdk.cli;
import io.vavr.control.Either;
import io.vavr.control.Try;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public final class Parser {
Class clazz;
Checker checker;
public Parser(final Class clazz) {
this.clazz = clazz;
checker = new Checker<>(clazz);
}
public Try> parse(final String in) {
return Try.of(() -> tokenize(in));
}
private Either tokenize(final String in) throws ParseError {
try {
final T instance = make(clazz);
final Command command;
SubCommand subCommand = null;
Argument argument = null;
List lexemes = splitBySpace(in);
command = checker.command(lexemes.get(0));
if (command == null) {
throw new ParseError(lexemes.get(0) + " is not a valid command!");
}
lexemes.remove(0);
if (lexemes.get(0).equals("help")) {
if (lexemes.size() > 1 && checker.isSubCommand(lexemes.get(1))) {
return Either.left(checker.help(checker.subCommand(lexemes.get(1))));
}
return Either.left(checker.help());
}
if (!checker.subCommands.isEmpty()) {
subCommand = checker.subCommand(lexemes.get(0));
if (subCommand == null) {
throw new ParseError(lexemes.get(0) + " is not a valid subCommand!");
}
lexemes.remove(0);
if (lexemes.get(0).equals("help")) {
return Either.left(checker.help(subCommand));
}
final String lastLexeme = lexemes.get(lexemes.size() - 1);
if (checker.isArgument(subCommand, lastLexeme)) {
argument = checker.argument(subCommand, lastLexeme);
if (argument == null) {
throw new ParseError(lastLexeme + " is not a valid subCommand argument for + " + subCommand.name() + "!");
}
setField(instance, clazz, subCommand.name(), lastLexeme);
}
lexemes.remove(lexemes.get(lexemes.size() - 1));
}
lexemes = splitByFlagOrOption(String.join(" ", lexemes));
for (int i = 0; i < lexemes.size(); i++) {
final String lexeme = lexemes.get(i);
final String nextLexeme = i <= lexemes.size() - 2 ? lexemes.get(i + 1) : null;
if (checker.isFlag(lexeme)) {
setField(instance, clazz, checker.flag(lexeme).name(), true);
} else if (checker.isOption(lexeme)) {
final Option option = checker.option(lexeme);
if (nextLexeme == null) {
throw new ParseError("No valid argument was found following the " + option.name() + " option!");
}
final Argument arg = checker.argument(option, nextLexeme);
if (arg == null) {
throw new ParseError(nextLexeme + " is not a valid argument for option " + option.name() + "!");
}
if (clazz.getDeclaredField(option.name()).getType() == String.class) {
setField(instance, clazz, option.name(), nextLexeme);
} else if (clazz.getDeclaredField(option.name()).getType() == List.class) {
@SuppressWarnings("unchecked")
List value = (List) getField(instance, clazz, option.name());
value = value == null ? new ArrayList<>() : value;
value.add(nextLexeme);
setField(instance, clazz, option.name(), value);
} else if (clazz.getDeclaredField(option.name()).getType().toString().equals("int")) {
setField(instance, clazz, option.name(), Integer.parseInt(nextLexeme));
} else {
System.out.println("Warning: " + option.name() + " was neither a String or List, and hence could not be set.");
}
i++;
} else if (checker.isArgument(subCommand, lexeme)) {
if (argument != null) {
throw new ParseError("More than one argument for subCommand " + subCommand.name() + " was found!");
}
argument = checker.argument(subCommand, lexeme);
if (argument == null) {
throw new ParseError(lexeme + " is not a valid subCommand argument for + " + subCommand.name() + "!");
}
setField(instance, clazz, subCommand.name(), lexeme);
} else if (checker.isSubCommand(lexeme)) {
throw new ParseError("Second subCommand specified: " + lexeme + ". SubCommand '" + subCommand.name() + "' was already supplied.");
} else {
throw new ParseError(lexeme + " is not a valid flag or option!");
}
}
return Either.right(instance);
} catch (final Exception e) {
throw new ParseError(e.getMessage(), e);
}
}
public String help() {
return checker.help();
}
public String help(final SubCommand subCommand) {
return checker.help(subCommand);
}
private static T make(final Class clazz) throws ParseError {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (final InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new ParseError("The class " + clazz.getSimpleName() + " could not be instantiated for some reason. Please make sure that the annotations were used properly.");
}
}
private static void setField(
final T instance,
final Class clazz,
final String name,
final Object value) throws NoSuchFieldException, IllegalAccessException {
final Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(instance, value);
}
private static Object getField(
final T instance,
final Class clazz,
final String name) throws IllegalAccessException, NoSuchFieldException {
final Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(instance);
}
private List splitByFlagOrOption(final String in) {
final String command = checker.command.name();
final List subCommands = checker.subCommands.stream().map(SubCommand::name).collect(Collectors.toList());
final List flags = checker.flags.stream().flatMap(e -> Arrays.stream(e.alias())).collect(Collectors.toList());
final List options = checker.options.stream().flatMap(e -> Arrays.stream(e.alias())).collect(Collectors.toList());
final List tokens = new ArrayList<>();
tokens.add(command);
tokens.addAll(subCommands);
tokens.addAll(flags);
tokens.addAll(options);
final List args = new ArrayList<>();
boolean lastWasToken = false;
for (final String arg : splitBySpace(in)) {
final int idx = args.size() - 1;
final boolean isToken = tokens.contains(arg);
if (isToken) {
args.add(arg);
} else if (!lastWasToken) {
if (idx > -1) {
args.set(idx, args.get(idx) + " " + arg);
} else {
args.add(arg);
}
} else {
args.add(arg);
}
lastWasToken = isToken;
}
return args;
}
private static List splitBySpace(final String in) {
return Arrays.stream(in.split(" ")).filter(e -> !e.trim().equals("")).collect(Collectors.toList());
}
private static List annotationsWithType(final Class> cls, final Class annotation) {
return Arrays.stream(cls.getDeclaredFields())
.flatMap(e -> Arrays.stream(e.getAnnotationsByType(annotation)))
.collect(Collectors.toList());
}
static class Checker {
Command command;
List subCommands;
List flags;
List