193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair/*
278795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair * Copyright 20078 the original author or authors.
393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair *
493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * Licensed under the Apache License, Version 2.0 (the "License");
593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * you may not use this file except in compliance with the License.
693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * You may obtain a copy of the License at
793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair *
893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair *      http://www.apache.org/licenses/LICENSE-2.0
993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair *
1093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * Unless required by applicable law or agreed to in writing, software
1193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * distributed under the License is distributed on an "AS IS" BASIS,
1293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * See the License for the specific language governing permissions and
1493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * limitations under the License.
1593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair */
1693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismairpackage org.mockftpserver.core.command;
1793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
1847fb67a4e600f339064de4c08f10279accc95e92chrismairimport org.mockftpserver.core.CommandSyntaxException;
1947fb67a4e600f339064de4c08f10279accc95e92chrismairimport org.mockftpserver.core.util.Assert;
2047fb67a4e600f339064de4c08f10279accc95e92chrismair
2193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismairimport java.util.Arrays;
2278795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismairimport java.util.List;
2393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
2493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair/**
2593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * Represents a command received from an FTP client, containing a command name and parameters.
2693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * Objects of this class are immutable.
2747fb67a4e600f339064de4c08f10279accc95e92chrismair *
2893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair * @author Chris Mair
2947fb67a4e600f339064de4c08f10279accc95e92chrismair * @version $Revision$ - $Date$
3093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair */
3193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismairpublic final class Command {
3293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
3393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    private String name;
3493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    private String[] parameters;
3547fb67a4e600f339064de4c08f10279accc95e92chrismair
3693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
3793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Construct a new immutable instance with the specified command name and parameters
3847fb67a4e600f339064de4c08f10279accc95e92chrismair     *
3947fb67a4e600f339064de4c08f10279accc95e92chrismair     * @param name       - the command name; may not be null
4078795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair     * @param parameters - the command parameters; may be empty; may not be null
4193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
4293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public Command(String name, String[] parameters) {
4393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        Assert.notNull(name, "name");
4493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        Assert.notNull(parameters, "parameters");
4593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        this.name = name;
4693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        this.parameters = copy(parameters);
4793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
4893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
4993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
5078795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair     * Construct a new immutable instance with the specified command name and parameters
5147fb67a4e600f339064de4c08f10279accc95e92chrismair     *
5247fb67a4e600f339064de4c08f10279accc95e92chrismair     * @param name       - the command name; may not be null
5378795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair     * @param parameters - the command parameters; may be empty; may not be null
5478795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair     */
5578795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair    public Command(String name, List parameters) {
5678795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair        this(name, (String[]) parameters.toArray(new String[parameters.size()]));
5778795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair    }
5847fb67a4e600f339064de4c08f10279accc95e92chrismair
5978795c9e5e3c55fc294f011bcc129b7aab0f49b7chrismair    /**
6093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return the name
6193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
6293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public String getName() {
6393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return name;
6493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
6547fb67a4e600f339064de4c08f10279accc95e92chrismair
6693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
6793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return the parameters
6893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
6993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public String[] getParameters() {
7093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return copy(parameters);
7193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
7293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
7393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
7493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Get the String value of the parameter at the specified index
7547fb67a4e600f339064de4c08f10279accc95e92chrismair     *
7693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @param index - the index
7793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return the parameter value as a String
7847fb67a4e600f339064de4c08f10279accc95e92chrismair     * @throws org.mockftpserver.core.util.AssertFailedException
7947fb67a4e600f339064de4c08f10279accc95e92chrismair     *          if the parameter index is invalid or the value is not a valid String
8093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
8131d38a11c73497bc273bfc0081b0d3b723482239chrismair    public String getRequiredParameter(int index) {
8293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        assertValidIndex(index);
8393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return parameters[index];
8493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
8593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
8693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
8793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Get the String value of the parameter at the specified index; return null if no parameter exists for the index
8847fb67a4e600f339064de4c08f10279accc95e92chrismair     *
8993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @param index - the index
9093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return the parameter value as a String, or null if this Command does not have a parameter for that index
9193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
9233e5281191636818c9efc791bdcd670c3a845f7echrismair    public String getParameter(int index) {
9393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return (parameters.length > index) ? parameters[index] : null;
9493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
9593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
9693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
9733e5281191636818c9efc791bdcd670c3a845f7echrismair     * Get the String value of the parameter at the specified index; return null if no
9833e5281191636818c9efc791bdcd670c3a845f7echrismair     * parameter exists for the index. This is an alias for {@link #getParameter(int)}.
9947fb67a4e600f339064de4c08f10279accc95e92chrismair     *
10033e5281191636818c9efc791bdcd670c3a845f7echrismair     * @param index - the index
10133e5281191636818c9efc791bdcd670c3a845f7echrismair     * @return the parameter value as a String, or null if this Command does not have a parameter for that index
10233e5281191636818c9efc791bdcd670c3a845f7echrismair     */
10333e5281191636818c9efc791bdcd670c3a845f7echrismair    public String getOptionalString(int index) {
10433e5281191636818c9efc791bdcd670c3a845f7echrismair        return getParameter(index);
10533e5281191636818c9efc791bdcd670c3a845f7echrismair    }
10633e5281191636818c9efc791bdcd670c3a845f7echrismair
10733e5281191636818c9efc791bdcd670c3a845f7echrismair    /**
10893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @see java.lang.Object#equals(java.lang.Object)
10993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
11093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public boolean equals(Object obj) {
11193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        if (this == obj) {
11293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair            return true;
11393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        }
11493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        if (obj == null || !(obj instanceof Command)) {
11593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair            return false;
11693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        }
11793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return this.hashCode() == obj.hashCode();
11893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
11993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
12093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
12193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @see java.lang.Object#hashCode()
12293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
12393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public int hashCode() {
12493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        String str = name + Arrays.asList(parameters);
12593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return str.hashCode();
12693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
12747fb67a4e600f339064de4c08f10279accc95e92chrismair
12893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
12993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Return the String representation of this object
13047fb67a4e600f339064de4c08f10279accc95e92chrismair     *
13193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @see java.lang.Object#toString()
13293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
13393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public String toString() {
13433e5281191636818c9efc791bdcd670c3a845f7echrismair        return "Command[" + name + ":" + Arrays.asList(parameters) + "]";
13593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
13693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair
13793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
13893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Return the name, normalized to a common format - convert to upper case.
13947fb67a4e600f339064de4c08f10279accc95e92chrismair     *
14093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return the name converted to upper case
14193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
14293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    public static String normalizeName(String name) {
14393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return name.toUpperCase();
14493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
14547fb67a4e600f339064de4c08f10279accc95e92chrismair
14693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
14793102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Construct a shallow copy of the specified array
14847fb67a4e600f339064de4c08f10279accc95e92chrismair     *
14993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @param array - the array to copy
15093102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @return a new array with the same contents
15193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
15293102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    private static String[] copy(String[] array) {
15393102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        String[] newArray = new String[array.length];
15493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        System.arraycopy(array, 0, newArray, 0, array.length);
15593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair        return newArray;
15693102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
15747fb67a4e600f339064de4c08f10279accc95e92chrismair
15893102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    /**
15993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * Assert that the index is valid
16047fb67a4e600f339064de4c08f10279accc95e92chrismair     *
16193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     * @param index - the index
16247fb67a4e600f339064de4c08f10279accc95e92chrismair     * @throws org.mockftpserver.core.CommandSyntaxException
16347fb67a4e600f339064de4c08f10279accc95e92chrismair     *          - if the parameter index is invalid
16493102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair     */
16593102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    private void assertValidIndex(int index) {
16647fb67a4e600f339064de4c08f10279accc95e92chrismair        if (index < 0 || index >= parameters.length) {
16747fb67a4e600f339064de4c08f10279accc95e92chrismair            throw new CommandSyntaxException("The parameter index " + index + " is not valid for " + this);
16847fb67a4e600f339064de4c08f10279accc95e92chrismair        }
16993102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair    }
17047fb67a4e600f339064de4c08f10279accc95e92chrismair
17193102446a7b7c3d17888064b4e2e4e5cb534e6d0chrismair}
172