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

org.conqat.lib.commons.options.Options Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
/*
 * Copyright (c) CQSE GmbH
 *
 * 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 org.conqat.lib.commons.options;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.stream.Collectors;

import org.conqat.lib.commons.enums.EnumUtils;
import org.conqat.lib.commons.string.StringUtils;

/**
 * This class offers a safe and flexible interface to Java properties files.
 * 

* Property files must follow the format for Java properties files. See Javadoc of * {@link java.util.Properties} for details. * * @author Florian Deissenboeck * @author Axel Gerster * * @see java.util.Properties */ public class Options { /** * Returned by countValues when trying to count values of a non-present option. */ public static final int OPTION_NOT_PRESENT = -1; /** * This implementation is back by a Properties object. */ private Properties properties; /** * Construct a new Option object holding now options. Use methods * {@link #init(String)}or {@link #setOption(String, String)}to store options. */ public Options() { init(); } /** * This initializes the Options object by reading a properties file. * * @param filename * full-qualified name of the properties file * @throws IOException * Thrown if an I/O problem is encountered while reading properties file. */ public void init(String filename) throws IOException { properties = new Properties(); try (InputStream inputStream = new FileInputStream(filename)) { properties.load(inputStream); } } /** * Init empty Options object. Existing options are cleared. */ public void init() { properties = new Properties(); } /** * Sets and option. Setting an already existing option overwrites current value. * * @param option * name of the option * @param value * option's value, must have same format as defined in the properties file * @return true if option was already present, false otherwise */ public boolean setOption(String option, String value) { boolean overridden = hasOption(option); properties.setProperty(option, value); return overridden; } /** * Gets the value for a specified option. * * @param option * the name of the option * @return the option's value, if the option is not present or has a null value * null is returned. If the option has a space separated value list, the whole * list is returned. Use {@link #getValues(String)}to access single values. */ public String getValue(String option) { if (!hasOption(option)) { return null; } String value = properties.getProperty(option); if ("".equals(value)) { return null; } return value; } /** * Return the value for a specified option or a default value if option is not present. * * @param option * name of the option * @param defaultValue * default value to use, if option is not present * @return the option's value or the default value */ public String getValue(String option, String defaultValue) { if (hasOption(option)) { return getValue(option); } return defaultValue; } /** * Returns the space separated value of an option as array. An option might have more the one space * separated value. This method returns them as an array. To allow values containing spaces use * double quotes. *

* Example: For the following line in a properties file *

* option=value1 value2 "value 3" value4 *

* the method returns this array
* *
* a[0] = "value1"
* a[1] = "value2"
* a[2] = "value 3"
* a[3] = "value4"
*
* * @param option * name of the option * @return the array as described above */ public String[] getValues(String option) { if (!hasOption(option)) { return null; } String values = properties.getProperty(option); if ("".equals(values)) { return null; } return parse(values); } /** * Checks if the specified option is present and has a boolean value. Boolean values are * true,false, yes and no * * @param option * name of the option * @return if the option is present and has a boolean value true is returned, otherwise * false */ public boolean hasBooleanValue(String option) { if (!hasValue(option)) { return false; } String value = getValue(option); return checkTrue(value) || checkFalse(value); } /** * Get the value for an option as boolean. * * @param option * name of the option * @return the value of this option * @throws ValueConversionException * if the option doesn't have a boolean value. Use * {@link #hasBooleanValue(String)}method or default value enabled version * {@link #getBooleanValue(String, boolean)}of this method to avoid conversion problems. */ public boolean getBooleanValue(String option) throws ValueConversionException { if (!hasBooleanValue(option)) { throw new ValueConversionException(option); } String value = getValue(option); return checkTrue(value); } /** * Get the value for an option as instance of an enumeration. Enumeration names are matched * case-insensitively. Dashes in values are replaced by underscores. *

* Typical usage is: * *

	 * 
	 * Colors color = options.getEnumValue("enum1", Colors.class);
	 * 
* * where Colors is an enumeration. * * @param * the enumeration * @param option * the name of the option * @param enumType * the enumeration type * @return the enumeration entry * @throws ValueConversionException * if the option doesn't have a value of the specified enumeration. Use * {@link #hasEnumValue(String, Class)}method or default value enabled version * {@link #getEnumValue(String, Enum, Class)}of this method to avoid conversion * problems. */ public > T getEnumValue(String option, Class enumType) throws ValueConversionException { if (!hasEnumValue(option, enumType)) { throw new ValueConversionException(option); } String value = getValue(option); return EnumUtils.valueOfIgnoreCase(enumType, normalizeEnumConstantName(value)); } /** * Same as {@link #getEnumValue(String, Class)} but allows to specify default value. * * @param * the enumeration * @param option * the name of the option * @param enumType * the enumeration type * @return the enumeration entry * */ public > T getEnumValue(String option, T defaultValue, Class enumType) { try { return getEnumValue(option, enumType); } catch (ValueConversionException e) { return defaultValue; } } /** * Checks if the specified option is present and has a legal value. * * @param option * name of the option * @return if the option is present and has a legal value true is returned, otherwise * false */ public > boolean hasEnumValue(String option, Class enumType) { if (!hasValue(option)) { return false; } String value = getValue(option); return checkEnum(value, enumType); } /** * Check if value describes an element of the enumeration (case-insensitive match). * */ private static > boolean checkEnum(String value, Class enumType) { T t = EnumUtils.valueOfIgnoreCase(enumType, normalizeEnumConstantName(value)); return t != null; } /** * Get the value for an option as int. * * @param option * name of the option * @return the value of this option * @throws ValueConversionException * if the option doesn't have a int value. Use * {@link #hasIntValue(String)}method or default value enabled version * {@link #getIntValue(String, int)}of this method to avoid conversion problems. */ public int getIntValue(String option) throws ValueConversionException { if (!hasIntValue(option)) { throw new ValueConversionException(option); } String value = getValue(option); return Integer.parseInt(value); } /** * Checks if the specified option is present and has a int value. * * @param option * name of the option * @return if the option is present and has a int value true is returned, * otherwise false */ public boolean hasIntValue(String option) { if (!hasValue(option)) { return false; } String value = getValue(option); return checkInt(value); } /** * Same as {@link #getBooleanValue(String)}but allows to specify a default value. * * @param option * name of the option * @param defaultValue * default value * @return return the value of the option if option is present and has a boolean value, otherwise * the default value is returned */ public boolean getBooleanValue(String option, boolean defaultValue) { try { return getBooleanValue(option); } catch (ValueConversionException e) { return defaultValue; } } /** * Same as {@link #getIntValue(String)}but allows to specify a default value. * * @param option * name of the option * @param defaultValue * default value * @return return the value of the option if option is present and has an integer value, otherwise * the default value is returned */ public int getIntValue(String option, int defaultValue) { try { return getIntValue(option); } catch (ValueConversionException e) { return defaultValue; } } /** * Checks if a given string represent an integer. * * @param value * - the string to check * @return true if the string represents an integer, false otherwise */ private static boolean checkInt(String value) { try { Integer.parseInt(value); } catch (NumberFormatException ex) { return false; } return true; } /** * Checks if the string is a boolean literal with value false. Literals * false and no are allowed. * * @param value * the string to check * @return true if the string represents a boolean literal with value * false,false otherwise */ private static boolean checkFalse(String value) { value = value.trim(); return value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"); } /** * Checks if the string is a boolean literal with value true. Literals * true and yes are allowed. * * @param value * the string to check * @return true if the string represents a boolean literal with value * true,false otherwise */ private static boolean checkTrue(String value) { value = value.trim(); return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"); } /** * Parses a space separated value list. To use values with spaces, use double quotes. * * @param string * the value list to parse * @return an array containing the values, quotes are omitted */ private static String[] parse(String string) { string = string.trim(); int length = string.length(); char[] content = new char[length]; string.getChars(0, length, content, 0); ArrayList list = new ArrayList<>(); int i = 0; int lastPos = 0; boolean inQM = false; boolean inToken = false; while (i < length) { switch (content[i]) { case ' ': case '\t': if (inToken && !inQM) { // parameter found String parameter = string.substring(lastPos, i).trim(); parameter = parameter.replaceAll("\"", ""); list.add(parameter); lastPos = i; } inToken = false; break; case '\"': inQM = !inQM; break; default: inToken = true; } i++; } String parameter = string.substring(lastPos, i).trim(); parameter = parameter.replaceAll("\"", ""); list.add(parameter); String[] result = new String[list.size()]; list.toArray(result); return result; } /** * Checks if a specified option is present. * * @param option * name of the option * @return true if option is present, false otherwise */ public boolean hasOption(String option) { return properties.getProperty(option) != null; } /** * Checks if specified option has a value. * * @param option * name of the option * @return true if option is present and has a value, false otherwise * (even if option is present but doesn't have a value) */ public boolean hasValue(String option) { return countValues(option) > 0; } /** * Count the space separated values of an option. Double quotes are taken into account. * * @param option * name of the option * @return value count */ public int countValues(String option) { if (!hasOption(option)) { return OPTION_NOT_PRESENT; } String[] values = getValues(option); if (values == null) { return 0; } return values.length; } /** * Returns a list with key-value-pairs as string. * * @return key-value-pairs as string */ @Override public String toString() { return properties.entrySet().stream().map(entry -> entry.getKey() + " = " + entry.getValue()) .collect(Collectors.joining(StringUtils.LINE_SEPARATOR)); } /** * Exception objects of this class are possibly returned by * {@link Options#getBooleanValue(String)}and {@link Options#getIntValue(String)}, if corresponding * options don't have a boolean respectively integer value. * */ public static class ValueConversionException extends Exception { /** * Construct new conversion exception. * * @param option * name of the option causing the exception */ public ValueConversionException(String option) { super("Option: " + option); } } /** * Get the value for an option as float. * * @param option * name of the option * @return the value of this option * @throws ValueConversionException * if the option doesn't have a float value. */ public float getFloatValue(String option) throws ValueConversionException { if (!hasFloatValue(option)) { throw new ValueConversionException(option); } String value = getValue(option); return Float.parseFloat(value); } /** * Checks if the specified option is present and has a float value. * * * @param option * name of the option * @return if the option is present and has a float value true is returned, otherwise * false */ public boolean hasFloatValue(String option) { if (!hasValue(option)) { return false; } String value = getValue(option); return checkFloat(value); } /** * Checks if a string contains a float. */ private static boolean checkFloat(String value) { try { Float.parseFloat(value); } catch (NumberFormatException ex) { return false; } return true; } /** * Normalize enum constant name. This replaces all dashes with underscores. */ private static String normalizeEnumConstantName(String constantName) { return constantName.replace("-", "_"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy