All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pvalsecc.opts.GetOptions Maven / Gradle / Ivy

/*
 * Copyright (C) 2008 Patrick Valsecchi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  U
 */
package org.pvalsecc.opts;

import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Helper to parse a process' arguments and assign their values to a bean.
 * 

* Uses the {@link org.pvalsecc.opts.Option} annotation on the bean to know what * attributes are configurable and how. */ public class GetOptions { private static Pattern BOOLEAN = Pattern.compile("^--([^=]+)$"); private static Pattern OTHER = Pattern.compile("^--([^=]+)=(.+)$"); /** * Parses the arguments and assign their values to the provided bean * * @param args The arguments as passed to the "main" static method. * @param dest The bean to initialize. * @return List of non "--" arguments (that are ignored) * @throws InvalidOption In case of error. */ public static List parse(String[] args, Object dest) throws InvalidOption { List remaining = new ArrayList(5); Set seen = new HashSet(); if (args != null) { for (int i = 0; i < args.length; ++i) { String arg = args[i]; Matcher bool = BOOLEAN.matcher(arg); Matcher other = OTHER.matcher(arg); if (bool.matches()) { String name = bool.group(1); handleBoolean(dest, name); seen.add(name); } else if (other.matches()) { String name = other.group(1); String value = other.group(2); handleOther(dest, name, value); seen.add(name); } else { remaining.add(arg); } } } checkMandatory(dest, dest.getClass(), seen); return remaining; } public static String getShortList(Object dest) { StringBuilder result = new StringBuilder(); final Class aClass = dest.getClass(); getShortList(result, aClass); return result.toString(); } public static String getLongList(Object dest) throws IllegalAccessException { StringBuilder result = new StringBuilder(); final Class aClass = dest.getClass(); getLongList(dest, result, aClass); return result.toString(); } private static void checkMandatory(Object dest, Class aClass, Set seen) throws InvalidOption { if (aClass == Object.class) return; checkMandatory(dest, aClass.getSuperclass(), seen); for (Field field : aClass.getDeclaredFields()) { final Option annotation = field.getAnnotation(Option.class); final String name = field.getName(); if (annotation != null && !seen.contains(name)) { if (annotation.environment().length() == 0) { if (annotation.mandatory()) { throw new InvalidOption("Mandatory option missing: " + name); } } else { String env = System.getenv(annotation.environment()); if (env != null) { handleOther(dest, field.getName(), env); } else if (annotation.mandatory()) { throw new InvalidOption("Mandatory option missing: " + name); } } } } } private static void getShortList(StringBuilder result, Class aClass) { if (aClass == Object.class) return; getShortList(result, aClass.getSuperclass()); for (Field field : aClass.getDeclaredFields()) { final Option annotation = field.getAnnotation(Option.class); if (annotation != null) { if (result.length() > 0) { result.append(' '); } if (!annotation.mandatory()) { result.append("["); } if (field.getType() == boolean.class) { result.append("--").append(field.getName()); } else { result.append("--").append(field.getName()).append("={value}"); } if (!annotation.mandatory()) { result.append("]"); } } } } private static void getLongList(Object dest, StringBuilder result, Class aClass) throws IllegalAccessException { if (aClass == Object.class) return; getLongList(dest, result, aClass.getSuperclass()); for (Field field : aClass.getDeclaredFields()) { final Option annotation = field.getAnnotation(Option.class); if (annotation != null) { if (result.length() > 0) { result.append('\n'); } if (field.getType() == boolean.class) { result.append(" --").append(field.getName()); } else { result.append(" --").append(field.getName()).append("={").append(field.getType().getSimpleName()).append("}"); } result.append(": ").append(annotation.desc()); if (!annotation.mandatory()) { field.setAccessible(true); result.append(" (defaults to [").append(field.get(dest)).append("])"); } } } } private static void handleBoolean(Object dest, String name) throws InvalidOption { try { Field opt = getField(dest, name); if (opt.getAnnotation(Option.class) == null) { throw new InvalidOption("'" + name + "' is not an option"); } opt.setAccessible(true); opt.setBoolean(dest, true); } catch (Exception e) { throw new InvalidOption("Unknown option '" + name + "'", e); } } private static void handleOther(Object dest, String name, String value) throws InvalidOption { try { Field opt = getField(dest, name); if (opt.getAnnotation(Option.class) == null) { throw new InvalidOption("'" + name + "' is not an option"); } opt.setAccessible(true); if (opt.getType() == int.class) { opt.setInt(dest, Integer.parseInt(value)); } else if (opt.getType() == double.class) { opt.setDouble(dest, Double.parseDouble(value)); } else if (opt.getType() == float.class) { opt.setFloat(dest, Float.parseFloat(value)); } else if (opt.getType() == boolean.class) { opt.setBoolean(dest, Boolean.parseBoolean(value)); } else if (opt.getType() == String.class) { opt.set(dest, value); } else if (opt.getType() == Integer.class) { if (value.equalsIgnoreCase("null")) { opt.set(dest, null); } else { opt.set(dest, Integer.parseInt(value)); } } else if (Enum.class.isAssignableFrom(opt.getType())) { opt.set(dest, Enum.valueOf((Class) opt.getType(), value.toUpperCase())); } else if (Collection.class.isAssignableFrom(opt.getType())) { //the generics type is dropped during compilation. So we can just hope it's String. ((Collection) opt.get(dest)).add(value); } else { throw new InvalidOption("Unknown type for option " + name + ": " + opt.getType()); } } catch (NoSuchFieldException e) { throw new InvalidOption("Unknown option " + name, e); } catch (IllegalAccessException e) { throw new InvalidOption("Unknown option " + name, e); } catch (IllegalArgumentException e) { throw new InvalidOption("Unknown value [" + value + "] for option " + name, e); } catch (RuntimeException e) { throw new InvalidOption("Unknown option " + name, e); } } private static Field getField(Object dest, String name) throws NoSuchFieldException { final Field field = getField(name, dest.getClass()); if (field == null) throw new NoSuchFieldException("name"); return field; } private static Field getField(String name, Class aClass) { Field result = null; try { result = aClass.getDeclaredField(name); } catch (NoSuchFieldException e) { //ignored } if (result == null && aClass != Object.class) { result = getField(name, aClass.getSuperclass()); } return result; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy