Advertisement
Guest User

Untitled

a guest
Jul 17th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.63 KB | None | 0 0
  1. /**
  2. * A UUID generator that can construct unique IDs in a variety of formats.
  3. *
  4. * A UUID is generated immediately upon instantiation of this class. The UUID can be retrieved in its normal form
  5. * (e.g. f111b8c5-ca2f-4a1a-8d0d-a8dd5f37c05f) or as a shortened web-safe form (e.g. jp64hwPZ-Lh7vY8INQA7ImQPbQE), which
  6. * is constructed by converting the UUID to Base64 and replacing '/' and '+' with '-' and '_', respectively.
  7. */
  8. public class Uuid {
  9.  
  10. private static final String HEX_PREFIX = '0x';
  11. private static final String HEX_ALPHABET = '0123456789abcdef';
  12. private static final String[] HEX_CHARACTERS = HEX_ALPHABET.split('');
  13.  
  14. public static final Integer UUID_V4_LENGTH = 36;
  15. public static final String UUID_V4_REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
  16. public static final String UUID_SHORT_REGEX = '[0-9a-zA-Z-_]{27}';
  17.  
  18.  
  19. // UUID value in its normal form
  20. public final String value { get; private set; }
  21.  
  22. // UUID value in its web-safe short-form
  23. public final String shortValue { get; private set; }
  24.  
  25. /*
  26. * Constructs a new UUID.
  27. */
  28. public Uuid() {
  29. this.value = generate();
  30. this.shortValue = getShortValue(this);
  31. }
  32.  
  33. /*
  34. * Overrides the toString() method to return the formatted UUID value.
  35. * @return Formatted UUID value
  36. */
  37. public override String toString() {
  38. return value;
  39. }
  40.  
  41.  
  42. //==================================================================================================================
  43. // Private
  44. //==================================================================================================================
  45.  
  46. /*
  47. * Generates a UUID string according to the UUID v4 spec.
  48. * @return A newly generated UUID
  49. */
  50. private String generate() {
  51. String hexValue = EncodingUtil.convertToHex(Crypto.generateAesKey(128));
  52.  
  53. // Version Calculation: (i & 0x0f) | 0x40
  54. // Version Format: Always begins with 4
  55. String versionShiftedHexBits = getShiftedHexBits(
  56. hexValue.substring(14, 16),
  57. convertHexToInteger('0x0f'),
  58. convertHexToInteger('0x40')
  59. );
  60.  
  61. // Variant Calculation: (i & 0x3f) | 0x80
  62. // Variant Format: Always begins with 8, 9, A or B
  63. String variantShiftedHexBits = getShiftedHexBits(
  64. hexValue.substring(18, 20),
  65. convertHexToInteger('0x3f'),
  66. convertHexToInteger('0x80')
  67. );
  68.  
  69. String uuid = hexValue.substring(0, 8) // time-low
  70. + '-' + hexValue.substring(8, 12) // time-mid
  71. + '-' + versionShiftedHexBits + hexValue.substring(14, 16) // time-high-and-version
  72. + '-' + variantShiftedHexBits + hexValue.substring(18, 20) // clock-seq-and-reserved + clock-seq-low
  73. + '-' + hexValue.substring(20); // node
  74.  
  75. return uuid;
  76. }
  77.  
  78. private String getShiftedHexBits(String hexSubstring, Integer lowerThreshold, Integer upperThreshold) {
  79. Integer shiftedIntegerBits = (convertHexToInteger(hexSubstring) & lowerThreshold) | upperThreshold;
  80. return convertIntegerToHex(shiftedIntegerBits);
  81. }
  82.  
  83. /*
  84. * Converts a given hexadecimal string to an integer value.
  85. * @param hexValue {String} Value to be converted
  86. * @return Integer equivalent to the given string
  87. */
  88. private Integer convertHexToInteger(String hexValue) {
  89. Integer hexBase = HEX_ALPHABET.length();
  90. hexValue = hexValue.toLowerCase();
  91.  
  92. if (hexValue.startsWith(HEX_PREFIX)) {
  93. hexValue = hexValue.substringAfter(HEX_PREFIX);
  94. }
  95.  
  96. Integer integerValue = 0;
  97. for (String hexCharacter : hexValue.split('')) {
  98. Integer hexCharacterIndex = HEX_CHARACTERS.indexOf(hexCharacter);
  99.  
  100. integerValue = hexBase * integerValue + hexCharacterIndex;
  101. }
  102. return integerValue;
  103. }
  104.  
  105. /*
  106. * Converts a given integer to a hexadecimal string.
  107. * @param integerValue {Integer} Value to be converted
  108. * @return Hexadecimal equivalent to the given integer
  109. */
  110. private String convertIntegerToHex(Integer integerValue) {
  111. Integer hexBase = HEX_ALPHABET.length();
  112. String hexValue = '';
  113. while (integerValue > 0) {
  114. Integer hexCharacterIndex = Math.mod(integerValue, hexBase);
  115.  
  116. hexValue = HEX_CHARACTERS[hexCharacterIndex] + hexValue;
  117. integerValue = integerValue / hexBase;
  118. }
  119. return hexValue;
  120. }
  121.  
  122.  
  123. //==================================================================================================================
  124. // Static
  125. //==================================================================================================================
  126.  
  127. /*
  128. * Determines whether a given string is a valid UUID.
  129. * @param uuid {String} A UUID string
  130. * @return True if the given string represents a valid UUID; false otherwise
  131. */
  132. public static Boolean validate(String uuid) {
  133.  
  134. // Should not be an empty string
  135. if (String.isBlank(uuid)) {
  136. return false;
  137. }
  138.  
  139. // Should be of appropriate length
  140. if (uuid.length() != UUID_V4_LENGTH) {
  141. return false;
  142. }
  143.  
  144. // Should match UUID regex
  145. Pattern uuidPattern = Pattern.compile(UUID_V4_REGEX.toLowerCase());
  146. Matcher uuidMatcher = uuidPattern.matcher(uuid.toLowerCase());
  147. return !!uuidMatcher.matches();
  148. }
  149.  
  150. /*
  151. * Generates a hashed and base64-encoded representation of the UUID, with '/' and '+' characters will be replaced by '-'
  152. * and '_', respectively, to avoid compatibility issues.
  153. * @param A UUID to convert
  154. * @return UUID value encoded as a base64 string
  155. */
  156. public static String getShortValue(Uuid uuid) {
  157.  
  158. // Remove hyphens
  159. String value = uuid.value.replace('-', '');
  160.  
  161. // Hash the UUID and convert to a base-64 string and replace '/' and '+'
  162. Blob digest = Crypto.generateDigest('SHA1', Blob.valueOf(value));
  163. String encoded = EncodingUtil.base64Encode(digest);
  164.  
  165. // Drop trailing '=' and replace '/' and '+'
  166. return encoded.substring(0, encoded.length() - 1)
  167. .replace('/', '-')
  168. .replace('+', '_');
  169. }
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement