package io.eguan.utils; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * 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. * #L% */ import java.util.UUID; /** * {@link CharSequence} over the hexa string representation of a UUID. The first char is the hexadecimal representation * of the highest half-byte of the most significant long. The last char is the hexadecimal representation of the lowest * half-byte of the least significant long. * * @author oodrive * @author llambert * */ public final class UuidCharSequence implements CharSequence { /** * Implementation of the subsequence. * * */ private class SubSequence implements CharSequence { private final int start; private final int end; SubSequence(final int start, final int end) { super(); this.start = start; this.end = end; } @Override public final CharSequence subSequence(final int start, final int end) { if (start < 0 || end < 0 || start > end || end > length()) { throw new IndexOutOfBoundsException("start=" + start + ", end=" + end); } return new SubSequence(this.start + start, this.start + end); } @Override public final int length() { return end - start; } @Override public final char charAt(final int index) { if (index < 0 || index >= length()) { throw new IndexOutOfBoundsException("index=" + index); } return UuidCharSequence.this.charAt(start + index); } @Override public final String toString() { return new StringBuilder(length()).append(this).toString(); } } private static final char[] HEX_UPPER_CASE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static final char[] HEX_LOWER_CASE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private final UUID uuid; private final boolean upperCase; /** * Create a new lower-case char sequence over a UUID. * * @param uuid * uuid to parse */ public UuidCharSequence(final UUID uuid) { this(uuid, false); } /** * Create a new char sequence over the given UUID. * * @param uuid * uuid to parse * @param upperCase * <code>true</code> to select upper characters. */ public UuidCharSequence(final UUID uuid, final boolean upperCase) { super(); this.uuid = uuid; this.upperCase = upperCase; } /** * Create a new lower-case char sequence over a UUID. * * @param uuid * uuid to parse */ public <F> UuidCharSequence(final UuidT<F> uuid) { this(uuid.getUuid()); } /** * Create a new char sequence over the given UUID. * * @param uuid * uuid to parse * @param upperCase * <code>true</code> to select upper characters. */ public <F> UuidCharSequence(final UuidT<F> uuid, final boolean upperCase) { this(uuid.getUuid(), upperCase); } @Override public final int length() { return 32; } @Override public final char charAt(final int index) { if (index < 0 || index >= length()) { throw new IndexOutOfBoundsException("index=" + index); } final long value; final int shift; if (index > 15) { value = uuid.getLeastSignificantBits(); shift = (31 - 16 - index) * 4; } else { value = uuid.getMostSignificantBits(); shift = (15 - index) * 4; } final int digit = (int) (value >> shift) & 0xF; return upperCase ? HEX_UPPER_CASE[digit] : HEX_LOWER_CASE[digit]; } @Override public final CharSequence subSequence(final int start, final int end) { if (start < 0 || end < 0 || start > end || end > length()) { throw new IndexOutOfBoundsException("start=" + start + ", end=" + end); } return new SubSequence(start, end); } @Override public final String toString() { return new StringBuilder(32).append(this).toString(); } }