Skip to content

Instantly share code, notes, and snippets.

@manoelcampos
Last active February 17, 2018 22:46
Show Gist options
  • Save manoelcampos/6ab623667f835ff1296f10a0834d1212 to your computer and use it in GitHub Desktop.
Save manoelcampos/6ab623667f835ff1296f10a0834d1212 to your computer and use it in GitHub Desktop.
A functional, generic class to show how to get String values from an array and return such values converted to the generic type.
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.lang.reflect.Array;
public class Option2<T>{
private int length;
private String defaultValue;
private final Function<String, T> conversionFunction;
private final Class<T> klass;
/**
* Creates an Option2 that consider the values are String and don't need to be converted.
* If the generic type is different from String, you must use the
* overloaded constructor to provide a conversion {@link Function}.
*
* <p>Using this construtor for a generic type different from String
* will throw a RuntimeException when trying to convert the values
* from the Option2.</p>
*/
@SuppressWarnings("unchecked")
public Option2(final Class<T> klass){
this(klass, value -> (T)value);
}
public Option2(final Class<T> klass, final Function<String, T> conversionFunction){
Objects.requireNonNull(conversionFunction);
this.conversionFunction = conversionFunction;
this.klass = klass;
}
public T getFirstValue(final String[] values){
return getValues(values)[0];
}
/**
* Gets the values of the Option2, excluding the Option2 name (the 0th element).
* @return an array containing the values (without the 0th element), if the values' length isn't as expected;
* or an array containing the default value if the length isn't as expected and there is a default value.
* @throws IllegalStateException when the length of values isn't as expected and there isn't a default value
*/
public T[] getValues(final String[] values){
if(defaultValue == null && values.length != length){
throw new IllegalStateException("Wrong Option2 line passed, string options do only have 2 values");
}
if(values.length == length) {
return createGenericArray(values, 1);
}
return createGenericArray(new String[]{defaultValue});
}
private T[] createGenericArray(final String[] values){
return createGenericArray(values, 0);
}
@SuppressWarnings("unchecked")
private T[] createGenericArray(final String[] values, final int startInclusive){
final T[] array = (T[])Array.newInstance(klass, values.length-startInclusive);
//It was required to convert to list then to array in order to get an array of the generic type.
Arrays
.stream(values, startInclusive, values.length)
.map(this.conversionFunction)
.collect(Collectors.toList())
.toArray(array);
return array;
}
/* Trying the implementation. */
public static void main(String[] args) {
System.out.println();
//Creates an Option2 of String values, which doesn't require a conversion Function.
Option2<String> strOpt = new Option2<>(String.class);
strOpt.length = 3;
String[] values = new String[]{"-o", "1", "2"};
System.out.println("First String Value: " + strOpt.getFirstValue(values));
System.out.println("String Values: " + Arrays.toString(strOpt.getValues(values)));
try{
values = new String[]{"-o", "1"};
//Error because the length of values isn't equal to 3
System.out.println("First String Value: " + strOpt.getFirstValue(values));
} catch(Exception e){
System.out.println("\nError: " + e.getMessage() + "\n");
}
strOpt.length = 2;
strOpt.defaultValue = "default value";
values = new String[]{"-o"};
System.out.println("First String Value: " + strOpt.getFirstValue(values));
System.out.println("String Values: " + Arrays.toString(strOpt.getValues(values)) + "\n");
//Creates an Option2 of Integer values, providing a Function to convert String to Integer.
Option2<Integer> intOpt = new Option2<>(Integer.class, value -> Integer.valueOf(value));
intOpt.length = 3;
values = new String[]{"-o", "1", "2"};
System.out.println("\nFirst Int Value: " + intOpt.getFirstValue(values));
Integer[] intValues = intOpt.getValues(values);
System.out.println("Int Values: ");
for(Integer i: intValues){
System.out.println(i);
}
System.out.println();
values = new String[]{"-o", "99", "this value isn't a number and will throw an exception"};
try {
System.out.println("First Int Value: " + intOpt.getFirstValue(values));
intValues = intOpt.getValues(values);
System.out.println("Int Values: ");
for(Integer i: intValues){
System.out.println(i);
}
}catch(RuntimeException e){
System.out.println(e.getMessage());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment