001package org.unix4j.unix.cd;
002
003
004import org.unix4j.command.Arguments;
005import org.unix4j.context.ExecutionContext;
006import org.unix4j.convert.ValueConverter;
007import org.unix4j.util.ArrayUtil;
008import org.unix4j.variable.Arg;
009import org.unix4j.variable.VariableContext;
010
011import org.unix4j.unix.Cd;
012
013/**
014 * Arguments and options for the {@link Cd cd} command.
015 */
016public final class CdArguments implements Arguments<CdArguments> {
017        
018
019        
020        // operand: <file>
021        private java.io.File file;
022        private boolean fileIsSet = false;
023        
024        // operand: <path>
025        private String path;
026        private boolean pathIsSet = false;
027        
028        /**
029         * Constructor to use if no options are specified.
030         */
031        public CdArguments() {
032                super();
033        }
034
035        private Object resolveVariable(VariableContext context, String variable) {
036                final Object value = context.getValue(variable);
037                if (value != null) {
038                        return value;
039                }
040                throw new IllegalArgumentException("cannot resolve variable " + variable + 
041                                " in command: cd " + this);
042        }
043        private <V> V convert(ExecutionContext context, String operandName, Class<V> operandType, Object value) {
044                final ValueConverter<V> converter = context.getValueConverterFor(operandType);
045                final V convertedValue;
046                if (converter != null) {
047                        convertedValue = converter.convert(value);
048                } else {
049                        convertedValue = null;
050                }
051                if (convertedValue != null) {
052                        return convertedValue;
053                }
054                throw new IllegalArgumentException("cannot convert --" + operandName + 
055                                " value '" + value + "' into the type " + operandType.getName() + 
056                                " for cd command");
057        }
058        
059        @Override
060        public CdArguments getForContext(ExecutionContext context) {
061                if (context == null) {
062                        throw new NullPointerException("context cannot be null");
063                }
064                //no String... args for this command, hence nothing to resolve
065                return this;
066        }
067        
068        /**
069         * Returns the {@code <file>} operand value: the file to use as input; relative paths are not resolved (use the
070                        string path argument to enable relative path resolving based on the
071                        current working directory).
072         * 
073         * @return the {@code <file>} operand value (variables are not resolved)
074         * @throws IllegalStateException if this operand has never been set
075         * 
076         */
077        public java.io.File getFile() {
078                if (fileIsSet) {
079                        return file;
080                }
081                throw new IllegalStateException("operand has not been set: " + file);
082        }
083
084        /**
085         * Returns true if the {@code <file>} operand has been set. 
086         * <p>
087         * Note that this method returns true even if {@code null} was passed to the
088         * {@link #setFile(java.io.File)} method.
089         * 
090         * @return      true if the setter for the {@code <file>} operand has 
091         *                      been called at least once
092         */
093        public boolean isFileSet() {
094                return fileIsSet;
095        }
096        /**
097         * Sets {@code <file>}: the file to use as input; relative paths are not resolved (use the
098                        string path argument to enable relative path resolving based on the
099                        current working directory).
100         * 
101         * @param file the value for the {@code <file>} operand
102         */
103        public void setFile(java.io.File file) {
104                this.file = file;
105                this.fileIsSet = true;
106        }
107        /**
108         * Returns the {@code <path>} operand value (variables are NOT resolved): the directory to become the new current working directory; 
109                        wildcards * and ? are supported; relative paths are resolved on the
110            basis of the current working directory.
111         * 
112         * @return the {@code <path>} operand value (variables are not resolved)
113         * @throws IllegalStateException if this operand has never been set
114         * @see #getPath(ExecutionContext)
115         */
116        public String getPath() {
117                if (pathIsSet) {
118                        return path;
119                }
120                throw new IllegalStateException("operand has not been set: " + path);
121        }
122        /**
123         * Returns the {@code <path>} (variables are resolved): the directory to become the new current working directory; 
124                        wildcards * and ? are supported; relative paths are resolved on the
125            basis of the current working directory.
126         * 
127         * @param context the execution context used to resolve variables
128         * @return the {@code <path>} operand value after resolving variables
129         * @throws IllegalStateException if this operand has never been set
130         * @see #getPath()
131         */
132        public String getPath(ExecutionContext context) {
133                final String value = getPath();
134                if (Arg.isVariable(value)) {
135                        final Object resolved = resolveVariable(context.getVariableContext(), value);
136                        final String converted = convert(context, "path", String.class, resolved);
137                        return converted;
138                }
139                return value;
140        }
141
142        /**
143         * Returns true if the {@code <path>} operand has been set. 
144         * <p>
145         * Note that this method returns true even if {@code null} was passed to the
146         * {@link #setPath(String)} method.
147         * 
148         * @return      true if the setter for the {@code <path>} operand has 
149         *                      been called at least once
150         */
151        public boolean isPathSet() {
152                return pathIsSet;
153        }
154        /**
155         * Sets {@code <path>}: the directory to become the new current working directory; 
156                        wildcards * and ? are supported; relative paths are resolved on the
157            basis of the current working directory.
158         * 
159         * @param path the value for the {@code <path>} operand
160         */
161        public void setPath(String path) {
162                this.path = path;
163                this.pathIsSet = true;
164        }
165        
166
167        @Override
168        public String toString() {
169                // ok, we have options or arguments or both
170                final StringBuilder sb = new StringBuilder();
171
172{
173                        // operand: <file>
174                        if (fileIsSet) {
175                                if (sb.length() > 0) sb.append(' ');
176                                sb.append("--").append("file");
177                                sb.append(" ").append(toString(getFile()));
178                        }
179                        // operand: <path>
180                        if (pathIsSet) {
181                                if (sb.length() > 0) sb.append(' ');
182                                sb.append("--").append("path");
183                                sb.append(" ").append(toString(getPath()));
184                        }
185                }
186                
187                return sb.toString();
188        }
189        private static String toString(Object value) {
190                if (value != null && value.getClass().isArray()) {
191                        return ArrayUtil.toString(value);
192                }
193                return String.valueOf(value);
194        }
195}