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

org.usergrid.utils.UUIDUtils Maven / Gradle / Ivy

There is a newer version: 0.0.27.1
Show newest version
/*******************************************************************************
 * Copyright 2012 Apigee Corporation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package org.usergrid.utils;

import static com.fasterxml.uuid.impl.UUIDUtil.BYTE_OFFSET_CLOCK_HI;
import static com.fasterxml.uuid.impl.UUIDUtil.BYTE_OFFSET_CLOCK_LO;
import static com.fasterxml.uuid.impl.UUIDUtil.BYTE_OFFSET_CLOCK_MID;
import static com.fasterxml.uuid.impl.UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE;
import static org.apache.commons.codec.binary.Base64.decodeBase64;
import static org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString;
import static org.usergrid.utils.ConversionUtils.bytes;
import static org.usergrid.utils.ConversionUtils.uuid;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import com.fasterxml.uuid.EthernetAddress;
import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.UUIDComparator;
import com.fasterxml.uuid.impl.TimeBasedGenerator;

/**
 * @author edanuff
 * 
 */
public class UUIDUtils {

	public static final UUID MIN_TIME_UUID = UUID
			.fromString("00000000-0000-1000-8000-000000000000");

	public static final UUID MAX_TIME_UUID = UUID
			.fromString("ffffffff-ffff-1fff-bfff-ffffffffffff");

	public static final TimeBasedGenerator generator = Generators
			.timeBasedGenerator(EthernetAddress.fromInterface());
	/**
	 * 
	 */
	public static final UUID zeroUUID = new UUID(0, 0);

	/**
	 * @return
	 */
	public static java.util.UUID newTimeUUID() {
		return generator.generate();
	}

	private final static long kClockOffset = 0x01b21dd213814000L;
	private final static long kClockMultiplierL = 10000L;

	private final static Random clockSequenceRandom = new Random();
	private final static Random timeResolutionRandom = new Random();

	// 13 bits of randomness
	private static int getRandomTimeResolution() {
		return timeResolutionRandom.nextInt() & 0x1FFF;
	}

	// 14 bits of randomness
	private static int getRandomClockSequence() {
		return clockSequenceRandom.nextInt() & 0x3FFF;
	}

