001package org.unix4j.unix.from; 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.From; 012 013/** 014 * Arguments and options for the {@link From from} command. 015 */ 016public final class FromArguments implements Arguments<FromArguments> { 017 018 019 020 // operand: <path> 021 private String path; 022 private boolean pathIsSet = false; 023 024 // operand: <input> 025 private org.unix4j.io.Input input; 026 private boolean inputIsSet = false; 027 028 /** 029 * Constructor to use if no options are specified. 030 */ 031 public FromArguments() { 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: from " + 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 from command"); 057 } 058 059 @Override 060 public FromArguments 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 <path>} operand value (variables are NOT resolved): the file to use as input; wildcards * and ? are supported; relative 070 paths are resolved on the basis of the current working directory. 071 * 072 * @return the {@code <path>} operand value (variables are not resolved) 073 * @throws IllegalStateException if this operand has never been set 074 * @see #getPath(ExecutionContext) 075 */ 076 public String getPath() { 077 if (pathIsSet) { 078 return path; 079 } 080 throw new IllegalStateException("operand has not been set: " + path); 081 } 082 /** 083 * Returns the {@code <path>} (variables are resolved): the file to use as input; wildcards * and ? are supported; relative 084 paths are resolved on the basis of the current working directory. 085 * 086 * @param context the execution context used to resolve variables 087 * @return the {@code <path>} operand value after resolving variables 088 * @throws IllegalStateException if this operand has never been set 089 * @see #getPath() 090 */ 091 public String getPath(ExecutionContext context) { 092 final String value = getPath(); 093 if (Arg.isVariable(value)) { 094 final Object resolved = resolveVariable(context.getVariableContext(), value); 095 final String converted = convert(context, "path", String.class, resolved); 096 return converted; 097 } 098 return value; 099 } 100 101 /** 102 * Returns true if the {@code <path>} operand has been set. 103 * <p> 104 * Note that this method returns true even if {@code null} was passed to the 105 * {@link #setPath(String)} method. 106 * 107 * @return true if the setter for the {@code <path>} operand has 108 * been called at least once 109 */ 110 public boolean isPathSet() { 111 return pathIsSet; 112 } 113 /** 114 * Sets {@code <path>}: the file to use as input; wildcards * and ? are supported; relative 115 paths are resolved on the basis of the current working directory. 116 * 117 * @param path the value for the {@code <path>} operand 118 */ 119 public void setPath(String path) { 120 this.path = path; 121 this.pathIsSet = true; 122 } 123 /** 124 * Returns the {@code <input>} operand value: the input object to read from 125 * 126 * @return the {@code <input>} operand value (variables are not resolved) 127 * @throws IllegalStateException if this operand has never been set 128 * 129 */ 130 public org.unix4j.io.Input getInput() { 131 if (inputIsSet) { 132 return input; 133 } 134 throw new IllegalStateException("operand has not been set: " + input); 135 } 136 137 /** 138 * Returns true if the {@code <input>} operand has been set. 139 * <p> 140 * Note that this method returns true even if {@code null} was passed to the 141 * {@link #setInput(org.unix4j.io.Input)} method. 142 * 143 * @return true if the setter for the {@code <input>} operand has 144 * been called at least once 145 */ 146 public boolean isInputSet() { 147 return inputIsSet; 148 } 149 /** 150 * Sets {@code <input>}: the input object to read from 151 * 152 * @param input the value for the {@code <input>} operand 153 */ 154 public void setInput(org.unix4j.io.Input input) { 155 this.input = input; 156 this.inputIsSet = true; 157 } 158 159 160 @Override 161 public String toString() { 162 // ok, we have options or arguments or both 163 final StringBuilder sb = new StringBuilder(); 164 165{ 166 // operand: <path> 167 if (pathIsSet) { 168 if (sb.length() > 0) sb.append(' '); 169 sb.append("--").append("path"); 170 sb.append(" ").append(toString(getPath())); 171 } 172 // operand: <input> 173 if (inputIsSet) { 174 if (sb.length() > 0) sb.append(' '); 175 sb.append("--").append("input"); 176 sb.append(" ").append(toString(getInput())); 177 } 178 } 179 180 return sb.toString(); 181 } 182 private static String toString(Object value) { 183 if (value != null && value.getClass().isArray()) { 184 return ArrayUtil.toString(value); 185 } 186 return String.valueOf(value); 187 } 188}