View Javadoc

1   package org.jscsi.target.settings;
2   
3   
4   import java.util.regex.Matcher;
5   
6   
7   /**
8    * A {@link NumericalValue} sub-class for representing single integers.
9    * 
10   * @author Andreas Ergenzinger
11   */
12  public final class SingleNumericalValue extends NumericalValue {
13  
14      /**
15       * The represented integer.
16       */
17      private final int value;
18  
19      /**
20       * The constructor.
21       * <p>
22       * This method is private to enforce usage of {@link #create(int)}, similar to the way new
23       * {@link NumericalValueRange} objects are created.
24       * 
25       * @param value the value of the new {@link SingleNumericalValue}
26       */
27      private SingleNumericalValue (final int value) {
28          this.value = value;
29      }
30  
31      /**
32       * Returns the represented value.
33       * 
34       * @return the represented value
35       */
36      public final int getValue () {
37          return value;
38      }
39  
40      /**
41       * Returns a new {@link SingleNumericalValue} with the specified value.
42       * 
43       * @param value the value of the returned {@link SingleNumericalValue}
44       * @return a new {@link SingleNumericalValue}
45       */
46      public static final SingleNumericalValue create (final int value) {
47          return new SingleNumericalValue(value);
48      }
49  
50      /**
51       * Parses a {@link SingleNumericalValue} from a {@link String}. The parameter must contain an integer value in
52       * decimal, hexadecimal, or Base64 format. If it does not, <code>null</code> will be returned.
53       * 
54       * @param value the {@link String} to parse
55       * @return a {@link SingleNumericalValue} with the parsed value or <code>null</code>
56       */
57      public static final SingleNumericalValue parseSingleNumericValue (final String value) {
58          // decimal constant
59          final Matcher decimalMatcher = DECIMAL_CONSTANT_PATTERN.matcher(value);
60          if (decimalMatcher.matches()) return new SingleNumericalValue(parseDecimalConstantString(value));
61          // hex constant
62          final Matcher hexMatcher = HEX_CONSTANT_PATTERN.matcher(value);
63          if (hexMatcher.matches()) return new SingleNumericalValue(parseHexConstantString(value));
64          // base 64 constant
65          final Matcher base64Matcher = BASE_64_CONSTANT_PATTERN.matcher(value);
66          if (base64Matcher.matches()) return new SingleNumericalValue(parseBase64ConstantString(value));
67          // none of the above
68          return null;
69      }
70  
71      /**
72       * Parses an integer value from a {@link String} encoded in decimal format.
73       * <p>
74       * This method does not check the passed {@link String} before parsing, so this method should only be used on string
75       * which are certain to match the required format.
76       * 
77       * @param value a {@link String} containing (only) an integer encoded in decimal format
78       * @return the parsed integer
79       */
80      private static final int parseDecimalConstantString (final String value) {
81          return Integer.valueOf(value);
82      }
83  
84      /**
85       * Parses an integer value from a {@link String} encoded in hexadecimal format.
86       * <p>
87       * This method does not check the passed {@link String} before parsing, so this method should only be used on string
88       * which are certain to match the required format.
89       * 
90       * @param value a {@link String} containing (only) an integer encoded in hexadecimal format
91       * @return the parsed integer
92       */
93      private static final int parseHexConstantString (final String value) {
94          return Integer.parseInt(value.substring(2),// skip "0x" prefix
95                  16);
96      }
97  
98      /**
99       * Parses an integer value from a {@link String} encoded in Base64 format.
100      * <p>
101      * This method does not check the passed {@link String} before parsing, so this method should only be used on string
102      * which are certain to match the required format.
103      * 
104      * @param value a {@link String} containing (only) an integer encoded in Base64 format
105      * @return the parsed integer
106      */
107     private static final int parseBase64ConstantString (final String value) {
108         final String s = value.substring(2);// crop "0b"/"0B" at the beginning
109         final int length = s.length();
110         int result = 0;
111         for (int i = 0; i < length; ++i) {
112             final char c = s.charAt(length - 1 - i);
113             result += base64ValueOf(c) * Math.pow(64, i);
114         }
115         return result;
116     }
117 
118     /**
119      * Returns a character's value in Base64
120      * 
121      * @param c a character that is assigned a value from 0 to 63 in Base64
122      * @throws NumberFormatException if the parameter is not a Base64 character
123      * @return the character's value in Base64
124      */
125     private static final int base64ValueOf (final char c) {
126         if ('A' <= c && c <= 'Z') return c - 'A';
127         if ('a' <= c && c <= 'z') return c - 'a' + 26;
128         if ('0' <= c && c <= '9') return c - '0' + 52;
129         if (c == '+') return 62;
130         if (c == '/') return 63;
131         throw new NumberFormatException();
132     }
133 
134     @Override
135     public final String toString () {
136         return "[" + value + "]";
137     }
138 
139     @Override
140     public boolean contains (Object value) {
141         if (value == null) return false;
142         if (value instanceof SingleNumericalValue) return contains(((SingleNumericalValue) value).getValue());
143         if (value instanceof Integer) return contains((int) ((Integer) value));
144         return false;
145     }
146 
147     @Override
148     public boolean contains (final int value) {
149         if (value == this.value) return true;
150         return false;
151     }
152 }