All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.weaverplatform.util.Cuid Maven / Gradle / Ivy

There is a newer version: 3.27.0
Show newest version
package com.weaverplatform.util;
// copied from https://github.com/graphcool/cuid-java/blob/master/src/main/java/cool/graph/cuid/Cuid.java

import java.lang.management.ManagementFactory;
import java.util.Date;
import java.util.regex.Pattern;

/**
 * Generates collision-resistant unique ids.
 */
public class Cuid {
  private static final int BASE = 36;
  private static final int LENGTH = 25;
  private static final int BLOCK_SIZE = 4;
  private static final int DISCRETE_VALUES = (int) Math.pow(BASE, BLOCK_SIZE);
  private static final String LETTER = "c";

  private static final String FINGERPRINT;

  private static Pattern PATTERN = Pattern.compile("[^A-Za-z0-9]");

  static {
    FINGERPRINT = getFingerprint();
  }

  private static int counter = 0;

  private static String getHostInfo(String idFallback, String nameFallback) {
    String jvmName = ManagementFactory.getRuntimeMXBean().getName();
    final int index = jvmName.indexOf('@');
    if (index < 1) {
      return String.format("%s@%s", idFallback, nameFallback);
    }

    return jvmName;
  }

  private static String getFingerprint() {
    String hostInfo = getHostInfo(Long.toString(new Date().getTime()), "dummy-host");

    String hostId = hostInfo.split("@")[0];
    String hostname = hostInfo.split("@")[1];

    int acc = hostname.length() + BASE;
    for (int i = 0; i < hostname.length(); i++) {
      acc += acc + (int) hostname.charAt(i);
    }

    String idBlock = pad(Long.toString(Long.parseLong(hostId), BASE), 2);
    String nameBlock = pad(Integer.toString(acc), 2);

    return idBlock + nameBlock;
  }

  private static String pad(String input, int size) {
    // courtesy of http://stackoverflow.com/a/4903603/1176596
    String repeatedZero = new String(new char[size]).replace("\0", "0");
    String padded = repeatedZero + input;
    return (padded).substring(padded.length() - size);
  }

  public static String getRandomBlock() {
    return pad(Integer.toString((int) (Math.random() * DISCRETE_VALUES), BASE), BLOCK_SIZE);
  }

  private static int safeCounter() {
    counter = counter < DISCRETE_VALUES ? counter : 0;
    return counter++;
  }

  /**
   * Generates collision-resistant unique ids.
   *
   * @return a collision-resistant unique id
   */
  public static String createCuid() {
    String timestamp = Long.toString(new Date().getTime(), BASE);
    String counter = pad(Integer.toString(safeCounter(), BASE), BLOCK_SIZE);
    String random = getRandomBlock() + getRandomBlock();

    return LETTER + timestamp + counter + FINGERPRINT + random;
  }

  /**
   *  Validates a cuid
   *
   * @param cuid
   * @return true if it's a valid cuid or false if it's not
   */
  public static boolean validate(String cuid) {
    return (null != cuid) && (cuid.length() == LENGTH && cuid.substring(0, 1).equals(LETTER)) && hasNotSpecialChars(cuid);
  }

  private static boolean hasNotSpecialChars(String cuid) {
    return !PATTERN.matcher(cuid).find();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy