372 lines
16 KiB
Java
372 lines
16 KiB
Java
package com.zwitserloot.cmdreader;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.ParameterizedType;
|
|
import java.lang.reflect.Type;
|
|
import java.util.AbstractCollection;
|
|
import java.util.AbstractList;
|
|
import java.util.AbstractSequentialList;
|
|
import java.util.AbstractSet;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Queue;
|
|
import java.util.Set;
|
|
/* loaded from: com.discord-120111.apk:com/zwitserloot/cmdreader/ParseItem.SCL.lombok */
|
|
class ParseItem {
|
|
private final Field field;
|
|
private final boolean isCollection;
|
|
private final Class<?> type;
|
|
private final String fullName;
|
|
private final boolean isSeq;
|
|
private final boolean isParameterized;
|
|
private final boolean isMandatory;
|
|
private final String shorthand;
|
|
private final String description;
|
|
private final List<String> excludes;
|
|
private final List<String> mandatoryIf;
|
|
private final List<String> mandatoryIfNot;
|
|
private final List<String> requires;
|
|
private static final List<Class<?>> ARRAY_LIST_COMPATIBLES = Collections.unmodifiableList(Arrays.asList(Collection.class, AbstractCollection.class, List.class, AbstractList.class, ArrayList.class));
|
|
private static final List<Class<?>> HASH_SET_COMPATIBLES = Collections.unmodifiableList(Arrays.asList(Set.class, AbstractSet.class, HashSet.class));
|
|
private static final List<Class<?>> LINKED_LIST_COMPATIBLES = Collections.unmodifiableList(Arrays.asList(AbstractSequentialList.class, Queue.class, LinkedList.class));
|
|
private final List<Class<?>> LEGAL_CLASSES = Collections.unmodifiableList(Arrays.asList(Integer.class, Long.class, Short.class, Byte.class, Float.class, Double.class, Boolean.class, Character.class, String.class, Enum.class));
|
|
private List<String> TRUE_VALS = Collections.unmodifiableList(Arrays.asList("1", "true", "t", "y", "yes", "on"));
|
|
private List<String> FALSE_VALS = Collections.unmodifiableList(Arrays.asList("0", "false", "f", "n", "no", "off"));
|
|
|
|
ParseItem(Field field) {
|
|
Class<?> cls;
|
|
this.field = field;
|
|
field.setAccessible(true);
|
|
if (Collection.class.isAssignableFrom(field.getType())) {
|
|
this.isCollection = true;
|
|
Type genericType = field.getGenericType();
|
|
Type[] actualTypeArguments = genericType instanceof ParameterizedType ? ((ParameterizedType) genericType).getActualTypeArguments() : null;
|
|
if (actualTypeArguments == null || actualTypeArguments.length != 1 || !(actualTypeArguments[0] instanceof Class)) {
|
|
throw new IllegalArgumentException(String.format("Only primitives, Strings, Enums, and Collections of those are allowed (for type: %s)", field.getGenericType()));
|
|
}
|
|
cls = (Class) actualTypeArguments[0];
|
|
} else {
|
|
this.isCollection = false;
|
|
cls = field.getType();
|
|
}
|
|
if (cls == Integer.TYPE) {
|
|
this.type = Integer.class;
|
|
} else if (cls == Long.TYPE) {
|
|
this.type = Long.class;
|
|
} else if (cls == Short.TYPE) {
|
|
this.type = Short.class;
|
|
} else if (cls == Byte.TYPE) {
|
|
this.type = Byte.class;
|
|
} else if (cls == Double.TYPE) {
|
|
this.type = Double.class;
|
|
} else if (cls == Float.TYPE) {
|
|
this.type = Float.class;
|
|
} else if (cls == Character.TYPE) {
|
|
this.type = Character.class;
|
|
} else if (cls == Boolean.TYPE) {
|
|
this.type = Boolean.class;
|
|
} else {
|
|
this.type = cls;
|
|
}
|
|
if (!this.LEGAL_CLASSES.contains(this.type)) {
|
|
throw new IllegalArgumentException("Not a valid class for command line parsing: " + field.getGenericType());
|
|
}
|
|
this.fullName = setupFullName(field);
|
|
this.isSeq = field.getAnnotation(Sequential.class) != null;
|
|
this.isParameterized = (field.getType() == Boolean.TYPE || field.getType() == Boolean.class) ? false : true;
|
|
this.shorthand = setupShorthand(field);
|
|
this.description = setupDescription(field);
|
|
this.isMandatory = setupMandatory(field);
|
|
this.mandatoryIf = setupMandatoryIf(field);
|
|
this.mandatoryIfNot = setupMandatoryIfNot(field);
|
|
this.requires = setupRequires(field);
|
|
this.excludes = setupExcludes(field);
|
|
try {
|
|
sanityChecks();
|
|
} catch (IllegalArgumentException e) {
|
|
throw new IllegalArgumentException(String.format("%s (at %s)", e.getMessage(), this.fullName));
|
|
}
|
|
}
|
|
|
|
private void sanityChecks() {
|
|
if (!this.isParameterized && Boolean.class != this.type) {
|
|
throw new IllegalArgumentException("Non-parameterized parameters must have type boolean. - it's there (true), or not (false).");
|
|
} else if (!this.isParameterized && this.isMandatory) {
|
|
throw new IllegalArgumentException("Non-parameterized parameters must not be mandatory - what's the point of having it?");
|
|
} else if (this.isSeq && !"".equals(this.shorthand)) {
|
|
throw new IllegalArgumentException("sequential parameters must not have any shorthands.");
|
|
} else if (this.isSeq && !this.isParameterized) {
|
|
throw new IllegalArgumentException("sequential parameters must always be parameterized.");
|
|
}
|
|
}
|
|
|
|
static void multiSanityChecks(List<ParseItem> list) {
|
|
int size = list.size();
|
|
for (int i = 0; i < size; i++) {
|
|
for (int i2 = i + 1; i2 < size; i2++) {
|
|
if (list.get(i).fullName.equalsIgnoreCase(list.get(i2).fullName)) {
|
|
throw new IllegalArgumentException(String.format("Duplicate full names for fields %s and %s.", list.get(i).field.getName(), list.get(i2).field.getName()));
|
|
}
|
|
}
|
|
}
|
|
ParseItem parseItem = null;
|
|
for (ParseItem parseItem2 : list) {
|
|
if (parseItem2.isSeq && parseItem != null) {
|
|
throw new IllegalArgumentException(String.format("After the sequential, collection item %s no more sequential items allowed (at %s)", parseItem.fullName, parseItem2.fullName));
|
|
} else if (parseItem2.isSeq && parseItem2.isCollection) {
|
|
parseItem = parseItem2;
|
|
}
|
|
}
|
|
ParseItem parseItem3 = null;
|
|
for (ParseItem parseItem4 : list) {
|
|
if (parseItem4.isSeq) {
|
|
if (parseItem3 == null && !parseItem4.isMandatory) {
|
|
parseItem3 = parseItem4;
|
|
}
|
|
if (parseItem4.isMandatory && parseItem3 != null) {
|
|
throw new IllegalArgumentException(String.format("Sequential item %s is non-mandatory, so %s which is a later sequential item must also be non-mandatory", parseItem3.fullName, parseItem4.fullName));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static Map<Character, ParseItem> makeShortHandMap(List<ParseItem> list) {
|
|
char[] charArray;
|
|
HashMap hashMap = new HashMap();
|
|
for (ParseItem parseItem : list) {
|
|
for (char c : parseItem.shorthand.toCharArray()) {
|
|
if (hashMap.containsKey(Character.valueOf(c))) {
|
|
throw new IllegalArgumentException(String.format("Both %s and %s contain the shorthand %s", ((ParseItem) hashMap.get(Character.valueOf(c))).fullName, parseItem.fullName, Character.valueOf(c)));
|
|
}
|
|
hashMap.put(Character.valueOf(c), parseItem);
|
|
}
|
|
}
|
|
return hashMap;
|
|
}
|
|
|
|
String getFullName() {
|
|
return this.fullName;
|
|
}
|
|
|
|
boolean isSeq() {
|
|
return this.isSeq;
|
|
}
|
|
|
|
boolean isMandatory() {
|
|
return this.isMandatory;
|
|
}
|
|
|
|
List<String> getMandatoryIf() {
|
|
return this.mandatoryIf;
|
|
}
|
|
|
|
List<String> getMandatoryIfNot() {
|
|
return this.mandatoryIfNot;
|
|
}
|
|
|
|
List<String> getRequires() {
|
|
return this.requires;
|
|
}
|
|
|
|
List<String> getExcludes() {
|
|
return this.excludes;
|
|
}
|
|
|
|
boolean isParameterized() {
|
|
return this.isParameterized;
|
|
}
|
|
|
|
boolean isCollection() {
|
|
return this.isCollection;
|
|
}
|
|
|
|
String getFullDescription() {
|
|
return this.description;
|
|
}
|
|
|
|
void set(Object obj, String str) {
|
|
Object stringToObject = stringToObject(str);
|
|
try {
|
|
if (this.isCollection) {
|
|
Collection collection = (Collection) this.field.get(obj);
|
|
if (collection == null) {
|
|
if (ARRAY_LIST_COMPATIBLES.contains(this.field.getType())) {
|
|
collection = new ArrayList();
|
|
} else if (LINKED_LIST_COMPATIBLES.contains(this.field.getType())) {
|
|
collection = new LinkedList();
|
|
} else if (HASH_SET_COMPATIBLES.contains(this.field.getType())) {
|
|
collection = new HashSet();
|
|
} else {
|
|
throw new IllegalArgumentException("Cannot construct a collection of type " + this.field.getType() + " -- try List, Set, Collection, or Queue.");
|
|
}
|
|
this.field.set(obj, collection);
|
|
}
|
|
collection.add(stringToObject);
|
|
} else {
|
|
this.field.set(obj, stringToObject);
|
|
}
|
|
} catch (IllegalAccessException e) {
|
|
throw new IllegalArgumentException("Huh?");
|
|
}
|
|
}
|
|
|
|
private Object stringToObject(String str) {
|
|
if (String.class == this.type) {
|
|
return str;
|
|
}
|
|
if (Integer.class == this.type) {
|
|
return Integer.valueOf(Integer.parseInt(str));
|
|
}
|
|
if (Long.class == this.type) {
|
|
return Long.valueOf(Long.parseLong(str));
|
|
}
|
|
if (Short.class == this.type) {
|
|
return Short.valueOf(Short.parseShort(str));
|
|
}
|
|
if (Byte.class == this.type) {
|
|
return Byte.valueOf(Byte.parseByte(str));
|
|
}
|
|
if (Float.class == this.type) {
|
|
return Float.valueOf(Float.parseFloat(str));
|
|
}
|
|
if (Double.class == this.type) {
|
|
return Double.valueOf(Double.parseDouble(str));
|
|
}
|
|
if (Boolean.class == this.type) {
|
|
return Boolean.valueOf(str == null ? true : parseBoolean(str));
|
|
} else if (Character.class == this.type) {
|
|
return Character.valueOf(str.length() == 0 ? (char) 0 : str.charAt(0));
|
|
} else if (Enum.class == this.type) {
|
|
return Enum.valueOf(this.type, str);
|
|
} else {
|
|
throw new IllegalArgumentException("Huh?");
|
|
}
|
|
}
|
|
|
|
private String setupFullName(Field field) {
|
|
FullName fullName = (FullName) field.getAnnotation(FullName.class);
|
|
if (fullName == null) {
|
|
return field.getName();
|
|
}
|
|
if (!fullName.value().trim().equals("")) {
|
|
return fullName.value();
|
|
}
|
|
throw new IllegalArgumentException("Missing name for field: " + field.getName());
|
|
}
|
|
|
|
private String setupShorthand(Field field) {
|
|
Shorthand shorthand = (Shorthand) field.getAnnotation(Shorthand.class);
|
|
if (shorthand == null) {
|
|
return "";
|
|
}
|
|
String[] value = shorthand.value();
|
|
StringBuilder sb = new StringBuilder();
|
|
for (String str : value) {
|
|
char[] charArray = str.toCharArray();
|
|
if (charArray.length != 1) {
|
|
throw new IllegalArgumentException(String.format("Shorthands must be strings of 1 character long. (%s at %s)", str, this.fullName));
|
|
} else if (charArray[0] == '-') {
|
|
throw new IllegalArgumentException(String.format("The dash (-) is not a legal shorthand character. (at %s)", this.fullName));
|
|
} else if (sb.indexOf(str) > -1) {
|
|
throw new IllegalArgumentException(String.format("Duplicate shorthand: %s (at %s)", str, this.fullName));
|
|
} else {
|
|
sb.append(str);
|
|
}
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private String setupDescription(Field field) {
|
|
Enum[] enumArr;
|
|
StringBuilder sb = new StringBuilder();
|
|
Description description = (Description) field.getAnnotation(Description.class);
|
|
if (description != null) {
|
|
sb.append(description.value());
|
|
}
|
|
if (this.isCollection) {
|
|
sb.append(sb.length() > 0 ? " " : "").append("This option may be used multiple times.");
|
|
}
|
|
if (this.isParameterized && this.type != String.class) {
|
|
if (sb.length() > 0) {
|
|
sb.append(" ");
|
|
}
|
|
if (this.type == Float.class || this.type == Double.class) {
|
|
sb.append("value is a floating point number.");
|
|
}
|
|
if (this.type == Integer.class || this.type == Long.class || this.type == Short.class || this.type == Byte.class) {
|
|
sb.append("value is an integer.");
|
|
}
|
|
if (this.type == Boolean.class) {
|
|
sb.append("value is 'true' or 'false'.");
|
|
}
|
|
if (this.type == Character.class) {
|
|
sb.append("Value is a single character.");
|
|
}
|
|
if (this.type == Enum.class) {
|
|
sb.append("value is one of: ");
|
|
boolean z2 = true;
|
|
for (Enum r0 : (Enum[]) this.type.getEnumConstants()) {
|
|
if (z2) {
|
|
z2 = false;
|
|
} else {
|
|
sb.append(", ");
|
|
}
|
|
sb.append(r0.name());
|
|
}
|
|
sb.append(".");
|
|
}
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private boolean setupMandatory(Field field) {
|
|
Mandatory mandatory = (Mandatory) field.getAnnotation(Mandatory.class);
|
|
return mandatory != null && mandatory.onlyIf().length == 0 && mandatory.onlyIfNot().length == 0;
|
|
}
|
|
|
|
private List<String> setupMandatoryIf(Field field) {
|
|
Mandatory mandatory = (Mandatory) field.getAnnotation(Mandatory.class);
|
|
return (mandatory == null || mandatory.onlyIf().length == 0) ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(mandatory.onlyIf()));
|
|
}
|
|
|
|
private List<String> setupMandatoryIfNot(Field field) {
|
|
Mandatory mandatory = (Mandatory) field.getAnnotation(Mandatory.class);
|
|
return (mandatory == null || mandatory.onlyIfNot().length == 0) ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(mandatory.onlyIfNot()));
|
|
}
|
|
|
|
private List<String> setupRequires(Field field) {
|
|
Requires requires = (Requires) this.field.getAnnotation(Requires.class);
|
|
return (requires == null || requires.value().length == 0) ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(requires.value()));
|
|
}
|
|
|
|
private List<String> setupExcludes(Field field) {
|
|
Excludes excludes = (Excludes) field.getAnnotation(Excludes.class);
|
|
return (excludes == null || excludes.value().length == 0) ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(excludes.value()));
|
|
}
|
|
|
|
private boolean parseBoolean(String str) {
|
|
for (String str2 : this.TRUE_VALS) {
|
|
if (str2.equalsIgnoreCase(str)) {
|
|
return true;
|
|
}
|
|
}
|
|
for (String str3 : this.FALSE_VALS) {
|
|
if (str3.equalsIgnoreCase(str)) {
|
|
return false;
|
|
}
|
|
}
|
|
throw new IllegalArgumentException("Not a boolean: " + str);
|
|
}
|
|
|
|
String getShorthand() {
|
|
return this.shorthand;
|
|
}
|
|
}
|