summaryrefslogtreecommitdiff
path: root/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java')
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java554
1 files changed, 278 insertions, 276 deletions
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
index f486f52..7418c4a 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
@@ -1,276 +1,278 @@
-package io.dico.dicore.command.parameter;
-
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.ExecutionContext;
-
-import java.lang.reflect.Array;
-import java.util.*;
-
-public class ContextParser {
- private final ExecutionContext m_context;
- private final ArgumentBuffer m_buffer;
- private final ParameterList m_paramList;
- private final Parameter<?, ?> m_repeatedParam;
- private final List<Parameter<?, ?>> m_indexedParams;
- private final int m_maxIndex;
- private final int m_maxRequiredIndex;
-
- private Map<String, Object> m_valueMap;
- private Set<String> m_parsedKeys;
- private int m_completionCursor = -1;
- private Parameter<?, ?> m_completionTarget = null;
-
- public ContextParser(ExecutionContext context,
- ParameterList parameterList,
- Map<String, Object> valueMap,
- Set<String> keySet) {
- m_context = context;
- m_paramList = parameterList;
- m_valueMap = valueMap;
- m_parsedKeys = keySet;
-
- m_buffer = context.getBuffer();
- m_repeatedParam = m_paramList.getRepeatedParameter();
- m_indexedParams = m_paramList.getIndexedParameters();
- m_maxIndex = m_indexedParams.size() - 1;
- m_maxRequiredIndex = m_paramList.getRequiredCount() - 1;
- }
-
- public ExecutionContext getContext() {
- return m_context;
- }
-
- public Map<String, Object> getValueMap() {
- return m_valueMap;
- }
-
- public Set<String> getParsedKeys() {
- return m_parsedKeys;
- }
-
- public void parse() throws CommandException {
- parseAllParameters();
- }
-
- public int getCompletionCursor() {
- if (!m_done) {
- throw new IllegalStateException();
- }
- return m_completionCursor;
- }
-
- public Parameter<?, ?> getCompletionTarget() {
- if (!m_done) {
- throw new IllegalStateException();
- }
- return m_completionTarget;
- }
-
- // ################################
- // # PARSING METHODS #
- // ################################
-
- private boolean m_repeating = false;
- private boolean m_done = false;
- private int m_curParamIndex = -1;
- private Parameter<?, ?> m_curParam = null;
- private List<Object> m_curRepeatingList = null;
-
- private void parseAllParameters() throws CommandException {
- try {
- do {
- prepareStateToParseParam();
- if (m_done) break;
- parseCurParam();
- } while (!m_done);
-
- } finally {
- m_curParam = null;
- m_curRepeatingList = null;
- assignDefaultValuesToUncomputedParams();
- arrayifyRepeatedParamValue();
- }
- }
-
- private void prepareStateToParseParam() throws CommandException {
-
- boolean requireInput;
- if (identifyFlag()) {
- m_buffer.advance();
- prepareRepeatedParameterIfSet();
- requireInput = false;
-
- } else if (m_repeating) {
- m_curParam = m_repeatedParam;
- requireInput = false;
-
- } else if (m_curParamIndex < m_maxIndex) {
- m_curParamIndex++;
- m_curParam = m_indexedParams.get(m_curParamIndex);
- prepareRepeatedParameterIfSet();
- requireInput = m_curParamIndex <= m_maxRequiredIndex;
-
- } else if (m_buffer.hasNext()) {
- throw new CommandException("Too many arguments for /" + m_context.getAddress().getAddress());
-
- } else {
- m_done = true;
- return;
- }
-
- if (!m_buffer.hasNext()) {
- if (requireInput) {
- reportParameterRequired(m_curParam);
- }
-
- if (m_repeating) {
- m_done = true;
- }
- }
-
- }
-
- private boolean identifyFlag() {
- String potentialFlag = m_buffer.peekNext();
- Parameter<?, ?> target;
- if (potentialFlag != null
- && potentialFlag.startsWith("-")
- && (target = m_paramList.getParameterByName(potentialFlag)) != null
- && target.isFlag()
- && !m_valueMap.containsKey(potentialFlag)
-
-// Disabled because it's checked by {@link Parameter#parse(ExecutionContext, ArgumentBuffer)}
-// && (target.getFlagPermission() == null || m_context.getSender().hasPermission(target.getFlagPermission()))
- ) {
- m_curParam = target;
- return true;
- }
-
- return false;
- }
-
- private void prepareRepeatedParameterIfSet() throws CommandException {
- if (m_curParam != null && m_curParam == m_repeatedParam) {
-
- if (m_curParam.isFlag() && m_curParamIndex < m_maxRequiredIndex) {
- Parameter<?, ?> requiredParam = m_indexedParams.get(m_curParamIndex + 1);
- reportParameterRequired(requiredParam);
- }
-
- m_curRepeatingList = new ArrayList<>();
- assignValue(m_curRepeatingList);
- m_repeating = true;
- }
- }
-
- private void reportParameterRequired(Parameter<?, ?> param) throws CommandException {
- throw new CommandException("The argument '" + param.getName() + "' is required");
- }
-
- private void parseCurParam() throws CommandException {
- if (!m_buffer.hasNext() && !m_curParam.isFlag()) {
- assignDefaultValue();
- return;
- }
-
- int cursorStart = m_buffer.getCursor();
-
- if (m_context.isTabComplete() && "".equals(m_buffer.peekNext())) {
- assignAsCompletionTarget(cursorStart);
- return;
- }
-
- Object parseResult;
- try {
- parseResult = m_curParam.parse(m_context, m_buffer);
- } catch (CommandException e) {
- assignAsCompletionTarget(cursorStart);
- throw e;
- }
-
- assignValue(parseResult);
- m_parsedKeys.add(m_curParam.getName());
- }
-
- private void assignDefaultValue() throws CommandException {
- assignValue(m_curParam.getDefaultValue(m_context, m_buffer));
- }
-
- private void assignAsCompletionTarget(int cursor) {
- m_completionCursor = cursor;
- m_completionTarget = m_curParam;
- m_done = true;
- }
-
- private void assignValue(Object value) {
- if (m_repeating) {
- m_curRepeatingList.add(value);
- } else {
- m_valueMap.put(m_curParam.getName(), value);
- }
- }
-
- private void assignDefaultValuesToUncomputedParams() throws CommandException {
- // add default values for unset parameters
- for (Map.Entry<String, Parameter<?, ?>> entry : m_paramList.getParametersByName().entrySet()) {
- String name = entry.getKey();
- if (!m_valueMap.containsKey(name)) {
- if (m_repeatedParam == entry.getValue()) {
- // below value will be turned into an array later
- m_valueMap.put(name, Collections.emptyList());
- } else {
- m_valueMap.put(name, entry.getValue().getDefaultValue(m_context, m_buffer));
- }
- }
- }
- }
-
- private void arrayifyRepeatedParamValue() {
- if (m_repeatedParam != null) {
- m_valueMap.computeIfPresent(m_repeatedParam.getName(), (k, v) -> {
- List list = (List) v;
- Class<?> returnType = m_repeatedParam.getType().getReturnType();
- Object array = Array.newInstance(returnType, list.size());
- ArraySetter setter = ArraySetter.getSetter(returnType);
- for (int i = 0, n = list.size(); i < n; i++) {
- setter.set(array, i, list.get(i));
- }
-
- return array;
- });
- }
- }
-
- private interface ArraySetter {
- void set(Object array, int index, Object value);
-
- static ArraySetter getSetter(Class<?> clazz) {
- if (!clazz.isPrimitive()) {
- return (array, index, value) -> ((Object[]) array)[index] = value;
- }
-
- switch (clazz.getSimpleName()) {
- case "boolean":
- return (array, index, value) -> ((boolean[]) array)[index] = (boolean) value;
- case "int":
- return (array, index, value) -> ((int[]) array)[index] = (int) value;
- case "double":
- return (array, index, value) -> ((double[]) array)[index] = (double) value;
- case "long":
- return (array, index, value) -> ((long[]) array)[index] = (long) value;
- case "short":
- return (array, index, value) -> ((short[]) array)[index] = (short) value;
- case "byte":
- return (array, index, value) -> ((byte[]) array)[index] = (byte) value;
- case "float":
- return (array, index, value) -> ((float[]) array)[index] = (float) value;
- case "char":
- return (array, index, value) -> ((char[]) array)[index] = (char) value;
- case "void":
- default:
- throw new InternalError("This should not happen");
- }
- }
- }
-
-}
+package io.dico.dicore.command.parameter;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.ExecutionContext;
+
+import java.lang.reflect.Array;
+import java.util.*;
+
+public class ContextParser {
+ private final ExecutionContext m_context;
+ private final ArgumentBuffer m_buffer;
+ private final ParameterList m_paramList;
+ private final Parameter<?, ?> m_repeatedParam;
+ private final List<Parameter<?, ?>> m_indexedParams;
+ private final int m_maxIndex;
+ private final int m_maxRequiredIndex;
+
+ private Map<String, Object> m_valueMap;
+ private Set<String> m_parsedKeys;
+ private int m_completionCursor = -1;
+ private Parameter<?, ?> m_completionTarget = null;
+
+ public ContextParser(ExecutionContext context,
+ ParameterList parameterList,
+ Map<String, Object> valueMap,
+ Set<String> keySet) {
+ m_context = context;
+ m_paramList = parameterList;
+ m_valueMap = valueMap;
+ m_parsedKeys = keySet;
+
+ m_buffer = context.getBuffer();
+ m_repeatedParam = m_paramList.getRepeatedParameter();
+ m_indexedParams = m_paramList.getIndexedParameters();
+ m_maxIndex = m_indexedParams.size() - 1;
+ m_maxRequiredIndex = m_paramList.getRequiredCount() - 1;
+ }
+
+ public ExecutionContext getContext() {
+ return m_context;
+ }
+
+ public Map<String, Object> getValueMap() {
+ return m_valueMap;
+ }
+
+ public Set<String> getParsedKeys() {
+ return m_parsedKeys;
+ }
+
+ public void parse() throws CommandException {
+ parseAllParameters();
+ }
+
+ public int getCompletionCursor() {
+ if (!m_done) {
+ throw new IllegalStateException();
+ }
+ return m_completionCursor;
+ }
+
+ public Parameter<?, ?> getCompletionTarget() {
+ if (!m_done) {
+ throw new IllegalStateException();
+ }
+ return m_completionTarget;
+ }
+
+ // ################################
+ // # PARSING METHODS #
+ // ################################
+
+ private boolean m_repeating = false;
+ private boolean m_done = false;
+ private int m_curParamIndex = -1;
+ private Parameter<?, ?> m_curParam = null;
+ private List<Object> m_curRepeatingList = null;
+
+ private void parseAllParameters() throws CommandException {
+ try {
+ do {
+ prepareStateToParseParam();
+ if (m_done) break;
+ parseCurParam();
+ } while (!m_done);
+
+ } finally {
+ m_curParam = null;
+ m_curRepeatingList = null;
+ assignDefaultValuesToUncomputedParams();
+ arrayifyRepeatedParamValue();
+
+ m_done = true;
+ }
+ }
+
+ private void prepareStateToParseParam() throws CommandException {
+
+ boolean requireInput;
+ if (identifyFlag()) {
+ m_buffer.advance();
+ prepareRepeatedParameterIfSet();
+ requireInput = false;
+
+ } else if (m_repeating) {
+ m_curParam = m_repeatedParam;
+ requireInput = false;
+
+ } else if (m_curParamIndex < m_maxIndex) {
+ m_curParamIndex++;
+ m_curParam = m_indexedParams.get(m_curParamIndex);
+ prepareRepeatedParameterIfSet();
+ requireInput = m_curParamIndex <= m_maxRequiredIndex;
+
+ } else if (m_buffer.hasNext()) {
+ throw new CommandException("Too many arguments for /" + m_context.getAddress().getAddress());
+
+ } else {
+ m_done = true;
+ return;
+ }
+
+ if (!m_buffer.hasNext()) {
+ if (requireInput) {
+ reportParameterRequired(m_curParam);
+ }
+
+ if (m_repeating) {
+ m_done = true;
+ }
+ }
+
+ }
+
+ private boolean identifyFlag() {
+ String potentialFlag = m_buffer.peekNext();
+ Parameter<?, ?> target;
+ if (potentialFlag != null
+ && potentialFlag.startsWith("-")
+ && (target = m_paramList.getParameterByName(potentialFlag)) != null
+ && target.isFlag()
+ && !m_valueMap.containsKey(potentialFlag)
+
+// Disabled because it's checked by {@link Parameter#parse(ExecutionContext, ArgumentBuffer)}
+// && (target.getFlagPermission() == null || m_context.getSender().hasPermission(target.getFlagPermission()))
+ ) {
+ m_curParam = target;
+ return true;
+ }
+
+ return false;
+ }
+
+ private void prepareRepeatedParameterIfSet() throws CommandException {
+ if (m_curParam != null && m_curParam == m_repeatedParam) {
+
+ if (m_curParam.isFlag() && m_curParamIndex < m_maxRequiredIndex) {
+ Parameter<?, ?> requiredParam = m_indexedParams.get(m_curParamIndex + 1);
+ reportParameterRequired(requiredParam);
+ }
+
+ m_curRepeatingList = new ArrayList<>();
+ assignValue(m_curRepeatingList);
+ m_repeating = true;
+ }
+ }
+
+ private void reportParameterRequired(Parameter<?, ?> param) throws CommandException {
+ throw new CommandException("The argument '" + param.getName() + "' is required");
+ }
+
+ private void parseCurParam() throws CommandException {
+ if (!m_buffer.hasNext() && !m_curParam.isFlag()) {
+ assignDefaultValue();
+ return;
+ }
+
+ int cursorStart = m_buffer.getCursor();
+
+ if (m_context.isTabComplete() && "".equals(m_buffer.peekNext())) {
+ assignAsCompletionTarget(cursorStart);
+ return;
+ }
+
+ Object parseResult;
+ try {
+ parseResult = m_curParam.parse(m_context, m_buffer);
+ } catch (CommandException e) {
+ assignAsCompletionTarget(cursorStart);
+ throw e;
+ }
+
+ assignValue(parseResult);
+ m_parsedKeys.add(m_curParam.getName());
+ }
+
+ private void assignDefaultValue() throws CommandException {
+ assignValue(m_curParam.getDefaultValue(m_context, m_buffer));
+ }
+
+ private void assignAsCompletionTarget(int cursor) {
+ m_completionCursor = cursor;
+ m_completionTarget = m_curParam;
+ m_done = true;
+ }
+
+ private void assignValue(Object value) {
+ if (m_repeating) {
+ m_curRepeatingList.add(value);
+ } else {
+ m_valueMap.put(m_curParam.getName(), value);
+ }
+ }
+
+ private void assignDefaultValuesToUncomputedParams() throws CommandException {
+ // add default values for unset parameters
+ for (Map.Entry<String, Parameter<?, ?>> entry : m_paramList.getParametersByName().entrySet()) {
+ String name = entry.getKey();
+ if (!m_valueMap.containsKey(name)) {
+ if (m_repeatedParam == entry.getValue()) {
+ // below value will be turned into an array later
+ m_valueMap.put(name, Collections.emptyList());
+ } else {
+ m_valueMap.put(name, entry.getValue().getDefaultValue(m_context, m_buffer));
+ }
+ }
+ }
+ }
+
+ private void arrayifyRepeatedParamValue() {
+ if (m_repeatedParam != null) {
+ m_valueMap.computeIfPresent(m_repeatedParam.getName(), (k, v) -> {
+ List list = (List) v;
+ Class<?> returnType = m_repeatedParam.getType().getReturnType();
+ Object array = Array.newInstance(returnType, list.size());
+ ArraySetter setter = ArraySetter.getSetter(returnType);
+ for (int i = 0, n = list.size(); i < n; i++) {
+ setter.set(array, i, list.get(i));
+ }
+
+ return array;
+ });
+ }
+ }
+
+ private interface ArraySetter {
+ void set(Object array, int index, Object value);
+
+ static ArraySetter getSetter(Class<?> clazz) {
+ if (!clazz.isPrimitive()) {
+ return (array, index, value) -> ((Object[]) array)[index] = value;
+ }
+
+ switch (clazz.getSimpleName()) {
+ case "boolean":
+ return (array, index, value) -> ((boolean[]) array)[index] = (boolean) value;
+ case "int":
+ return (array, index, value) -> ((int[]) array)[index] = (int) value;
+ case "double":
+ return (array, index, value) -> ((double[]) array)[index] = (double) value;
+ case "long":
+ return (array, index, value) -> ((long[]) array)[index] = (long) value;
+ case "short":
+ return (array, index, value) -> ((short[]) array)[index] = (short) value;
+ case "byte":
+ return (array, index, value) -> ((byte[]) array)[index] = (byte) value;
+ case "float":
+ return (array, index, value) -> ((float[]) array)[index] = (float) value;
+ case "char":
+ return (array, index, value) -> ((char[]) array)[index] = (char) value;
+ case "void":
+ default:
+ throw new InternalError("This should not happen");
+ }
+ }
+ }
+
+}