Last active
August 29, 2015 14:24
-
-
Save rbrick/9919b645f0bc2be43670 to your computer and use it in GitHub Desktop.
Parse strings and inject them as parameters into methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Binder<B, T> { | |
Binder<B, T> bind(B bind); | |
void to(T to); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.PARAMETER) | |
public @interface Default { | |
String value(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MethodParser { | |
private Method method; | |
private ParametricRegistry registry; | |
public MethodParser(Method method, ParametricRegistry registry) { | |
this.method = method; | |
this.registry = registry; | |
} | |
public Method getMethod() { | |
return method; | |
} | |
public ParametricRegistry getRegistry() { | |
return registry; | |
} | |
/** | |
* @return A list of {@link Parameter}s | |
*/ | |
public List<Parameter> parse() { | |
List<Parameter> parameters = new ArrayList<>(); | |
for (int i = 0; i < method.getParameterCount(); i++) { | |
Parameter lp = new Parameter(method.getParameterTypes()[i], method.getParameterAnnotations()[i], registry, | |
method.getParameters()[i].getName(), i); | |
parameters.add(lp); | |
} | |
return parameters; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Parameter { | |
private Class<?> type; | |
private ParametricRegistry registry; | |
private List<Annotation> annotations; | |
private int index; | |
private String name; | |
public Parameter(Class<?> type, Annotation[] annotations, ParametricRegistry registry, String name, int index) { | |
this.type = type; | |
this.annotations = Arrays.asList(annotations); | |
this.registry = registry; | |
this.index = index; | |
this.name = name; | |
} | |
public Class<?> getType() { | |
return type; | |
} | |
public boolean isAnnotationPresent(Class<? extends Annotation> annotation) { | |
boolean found = false; | |
for (Annotation anno : annotations) { | |
if (anno.annotationType() == annotation) { | |
found = true; | |
} | |
} | |
return found; | |
} | |
public Annotation getAnnotation(final Class<? extends Annotation> annotation) { | |
if (isAnnotationPresent(annotation)) { | |
return annotations.stream().filter((a) -> a.annotationType() == annotation) | |
.findFirst().orElseThrow(() -> new IllegalArgumentException("Could not find annotation!")); | |
} | |
return null; | |
} | |
public int getIndex() { | |
return index; | |
} | |
public int getArgumentIndex() { | |
return index - 1; | |
} | |
public boolean hasText() { | |
return isAnnotationPresent(Text.class); | |
} | |
public boolean hasDefault() { | |
return isAnnotationPresent(Default.class); | |
} | |
public String getDefault() { | |
if (hasDefault()) { | |
Default defaultV = (Default) getAnnotation(Default.class); | |
return defaultV.value(); | |
} | |
return null; | |
} | |
public String getName() { | |
return name; | |
} | |
public Object parse(String argument) { | |
return registry.get(type).resolve(argument); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface ParameterResolver<T> { | |
T resolve(String argument); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ParametricParser { | |
private List<Parameter> parameters; | |
public ParametricParser(List<Parameter> parameters) { | |
this.parameters = parameters; | |
} | |
public ParsedResult parse(Object sender, Arguments arguments) { | |
boolean wasSuccess = true; | |
List<Object> objects = new ArrayList<>(); | |
objects.add(sender); | |
for (Parameter parameter : parameters) { | |
Object obj = null; | |
if (arguments.get(parameter.getArgumentIndex()) == null) { | |
if (parameter.hasDefault()) { | |
obj = parameter.parse(parameter.getDefault()); | |
} else { | |
wasSuccess = false; | |
} | |
} else { | |
obj = parameter.parse(arguments.get(parameter.getArgumentIndex())); | |
} | |
// is continuous | |
if (parameter.hasText()) { | |
if (arguments.get(parameter.getArgumentIndex()) != null) { | |
obj = arguments.join(parameter.getArgumentIndex()); | |
} | |
objects.add(obj); | |
break; | |
} else if (parameter.getType().isPrimitive()) { | |
if (Number.class.isAssignableFrom(parameter.getType())) { | |
obj = PrimitiveUtils.toPrimitiveNumber((Number) obj); | |
} else if (Boolean.class.isAssignableFrom(parameter.getType())) { | |
obj = PrimitiveUtils.toPrimitiveBoolean((Boolean) obj); | |
} | |
} | |
objects.add(obj); | |
} | |
return new ParsedResult(objects.toArray(), wasSuccess); | |
} | |
public class ParsedResult { | |
private Object[] objects; | |
private boolean successful; | |
public ParsedResult(Object[] objects, boolean successful) { | |
this.objects = objects; | |
this.successful = successful; | |
} | |
public boolean isSuccessful() { | |
return successful; | |
} | |
public Object[] getObjects() { | |
return objects; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ParametricRegistry implements Binder<Class<?>, ParameterResolver<?>> { | |
private Map<Class<?>, ParameterResolver<?>> currentBindings = new HashMap<Class<?>, ParameterResolver<?>>(); | |
private Class<?> currentBind = null; | |
public ParametricRegistry() { | |
bind(String.class).to(argument -> argument); | |
bind(Integer.TYPE).to(argument -> { | |
int parsed = 0; | |
try { | |
parsed = Integer.parseInt(argument); | |
} catch (NumberFormatException ex) { | |
ex.printStackTrace(); | |
} | |
return parsed; | |
}); | |
bind(Integer.class).to(currentBindings.get(Integer.TYPE)); | |
bind(Float.TYPE).to(argument -> { | |
float parsed = 0; | |
try { | |
parsed = Float.parseFloat(argument); | |
} catch (NumberFormatException ex) { | |
ex.printStackTrace(); | |
} | |
return parsed; | |
}); | |
bind(Float.class).to(currentBindings.get(Float.TYPE)); | |
bind(Double.TYPE).to(argument -> { | |
Double parsed = 0d; | |
try { | |
parsed = Double.parseDouble(argument); | |
} catch (NumberFormatException ex) { | |
ex.printStackTrace(); | |
} | |
return parsed; | |
}); | |
bind(Double.class).to(currentBindings.get(Double.TYPE)); | |
bind(Long.TYPE).to(argument -> { | |
Long parsed = 0L; | |
try { | |
parsed = Long.parseLong(argument); | |
} catch (NumberFormatException ex) { | |
ex.printStackTrace(); | |
} | |
return parsed; | |
}); | |
bind(Long.class).to(currentBindings.get(Long.TYPE)); | |
bind(Byte.TYPE).to(argument -> { | |
Byte parsed = 0x0; | |
try { | |
parsed = Byte.parseByte(argument); | |
} catch (NumberFormatException ex) { | |
ex.printStackTrace(); | |
} | |
return parsed; | |
}); | |
bind(Byte.class).to(currentBindings.get(Byte.TYPE)); | |
bind(Boolean.TYPE).to(argument -> { | |
boolean parsed = false; | |
if (argument.equalsIgnoreCase("true") || argument.equalsIgnoreCase("yes")) { | |
parsed = true; | |
} else if (argument.equalsIgnoreCase("false") || argument.equalsIgnoreCase("no")) { | |
parsed = false; | |
} | |
return parsed; | |
}); | |
bind(Boolean.class).to(currentBindings.get(Boolean.TYPE)); | |
} | |
public Binder<Class<?>, ParameterResolver<?>> bind(Class<?> bind) { | |
this.currentBind = bind; | |
return this; | |
} | |
public void to(ParameterResolver<?> to) { | |
if (currentBind == null) { | |
throw new IllegalArgumentException("currentBind is null!"); | |
} else { | |
currentBindings.put(currentBind, to); | |
currentBind = null; | |
} | |
} | |
public Map<Class<?>, ParameterResolver<?>> getBindings() { | |
return currentBindings; | |
} | |
public ParameterResolver<?> get(Class<?> clazz) { | |
if (!currentBindings.containsKey(clazz)) { | |
throw new IllegalArgumentException("Could not find resolver for " + clazz.getSimpleName() + ".class"); | |
} | |
return currentBindings.get(clazz); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.PARAMETER) | |
public @interface Text { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment