/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.binding; /** * This class represents a numerical value range. * @author Norman Fomferra * @since 0.6 */ public class ValueRange { private final double min; private final double max; private final boolean minIncluded; private final boolean maxIncluded; public ValueRange(double min, double max) { this(min, max, true, true); } public ValueRange(double min, double max, boolean minIncluded, boolean maxIncluded) { this.min = min; this.max = max; this.minIncluded = minIncluded; this.maxIncluded = maxIncluded; } public double getMin() { return min; } public double getMax() { return max; } public boolean isMinIncluded() { return minIncluded; } public boolean isMaxIncluded() { return maxIncluded; } public boolean hasMin() { return min > Double.NEGATIVE_INFINITY; } public boolean hasMax() { return max < Double.POSITIVE_INFINITY; } public boolean contains(double v) { boolean b1 = minIncluded ? (v >= min) : (v > min); boolean b2 = maxIncluded ? (v <= max) : (v < max); return b1 && b2; } /** * Parses an {@link ValueRange}. * <p>The syntax of a version range is: * <pre> * interval ::= ( '[' | '(' ) min ',' max ( ']' | ')' ) * min ::= number | '*' * max ::= number | '*' * </pre> * @param text The textual representation of the value range. * @return The value range. * @throws IllegalArgumentException If the text has an invalid format. */ public static ValueRange parseValueRange(final String text) throws IllegalArgumentException { if (text.length() > 0) { final char c1 = text.charAt(0); if (c1 == '(' || c1 == '[') { final char c2 = text.charAt(text.length() - 1); if (c2 == ')' || c2 == ']') { int d = text.indexOf(',', 1); if (d > 1 && d < text.length() - 2) { String s1 = text.substring(1, d).trim(); String s2 = text.substring(d + 1, text.length() - 1).trim(); try { return new ValueRange( s1.equals("*") ? Double.NEGATIVE_INFINITY : Double.valueOf(ValueRange.trimNumberString(s1)), s2.equals("*") ? Double.POSITIVE_INFINITY : Double.valueOf(ValueRange.trimNumberString(s2)), c1 == '[', c2 == ']'); } catch (NumberFormatException e) { throw new IllegalArgumentException("Invalid number format in interval."); } } else { throw new IllegalArgumentException("Missing ',' in interval."); } } else { throw new IllegalArgumentException("Missing trailing ')' or ']' in interval."); } } else { throw new IllegalArgumentException("Missing leading '(' or '[' in interval."); } } else { throw new IllegalArgumentException("Empty string."); } } private static String trimNumberString(String s) { s = s.trim(); if (s.startsWith("+")) { s = s.substring(1); } return s; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(minIncluded ? '[' : '('); sb.append(hasMin() ? toString(min) : "*"); sb.append(','); sb.append(hasMax() ? toString(max) : "*"); sb.append(maxIncluded ? ']' : ')'); return sb.toString(); } private static String toString(double d) { final long l = Math.round(d); return d == l ? Long.toString(l) : Double.toString(d); } }