	private static void setTimestamp(long timestamp, byte[] uuidBytes,
			int clockSeq, int timeOffset) {

		timestamp *= kClockMultiplierL;
		timestamp += kClockOffset;
		timestamp += timeOffset;

		// Set random clock sequence
		uuidBytes[BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
		uuidBytes[BYTE_OFFSET_CLOCK_SEQUENCE + 1] = (byte) clockSeq;

		// Set variant
		uuidBytes[BYTE_OFFSET_CLOCK_SEQUENCE] &= 0x3F;
		uuidBytes[BYTE_OFFSET_CLOCK_SEQUENCE] |= 0x80;

		// Time fields aren't nicely split across the UUID, so can't just
		// linearly dump the stamp:
		int clockHi = (int) (timestamp >>> 32);
		int clockLo = (int) timestamp;

		uuidBytes[BYTE_OFFSET_CLOCK_HI] = (byte) (clockHi >>> 24);
		uuidBytes[BYTE_OFFSET_CLOCK_HI + 1] = (byte) (clockHi >>> 16);
		uuidBytes[BYTE_OFFSET_CLOCK_MID] = (byte) (clockHi >>> 8);
		uuidBytes[BYTE_OFFSET_CLOCK_MID + 1] = (byte) clockHi;

		uuidBytes[BYTE_OFFSET_CLOCK_LO] = (byte) (clockLo >>> 24);
		uuidBytes[BYTE_OFFSET_CLOCK_LO + 1] = (byte) (clockLo >>> 16);
		uuidBytes[BYTE_OFFSET_CLOCK_LO + 2] = (byte) (clockLo >>> 8);
		uuidBytes[BYTE_OFFSET_CLOCK_LO + 3] = (byte) clockLo;

		// Set version
		uuidBytes[BYTE_OFFSET_CLOCK_HI] &= 0x0F;
		uuidBytes[BYTE_OFFSET_CLOCK_HI] |= 0x10;

	}

	public static UUID newTimeUUID(long ts) {
		if (ts == 0) {
			return newTimeUUID();
		}

		byte[] uuidBytes = new byte[16];
		// 47 bits of randomness
		EthernetAddress eth = EthernetAddress.constructMulticastAddress();
		eth.toByteArray(uuidBytes, 10);
		setTimestamp(ts, uuidBytes, getRandomClockSequence(),
				getRandomTimeResolution());

		return uuid(uuidBytes);
	}

	public static UUID minTimeUUID(long ts) {
		byte[] uuidBytes = new byte[16];
		setTimestamp(ts, uuidBytes, 0, 0);

		return uuid(uuidBytes);
	}

	public static UUID maxTimeUUID(long ts) {
		byte[] uuidBytes = new byte[16];
		uuidBytes[10] = (byte) 0xFF;
		uuidBytes[11] = (byte) 0xFF;
		uuidBytes[12] = (byte) 0xFF;
		uuidBytes[13] = (byte) 0xFF;
		uuidBytes[14] = (byte) 0xFF;
		uuidBytes[15] = (byte) 0xFF;
		setTimestamp(ts, uuidBytes, 0x3FFF, 0x1FFF);

		return uuid(uuidBytes);
	}

	/**
	 * @param uuid
	 * @return
	 */
	public static boolean isTimeBased(UUID uuid) {
		if (uuid == null) {
			return false;
		}
		return uuid.version() == 1;
	}

	public static long getTimestampInMillis(UUID uuid) {
		if (uuid == null) {
			return 0;
		}
		long t = uuid.timestamp();
		long timeMillis = (t - kClockOffset) / kClockMultiplierL;
		return timeMillis;
	}

	public static long getTimestampInMicros(UUID uuid) {
		if (uuid == null) {
			return 0;
		}
		long t = uuid.timestamp();
		long timeMillis = (t - kClockOffset) / 10;
		return timeMillis;
	}

	public static UUID tryGetUUID(String s) {
		if (s == null) {
			return null;
		}
		if (s.length() != 36) {
			return null;
		}
		// 8-4-4-4-12
		// 0-7,8,9-12,13,14-17,18,19-22,23,24-35
		if (s.charAt(8) != '-') {
			return null;
		}
		if (s.charAt(13) != '-') {
			return null;
		}
		if (s.charAt(18) != '-') {
			return null;
		}
		if (s.charAt(23) != '-') {
			return null;
		}
		UUID uuid = null;
		try {
			uuid = UUID.fromString(s);
		} catch (Exception e) {
		}
		return uuid;
	}

	public static boolean isUUID(String s) {
		return tryGetUUID(s) != null;
	}

	public static boolean startsWithUUID(String s) {
		if (s == null) {
			return false;
		}
		if (s.length() < 36) {
			return false;
		}
		return isUUID(s.substring(0, 36));
	}

	public static UUID tryExtractUUID(String s) {
		if (s == null) {
			return null;
		}
		if (s.length() < 36) {
			return null;
		}
		return tryGetUUID(s.substring(0, 36));
	}

	public static UUID tryExtractUUID(String s, int offset) {
		if (s == null) {
			return null;
		}
		if ((s.length() - offset) < 36) {
			return null;
		}
		return tryGetUUID(s.substring(offset, offset + 36));
	}

	public static String toBase64(UUID id) {
		if (id == null) {
			return null;
		}
		return encodeBase64URLSafeString(bytes(id));
	}

	public static UUID fromBase64(String str) {
		if (str == null) {
			return null;
		}
		byte[] bytes = decodeBase64(str);
		if (bytes.length != 16) {
			return null;
		}
		return uuid(bytes);
	}

	public static int compare(UUID u1, UUID u2) {
		return UUIDComparator.staticCompare(u1, u2);
	}

	public static List sort(List uuids) {
		Collections.sort(uuids, new UUIDComparator());
		return uuids;
	}

	public static List sortReversed(List uuids) {
		Collections.sort(uuids, new Comparator() {
			@Override
			public int compare(UUID u1, UUID u2) {
				return UUIDComparator.staticCompare(u2, u1);
			}
		});
		return uuids;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy