de.unkrig.commons.util.Enums Maven / Gradle / Ivy
/*
* de.unkrig.commons - A general-purpose Java class library
*
* Copyright (c) 2016, Arno Unkrig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.unkrig.commons.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import de.unkrig.commons.nullanalysis.Nullable;
/**
* Various enum-related utility methods.
*/
public final
class Enums {
private Enums() {}
/**
* @return The ordinals of all members of the enumSet
*/
public static Collection
ordinals(Collection extends Enum>> enumSet) {
Collection result = new ArrayList();
for (Enum> e : enumSet) result.add(e.ordinal());
return result;
}
/**
* Creates an {@link EnumSet} from the given string. The string must have one of the following formats:
*
* -
* (Empty)
*
* '[]'
*
* - Empty enum set
*
* enum-constant
* - Enum set with one element
*
* '[' enum-constant { ',' enum-constant } ']'
* - Enum set with one or more elements
*
*
* enum-constant := java-identifier-start { java-identifier-part }
*
* @return A (mutable) {@link EnumSet}
*/
public static > EnumSet
enumSetFromString(String s, Class elementType) {
int i = 0;
i = Enums.skipWhitespace(s, i);
if (i == s.length()) return EnumSet.noneOf(elementType); // Empty string => empty set
if (s.charAt(i) != '[') return EnumSet.of(Enums.valueOf(s, elementType));
i = Enums.skipWhitespace(s, i + 1);
if (s.charAt(i) == ']') {
// '[]' => empty set
i = Enums.skipWhitespace(s, i + 1);
if (i < s.length()) throw new IllegalArgumentException("Trailing garbage");
return EnumSet.noneOf(elementType);
}
// Now let's parse
// enum-constant { ',' enum-constant } ']' end-of-input
for (EnumSet result = EnumSet.noneOf(elementType);;) {
{
int j = Enums.scanIdentifier(s, i);
result.add(Enums.valueOf(s.substring(i, j), elementType));
i = Enums.skipWhitespace(s, j);
}
if (i == s.length()) throw new IllegalArgumentException("Unexpected end-of-input");
char c = s.charAt(i);
if (c == ']') {
i = Enums.skipWhitespace(s, i + 1);
if (i < s.length()) throw new IllegalArgumentException("Trailing garbage");
return result;
}
if (c != ',') throw new IllegalArgumentException("Unexpected character '" + c + "'");
i = Enums.skipWhitespace(s, i + 1);
}
}
/**
* Verifies that the character at position index is a valid Java identifier start character, and
* returns the position of the first non-Java identifier part character after the first char.
*
* @throws IllegalArgumentException index {@code ==} s{@code .length()}
* @throws IllegalArgumentException The character at position index is not a valid Java identifier start
* character
*/
private static int
scanIdentifier(String s, int index) {
if (index == s.length()) throw new IllegalArgumentException("Uxpected end-of-input");
if (!Character.isJavaIdentifierStart(s.charAt(index))) {
throw new IllegalArgumentException("Identifier expected");
}
for (index++; index < s.length() && Character.isJavaIdentifierPart(s.charAt(index)); index++);
return index;
}
private static int
skipWhitespace(String s, int index) {
while (index < s.length() && Character.isWhitespace(s.charAt(index))) index++;
return index;
}
/**
* Returns the enum constant of the enumType with the specified name. The string must match
* exactly the identifier used to declare the enum constant in this type. Extraneous whitespace characters are not
* permitted.
*
* @return The enum constant with the specified name
* @throws IllegalArgumentException The enumType has no constant with the specified name
*/
public static > E
valueOf(String name, Class enumType) {
for (E e : Enums.getEnumConstants(enumType)) {
if (name.equals(e.name())) return e;
}
throw new IllegalArgumentException(name);
}
/**
* Identical with {@link Class#getEnumConstants()}, but caches its result.
*/
private static > E[]
getEnumConstants(Class enumType) {
// Look up the cache.
{
Enum>[] cache = Enums.cache;
if (cache != null && cache[0].getClass() == enumType) {
@SuppressWarnings("unchecked") E[] result = (E[]) cache;
return result;
}
}
// Cache miss; call "Class.getEnumConstants()".
E[] result = enumType.getEnumConstants();
if (result.length > 0) Enums.cache = result; // Cannot cache zero-constant enums.
return result;
}
@Nullable private static Enum>[] cache;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy