]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.datatypes/src/org/simantics/datatypes/literal/GUID.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.datatypes / src / org / simantics / datatypes / literal / GUID.java
diff --git a/bundles/org.simantics.datatypes/src/org/simantics/datatypes/literal/GUID.java b/bundles/org.simantics.datatypes/src/org/simantics/datatypes/literal/GUID.java
new file mode 100644 (file)
index 0000000..b4f9b02
--- /dev/null
@@ -0,0 +1,167 @@
+package org.simantics.datatypes.literal;\r
+\r
+import java.util.UUID;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.util.Bean;\r
+\r
+\r
+public class GUID extends Bean {\r
+\r
+       public static final Binding BINDING = Bindings.getBindingUnchecked(GUID.class);\r
+\r
+       public long mostSignificant;\r
+       public long leastSignificant;\r
+       \r
+       public GUID(long mostSignificant, long leastSignificant) {\r
+               super(BINDING);\r
+               this.mostSignificant = mostSignificant;\r
+               this.leastSignificant = leastSignificant;\r
+       }\r
+       \r
+       public static GUID invalid() {\r
+               return new GUID(0, 0);\r
+       }\r
+       \r
+       public static GUID invalid2() {\r
+               return new GUID(0, 1);\r
+       }\r
+\r
+       public boolean isInvalid() {\r
+               return mostSignificant == 0 && leastSignificant == 0;\r
+       }\r
+\r
+       public static GUID random() {\r
+               UUID random = UUID.randomUUID();\r
+               return new GUID(random.getMostSignificantBits(), random.getLeastSignificantBits());\r
+       }\r
+       \r
+       public String indexString() {\r
+               StringBuilder b = new StringBuilder();\r
+               b.append(Long.toHexString(mostSignificant));\r
+               b.append("_");\r
+               b.append(Long.toHexString(leastSignificant));\r
+               return b.toString();\r
+       }\r
+       \r
+       public static GUID parseIndexString(String indexString) {\r
+               String[] parts = indexString.split("_");\r
+               if(parts.length != 2) throw new IllegalArgumentException();\r
+               Long mostSignificant = parseUnsignedLong(parts[0].toUpperCase(), 16);\r
+               Long leastSignificant = parseUnsignedLong(parts[1], 16);\r
+               return new GUID(mostSignificant, leastSignificant);\r
+       }\r
+\r
+    /**\r
+     * Parses the string argument as an unsigned {@code long} in the\r
+     * radix specified by the second argument.  An unsigned integer\r
+     * maps the values usually associated with negative numbers to\r
+     * positive numbers larger than {@code MAX_VALUE}.\r
+     *\r
+     * The characters in the string must all be digits of the\r
+     * specified radix (as determined by whether {@link\r
+     * java.lang.Character#digit(char, int)} returns a nonnegative\r
+     * value), except that the first character may be an ASCII plus\r
+     * sign {@code '+'} ({@code '\u005Cu002B'}). The resulting\r
+     * integer value is returned.\r
+     *\r
+     * <p>An exception of type {@code NumberFormatException} is\r
+     * thrown if any of the following situations occurs:\r
+     * <ul>\r
+     * <li>The first argument is {@code null} or is a string of\r
+     * length zero.\r
+     *\r
+     * <li>The radix is either smaller than\r
+     * {@link java.lang.Character#MIN_RADIX} or\r
+     * larger than {@link java.lang.Character#MAX_RADIX}.\r
+     *\r
+     * <li>Any character of the string is not a digit of the specified\r
+     * radix, except that the first character may be a plus sign\r
+     * {@code '+'} ({@code '\u005Cu002B'}) provided that the\r
+     * string is longer than length 1.\r
+     *\r
+     * <li>The value represented by the string is larger than the\r
+     * largest unsigned {@code long}, 2<sup>64</sup>-1.\r
+     *\r
+     * </ul>\r
+     *\r
+     *\r
+     * @param      s   the {@code String} containing the unsigned integer\r
+     *                  representation to be parsed\r
+     * @param      radix   the radix to be used while parsing {@code s}.\r
+     * @return     the unsigned {@code long} represented by the string\r
+     *             argument in the specified radix.\r
+     * @throws     NumberFormatException if the {@code String}\r
+     *             does not contain a parsable {@code long}.\r
+     * @since 1.8\r
+     */\r
+    public static long parseUnsignedLong(String s, int radix)\r
+                throws NumberFormatException {\r
+        if (s == null)  {\r
+            throw new NumberFormatException("null");\r
+        }\r
+\r
+        int len = s.length();\r
+        if (len > 0) {\r
+            char firstChar = s.charAt(0);\r
+            if (firstChar == '-') {\r
+                throw new\r
+                    NumberFormatException(String.format("Illegal leading minus sign " +\r
+                                                       "on unsigned string %s.", s));\r
+            } else {\r
+                if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits\r
+                    (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits\r
+                    return Long.parseLong(s, radix);\r
+                }\r
+\r
+                // No need for range checks on len due to testing above.\r
+                long first = Long.parseLong(s.substring(0, len - 1), radix);\r
+                int second = Character.digit(s.charAt(len - 1), radix);\r
+                if (second < 0) {\r
+                    throw new NumberFormatException("Bad digit at end of " + s);\r
+                }\r
+                long result = first * radix + second;\r
+                if (compareUnsigned(result, first) < 0) {\r
+                    /*\r
+                     * The maximum unsigned value, (2^64)-1, takes at\r
+                     * most one more digit to represent than the\r
+                     * maximum signed value, (2^63)-1.  Therefore,\r
+                     * parsing (len - 1) digits will be appropriately\r
+                     * in-range of the signed parsing.  In other\r
+                     * words, if parsing (len -1) digits overflows\r
+                     * signed parsing, parsing len digits will\r
+                     * certainly overflow unsigned parsing.\r
+                     *\r
+                     * The compareUnsigned check above catches\r
+                     * situations where an unsigned overflow occurs\r
+                     * incorporating the contribution of the final\r
+                     * digit.\r
+                     */\r
+                    throw new NumberFormatException(String.format("String value %s exceeds " +\r
+                                                                  "range of unsigned long.", s));\r
+                }\r
+                return result;\r
+            }\r
+        } else {\r
+            throw new NumberFormatException("For input string: \"" + s + "\"");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Compares two {@code long} values numerically treating the values\r
+     * as unsigned.\r
+     *\r
+     * @param  x the first {@code long} to compare\r
+     * @param  y the second {@code long} to compare\r
+     * @return the value {@code 0} if {@code x == y}; a value less\r
+     *         than {@code 0} if {@code x < y} as unsigned values; and\r
+     *         a value greater than {@code 0} if {@code x > y} as\r
+     *         unsigned values\r
+     * @since 1.8\r
+     */\r
+    public static int compareUnsigned(long x, long y) {\r
+        return Long.compare(x + Long.MIN_VALUE, y + Long.MIN_VALUE);\r
+    }\r
+    \r
+}\r