diff options
author | snowleo <schneeleo@gmail.com> | 2011-10-12 03:14:07 +0200 |
---|---|---|
committer | snowleo <schneeleo@gmail.com> | 2011-10-12 03:14:26 +0200 |
commit | 860d446d28776ec842fa53e8e08538d4e093d6e9 (patch) | |
tree | 0c4598eae4eb8c59fd36e8312eab1b27a8018794 /EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java | |
parent | 9ec398b39b0f48392a9d635041b392c7dba2ca0c (diff) | |
download | Essentials-860d446d28776ec842fa53e8e08538d4e093d6e9.tar Essentials-860d446d28776ec842fa53e8e08538d4e093d6e9.tar.gz Essentials-860d446d28776ec842fa53e8e08538d4e093d6e9.tar.lz Essentials-860d446d28776ec842fa53e8e08538d4e093d6e9.tar.xz Essentials-860d446d28776ec842fa53e8e08538d4e093d6e9.zip |
EssentialsUpdate WIP
Diffstat (limited to 'EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java')
-rw-r--r-- | EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java b/EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java new file mode 100644 index 000000000..b3c3e19ef --- /dev/null +++ b/EssentialsUpdate/src/f00f/net/irc/martyr/commands/ModeCommand.java @@ -0,0 +1,237 @@ +package f00f.net.irc.martyr.commands; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import f00f.net.irc.martyr.CommandRegister; +import f00f.net.irc.martyr.InCommand; +import f00f.net.irc.martyr.Mode; +import f00f.net.irc.martyr.OutCommand; +import f00f.net.irc.martyr.State; +import f00f.net.irc.martyr.clientstate.Channel; +import f00f.net.irc.martyr.clientstate.ClientState; +import java.util.logging.Logger; + +/** + * Defines MODE command. Since the MODE command is of two distinct + * types, this class is really more of a command mini-factory. It + * determines which type of command it is, either a UserModeCommand or + * a ChannelModeCommand. + * + */ +public class ModeCommand implements InCommand, OutCommand +{ + static Logger log = Logger.getLogger(ModeCommand.class.getName()); + + public static final String IDENTIFIER = "MODE"; + private String source; + + /** For use as a factory */ + public ModeCommand() + { + } + + public Iterator getAttributeKeys() + { + return new LinkedList().iterator(); + } + + public String getAttribute( String key ) + { + return null; + } + + public static void registerMode( Map<Character,Mode> modes, Mode mode ) + { + Character modeChar = mode.getChar(); + + if( modes.get( modeChar ) != null ) + { + log.severe("ModeCommand: Warning: Two modes with same letter: " + + modes.get( modeChar ) + " and " + mode); + } + + modes.put( modeChar, mode ); + } + + public State getState() + { + return State.REGISTERED; + } + + public void selfRegister( CommandRegister reg ) + { + reg.addCommand( IDENTIFIER, this ); + } + + public String getIrcIdentifier() + { + return IDENTIFIER; + } + + // Example + // <pre>:repp_!bdamm@dammfine.com MODE #bytesex +oo z * repp_telnet</pre> + public InCommand parse( String prefix, String identifier, String params ) + { + // there are two kinds of modes. Either a channel mode, or a user + // mode. We need to figure out which we are dealing with, and + // return that. + + // TODO: Research: Should we specify delimiters other than whitespace? + StringTokenizer tokens = new StringTokenizer( params ); + + String str = tokens.nextToken(); + + //log.debug("ModeCommand: Prefix: " + prefix + " str: " + str + // + " total: " + params); + + // Malformed command. + if( str == null ) + return null; + + // Should we check to see if the string is really a channel + // that we know about? + if( Channel.isChannel( str ) ) + { + return new ChannelModeCommand( prefix, str, tokens ); + } + else + { + return new UserModeCommand( prefix, str, tokens ); + } + } + + /** + * Should not be called, as ModeCommand doesn't actually represent a + * command. Use UserModeCommand or ChannelModeCommand instead. + */ + public String render() + { + throw new IllegalStateException("Don't try to send ModeCommand!"); + } + + public void setSourceString( String source ) + { + this.source = source; + } + + public String getSourceString() + { + return source; + } + + /** + * Does nothing, as this is a factory command. + */ + public boolean updateClientState( ClientState cs ) + { + // Nothing here, move on. + return false; + } + + public String toString() + { + return "ModeCommand"; + } + + /** Takes a mode string, such as: '+ooo A B C' or '+o A +o B' or even + * '+o-o A B' and returns a List containing Mode objects that + * correspond to the modes specified. + * + * @param modes is a Map of Character to Mode objects. + * @param tokens is the sequence of tokens making up the parameters of + * the command. + * @return List of modes + */ + public List<Mode> parseModes( Map<Character,Mode> modes, StringTokenizer tokens ) + { + LinkedList<Mode> results = new LinkedList<Mode>(); + + while( true ) + { + if( tokens.hasMoreTokens() ) + { + parseOneModeSet( modes, tokens, results ); + } + else + { + return results; + } + } + } + + /** + * Parses one group of modes. '+ooo A B C' and not '+o A +o B'. It + * will parse the first group it finds and will ignore the rest. + * + * @param modes Map of character to Mode objects. + * @param tokens Sequence of tokens making up the parameters of the command. + * @param results List of Mode results to be filled in + */ + private void parseOneModeSet( Map<Character,Mode> modes, StringTokenizer tokens, List<Mode> results ) + { + // A list of modes that we have. + LinkedList<Mode> localModes = new LinkedList<Mode>(); + + Mode.Sign sign = Mode.Sign.NOSIGN; + String chars = tokens.nextToken(); + + int stop = chars.length(); + for( int i = 0; i < stop; ++i ) + { + char lookingAt = chars.charAt( i ); + if( lookingAt == '+' ) + sign = Mode.Sign.POSITIVE; + else if( lookingAt == '-' ) + sign = Mode.Sign.NEGATIVE; + else if( lookingAt == ':' ) + // This is to get around a bug in some ircds + continue; + else + { + // A real mode character! + Mode mode = modes.get( lookingAt ); + if( mode == null ) + { + //TODO: Is there some way we can figure out if the mode + // we don't know anything about needs a parameter? + // Things get messy if it does need a parameter, and we + // don't eat the string. + //log.severe("ModeCommand: Unknown mode: " + lookingAt); + } + else + { + mode = mode.newInstance(); + mode.setSign( sign ); + localModes.add( mode ); + } + } + } + + // Now we know what modes are specified, and whether they are + // positive or negative. Now we need to fill in the parameters for + // any that require parameters, and place the results in the result + // list. + for (Mode localMode : localModes) { + /* + * What we do if the server doesn't pass us a parameter + * for a mode is rather undefined - except that we don't + * want to run off the end of the tokens. So we just + * ignore it. The problem is that we don't always know + * when a server is going to send us a parameter or not. + * We can only hope that servers don't send ambiguous + * masks followed by more modes instead of a parameter. + */ + if (localMode != null && localMode.requiresParam() && tokens.hasMoreTokens()) { + localMode.setParam(tokens.nextToken()); + } + + results.add(localMode); + } + } +} + + |