Coverage Report - org.jscsi.target.settings.NumericalValue
 
Classes in this File Line Coverage Branch Coverage Complexity
NumericalValue
0%
0/34
0%
0/14
3.2
 
 1  
 package org.jscsi.target.settings;
 2  
 
 3  
 
 4  
 import java.util.regex.Matcher;
 5  
 import java.util.regex.Pattern;
 6  
 
 7  
 
 8  
 /**
 9  
  * An abstract parent class to {@link SingleNumericalValue} and {@link NumericalValueRange}. Objects of these two
 10  
  * classes represent single integers and integer intervals, respectively, and can be parsed from any properly formatted
 11  
  * <i>key=value</i> pair <i>value</i>, be they formatted in decimal, hexadecimal, or Base64 notation.
 12  
  * <p>
 13  
  * Instances of {@link NumericalValue} can be intersected, i.e. that by using either the
 14  
  * {@link #intersect(NumericalValue)} or the {@link #intersect(NumericalValue, NumericalValue)}, a
 15  
  * {@link NumericalValue} can be created which encompasses all integers that are part of the range of values represented
 16  
  * by the intersected {@link NumericalValue} objects.
 17  
  * <p>
 18  
  * For example, if the interval [1,10] is intersected with the interval [5,15], the result would be a
 19  
  * {@link NumericalValueRange} representing the interval [5,10]. Intersecting an interval with a single number would
 20  
  * return the number, but only if the number is part of the interval. Generally, both methods return <code>null</code>
 21  
  * if there is no overlap.
 22  
  * 
 23  
  * @author Andreas Ergenzinger
 24  
  */
 25  0
 public abstract class NumericalValue {
 26  
 
 27  
     // *** single number regular expressions ***
 28  
     /**
 29  
      * Regular expression for decimal integers.
 30  
      */
 31  
     private static final String DECIMAL_REGEX = "0|[-]?[1-9][0-9]*";
 32  
 
 33  
     /**
 34  
      * Regular expression for hexadecimal integers.
 35  
      */
 36  
     private static final String HEX_REGEX = "0[x|X][0-9a-fA-F]+";
 37  
 
 38  
     /**
 39  
      * Regular expression for Base64 integers.
 40  
      */
 41  
     private static final String BASE_64_REGEX = "0[b|B][0-9a-zA-Z+/]+";
 42  
     private static final String SINGLE_CONSTANT_REGEX = DECIMAL_REGEX + "|" + HEX_REGEX + "|" + BASE_64_REGEX;
 43  
 
 44  
     // *** single number patterns ***
 45  
     /**
 46  
      * A precompiled pattern for matching decimal integer {@link String}.
 47  
      */
 48  0
     public static final Pattern DECIMAL_CONSTANT_PATTERN = Pattern.compile(DECIMAL_REGEX);
 49  
 
 50  
     /**
 51  
      * A precompiled pattern for matching hexadecimal integer {@link String}.
 52  
      */
 53  0
     public static final Pattern HEX_CONSTANT_PATTERN = Pattern.compile(HEX_REGEX);
 54  
 
 55  
     /**
 56  
      * A precompiled pattern for matching Base64 integer {@link String}.
 57  
      */
 58  0
     public static final Pattern BASE_64_CONSTANT_PATTERN = Pattern.compile(BASE_64_REGEX);
 59  
 
 60  
     /**
 61  
      * A precompiled pattern for matching decimal, hexadecimal, and Base64 integer {@link String}.
 62  
      */
 63  0
     public static final Pattern SINGLE_CONSTANT_PATTERN = Pattern.compile(SINGLE_CONSTANT_REGEX);
 64  
 
 65  
     /**
 66  
      * A precompiled pattern for matching decimal, hexadecimal, and Base64 integer interval {@link String} (two integers
 67  
      * separated by '~').
 68  
      */
 69  0
     public static final Pattern NUMERICAL_RANGE_PATTERN = Pattern.compile("(" + SINGLE_CONSTANT_REGEX + ")~(" + SINGLE_CONSTANT_REGEX + ")");
 70  
 
 71  
     // *** methods ***
 72  
 
 73  
     /**
 74  
      * Parses a {@link NumericalValue} from a {@link String}.
 75  
      * 
 76  
      * @param value the {@link String} to parse.
 77  
      * @return a {@link NumericalValue} or <code>null</code> if the parameter does not match any of the supported
 78  
      *         patterns (specified by the iSCSI standard).
 79  
      */
 80  
     public static final NumericalValue parseNumericalValue (final String value) {
 81  
         // return SingleNumericalValue ...
 82  0
         final Matcher singleValueMatcher = SINGLE_CONSTANT_PATTERN.matcher(value);
 83  0
         if (singleValueMatcher.matches()) return SingleNumericalValue.parseSingleNumericValue(value);
 84  
         // ... NumericalValueRange ...
 85  0
         final Matcher rangeMatcher = NUMERICAL_RANGE_PATTERN.matcher(value);
 86  0
         if (rangeMatcher.matches()) return NumericalValueRange.parseNumericalValueRange(value);
 87  
         // ... or null
 88  0
         return null;
 89  
     }
 90  
 
 91  
     /**
 92  
      * Returns a {@link NumericalValue} spanning the overlap of this {@link NumericalValue} and the parameter.
 93  
      * 
 94  
      * @param value the {@link NumericalValue} to be intersected with this object
 95  
      * @return a {@link NumericalValue} representing the intersection of this {@link NumericalValue} with the parameter
 96  
      */
 97  
     public NumericalValue intersect (final NumericalValue value) {
 98  0
         return intersect(this, value);
 99  
     }
 100  
 
 101  
     /**
 102  
      * Returns a {@link NumericalValue} representing the intersection of the two parameters
 103  
      * 
 104  
      * @param a the first {@link NumericalValue}
 105  
      * @param b the second {@link NumericalValue}
 106  
      * @return a {@link NumericalValue} representing the intersection of the two parameters
 107  
      */
 108  
     public static NumericalValue intersect (final NumericalValue a, final NumericalValue b) {
 109  
         // early exit
 110  0
         if (a == null || b == null) return null;
 111  
         // get ranges of a and b
 112  
         int aMin, aMax, bMin, bMax;
 113  0
         if (a instanceof SingleNumericalValue) {
 114  0
             final SingleNumericalValue v = (SingleNumericalValue) a;
 115  0
             aMin = v.getValue();
 116  0
             aMax = aMin;
 117  0
         } else {
 118  0
             final NumericalValueRange r = (NumericalValueRange) a;
 119  0
             aMin = r.getMin();
 120  0
             aMax = r.getMax();
 121  
         }
 122  0
         if (b instanceof SingleNumericalValue) {
 123  0
             final SingleNumericalValue v = (SingleNumericalValue) b;
 124  0
             bMin = v.getValue();
 125  0
             bMax = bMin;
 126  0
         } else {
 127  0
             final NumericalValueRange r = (NumericalValueRange) b;
 128  0
             bMin = r.getMin();
 129  0
             bMax = r.getMax();
 130  
         }
 131  
         // intersect ranges
 132  0
         final int min = Math.max(aMin, bMin);
 133  0
         final int max = Math.min(aMax, bMax);
 134  0
         if (min == max)
 135  0
             return SingleNumericalValue.create(min);
 136  
         else
 137  0
             return NumericalValueRange.create(min, max);
 138  
     }
 139  
 
 140  
     /**
 141  
      * Returns true if the passed {@link Integer} or {@link NumericalValue} lies completely inside the interval
 142  
      * represented by this {@link NumericalValue} . If the parameter is not an {@link Integer} or a
 143  
      * {@link NumericalValue}, the method will return <code>false</code>.
 144  
      * 
 145  
      * @param value the {@link Integer} or {@link NumericalValue} to check
 146  
      * @return <code>true</code> if the value is complete contained, <code>false</code> if it is not
 147  
      */
 148  
     public abstract boolean contains (Object value);
 149  
 
 150  
     /**
 151  
      * Returns true if the passed integer lies completely inside the interval represented by this {@link NumericalValue}
 152  
      * .
 153  
      * 
 154  
      * @param value the integer to check
 155  
      * @return <code>true</code> if the value is complete contained, <code>false</code> if it is not
 156  
      */
 157  
     public abstract boolean contains (int value);
 158  
 }