001package fr.aumgn.bukkitutils.command.args; 002 003import java.util.ArrayList; 004import java.util.HashMap; 005import java.util.HashSet; 006import java.util.Map; 007import java.util.Map.Entry; 008import java.util.Set; 009 010import fr.aumgn.bukkitutils.command.CommandsMessages; 011import fr.aumgn.bukkitutils.command.exception.CommandUsageError; 012 013public class CommandArgsParser { 014 015 private CommandsMessages messages; 016 private String[] args; 017 private Set<Character> flags; 018 private Map<Character, String> argsFlags; 019 020 public CommandArgsParser(CommandsMessages messages, String[] tokens) { 021 this.messages = messages; 022 parse(tokens); 023 } 024 025 private void parse(String[] tokens) { 026 flags = new HashSet<Character>(); 027 argsFlags = new HashMap<Character, String>(); 028 ArrayList<String> argsList = new ArrayList<String>(); 029 boolean quoted = false; 030 StringBuilder current = null; 031 032 for (String token : tokens) { 033 034 if (quoted) { 035 if (!token.isEmpty() 036 && token.charAt(token.length() - 1) == '\"') { 037 current.append(" "); 038 current.append(token.substring(0, token.length() - 1)); 039 argsList.add(current.toString()); 040 quoted = false; 041 } else { 042 current.append(" "); 043 current.append(token); 044 } 045 } else { 046 if (token.isEmpty()) { 047 continue; 048 } 049 050 if (token.charAt(0) == '"') { 051 if (token.charAt(token.length() - 1) == '\"') { 052 argsList.add(token.substring(1, token.length() - 1)); 053 } else { 054 quoted = true; 055 current = new StringBuilder(); 056 current.append(token.substring(1)); 057 } 058 } else if (token.charAt(0) == '-' && token.length() > 1 059 && Character.isLetter(token.charAt(1))) { 060 parseFlags(token.substring(1)); 061 } else { 062 argsList.add(token); 063 } 064 } 065 } 066 067 if (quoted) { 068 throw new CommandUsageError( 069 messages.missingEndingQuote(current.toString())); 070 } 071 072 args = argsList.toArray(new String[argsList.size()]); 073 } 074 075 private void parseFlags(String flagsString) { 076 int equal = flagsString.indexOf("="); 077 if (equal == -1) { 078 parseRegularFlags(flagsString); 079 return; 080 } 081 082 if (equal > 1) { 083 parseRegularFlags(flagsString.substring(0, equal -1)); 084 } 085 086 argsFlags.put( 087 flagsString.charAt(equal - 1), 088 flagsString.substring(equal + 1)); 089 } 090 091 private void parseRegularFlags(String flagsString) { 092 for (char flag : flagsString.toCharArray()) { 093 flags.add(flag); 094 } 095 } 096 097 public void validate(Set<Character> allowedFlags, 098 Set<Character> allowedArgsFlags, int min, int max) { 099 StringBuilder invalidFlags = new StringBuilder(); 100 for (char flag : flags) { 101 if (!allowedFlags.contains(flag)) { 102 invalidFlags.append(flag); 103 } 104 } 105 106 for (char flag : argsFlags.keySet()) { 107 if (!allowedArgsFlags.contains(flag)) { 108 invalidFlags.append(flag); 109 } 110 } 111 112 if (invalidFlags.length() > 0) { 113 throw new CommandUsageError( 114 messages.invalidFlag(invalidFlags.toString())); 115 } 116 117 if (args.length < min) { 118 throw new CommandUsageError( 119 messages.missingArguments(args.length, min)); 120 } 121 if (max != -1 && args.length > max) { 122 throw new CommandUsageError( 123 messages.tooManyArguments(args.length, max)); 124 } 125 } 126 127 public Set<Character> getFlags() { 128 return flags; 129 } 130 131 public Map<Character, String> getArgsFlags() { 132 return argsFlags; 133 } 134 135 public String[] getArgs() { 136 return args; 137 } 138 139 public String[] linearize() { 140 int length = args.length + flags.size() + argsFlags.size(); 141 String[] linearized = new String[length]; 142 System.arraycopy(args, 0, linearized, 0, args.length); 143 int i = args.length; 144 for (char flag : flags) { 145 linearized[i] = "-" + flag; 146 i++; 147 } 148 for (Entry<Character, String> argFlag : argsFlags.entrySet()) { 149 linearized[i] = "-" + argFlag.getKey() + "=" + argFlag.getValue(); 150 i++; 151 } 152 153 return linearized; 154 } 155}