/*
* Copyright © 2014 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package co.cask.cdap.common.options;
import java.lang.reflect.Field;
/**
* Specifies an implementation for the specification of an Option.
*/
public class OptionSpec {
/**
* Instance of the field.
*/
private Field field;
/**
* Specification of an object.
*/
private Option option;
/**
* Object the field and specification are from.
*/
private Object object;
/**
* Creates an instance of OptionSpec.
* @param field annotated with @Option
* @param option specifying information about the field that needs to be filled in by command line argument.
* @param object specifies the object the option is specified in.
*/
public OptionSpec(Field field, Option option, Object object) {
this.field = field;
this.option = option;
this.object = object;
}
/**
* Returns the name of the field.
* @return name of the field.
*/
public String getName() {
return option.name().isEmpty() ? field.getName() : option.name();
}
/**
* Returns the type of the field.
* @return type of the field.
*/
public Class<?> getType() {
return field.getType();
}
/**
* Returns the type name of the field annotated by <code>@Option</code>.
* @return name of the type of field.
*/
public String getTypeName() {
return option.type();
// Class<?> type = getType();
// if(type == String.class) {
// return "String";
// }
// return type.toString();
}
/**
* Returns whether the field needs to be hidden or no.
* @return true if hidden; false otherwise.
*/
public boolean isHidden() {
return option.hidden();
}
/**
* Returns the usage of the field.
* @return String representation of usage.
*/
public String getUsage() {
return option.usage();
}
/**
* Returns environment variable to be associated with the field annotated with @Option.
* @return value of environment field.
*/
public String getEnvVar() {
return option.envVar();
}
/**
* Returns string representation of default value.
* @return default value of the field.
*/
public String getDefaultValue() {
String value = "";
try {
// If private field, set the accessible to true to access it.
if (!field.isAccessible()) {
field.setAccessible(true);
}
// Now depending on the type of the field convert the field
// to string type.
if (field.getType() == int.class) {
value = Integer.toString(field.getInt(object));
} else if (field.getType() == long.class) {
value = Long.toString(field.getLong(object));
} else if (field.getType() == short.class) {
value = Short.toString(field.getShort(object));
} else if (field.getType() == float.class) {
value = Float.toString(field.getFloat(object));
} else if (field.getType() == double.class) {
value = Double.toString(field.getDouble(object));
} else if (field.getType() == boolean.class) {
value = Boolean.toString(field.getBoolean(object));
} else if (field.getType() == String.class) {
String s = (String) field.get(object);
if (s != null) {
value = "\"" + s + "\"";
} else {
value = "null";
}
}
} catch (IllegalAccessException e) {
throw new IllegalAccessError(e.getMessage());
}
return value;
}
/**
* Sets the field with the value.
* @param value to be set
* @throws IllegalAccessException
*/
public void setValue(String value) throws IllegalAccessException {
if (!field.isAccessible()) {
field.setAccessible(true);
}
if (field.getType() == boolean.class) {
if (value.equals("true") || value.isEmpty()) {
field.setBoolean(object, true);
} else if (value.equals("false")) {
field.setBoolean(object, false);
} else {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == double.class) {
try {
field.setDouble(object, Double.parseDouble(value));
} catch (NumberFormatException e) {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == float.class) {
try {
field.setFloat(object, Float.parseFloat(value));
} catch (NumberFormatException e) {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == int.class) {
try {
field.setInt(object, Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == long.class) {
try {
field.setLong(object, Long.parseLong(value));
} catch (NumberFormatException e) {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == short.class) {
try {
field.setShort(object, Short.parseShort(value));
} catch (NumberFormatException e) {
throw new IllegalOptionValueException(getName(), value);
}
} else if (field.getType() == String.class) {
field.set(object, value);
} else {
throw new UnsupportedOptionTypeException(field.getName());
}
}
}