001/************************* PROJECT RON *************************/ 002/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved. */ 003/* Use of this source code is governed by an MIT-style license */ 004/* that can be found in the repository LICENSE file. */ 005/***************************************************************/ 006package tools.ToolClasses; 007 008import java.util.ArrayList; 009import java.util.List; 010 011public abstract class VarArgumentedTool<V> { 012 private final Class<?> argumentType; 013 private final String description; 014 015 @SuppressWarnings("unchecked") 016 private List<V> parseArguments(String rawArgs) { 017 String[] argStrings = rawArgs.split(" (?=(?:[^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); // split by spaces if not within single or double quotes 018 List<V> arguments = new ArrayList<V>(); 019 for (int i = 0; i < argStrings.length; i++) { 020 argStrings[i] = argStrings[i].replaceAll("^\"|\"$|^'|'$", ""); // remove surrounding quotes 021 if (this.argumentType == String.class) { 022 arguments.add(((V) argStrings[i])); 023 continue; 024 } 025 026 switch (this.argumentType.getSimpleName()) { 027 case "Integer", "int" -> { 028 try { 029 arguments.add((V) Integer.valueOf(argStrings[i])); 030 } catch (Exception e) { 031 System.err.println("Failed to parse argument " + argStrings[i] + " into an integer. Skipping."); 032 } 033 } 034 case "Double", "double" -> { 035 try { 036 arguments.add((V) Double.valueOf(argStrings[i])); 037 } catch (Exception e) { 038 System.err.println("Failed to parse argument " + argStrings[i] + " into a double. Skipping."); 039 } 040 } 041 case "Boolean", "boolean" -> { 042 if (argStrings[i].equalsIgnoreCase("true") || argStrings[i].equalsIgnoreCase("false")) { 043 arguments.add((V) Boolean.valueOf(argStrings[i])); 044 } else { 045 System.err.println("Failed to parse argument " + argStrings[i] + " into a boolean. Skipping."); 046 } 047 } 048 default -> { 049 if (this.argumentType.isEnum()) { 050 try { 051 String enumName = (String) argStrings[i]; 052 Enum<?> match = null; 053 for (Enum<?> c : (Enum<?>[]) this.argumentType.getEnumConstants()) { 054 if (c.name().equalsIgnoreCase(enumName)) { 055 match = c; 056 break; 057 } 058 } 059 060 if (match == null) { 061 throw new IllegalArgumentException(); // to be caught by catch block 062 } 063 arguments.add((V) match); 064 } catch (Exception e) { 065 System.err.println("Failed to parse argument " + argStrings[i] + " into an enum of type " + this.argumentType.getSimpleName() + ". Skipping."); 066 } 067 } else { 068 System.err.println("Unsupported argument type: " + this.argumentType.getSimpleName()); 069 } 070 } 071 } 072 } 073 074 return arguments; 075 } 076 077 protected VarArgumentedTool(Class<?> argumentType, String description) { 078 this.argumentType = argumentType; 079 this.description = description; 080 } 081 082 protected abstract void execute(List<V> arguments); 083 084 public final void run(String rawArgs) { 085 List<V> arguments = parseArguments(rawArgs); 086 execute(arguments); 087 } 088}