jnr.constants.ConstantSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jnr-constants Show documentation
Show all versions of jnr-constants Show documentation
A set of platform constants (e.g. errno values)
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jnr.constants;
import java.lang.reflect.Field;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Provides forward and reverse lookup for platform constants
*/
public class ConstantSet extends AbstractSet {
private final ConcurrentMap nameToConstant;
private final ConcurrentMap valueToConstant;
private final Set constants;
private final Class enumClass;
private volatile Long minValue;
private volatile Long maxValue;
private static final ConcurrentMap constantSets
= new ConcurrentHashMap();
private static final Object lock = new Object();
/**
* Gets a ConstantSet
*
* @param name The name of the constant set to get.
* @return A ConstantSet.
*/
public static ConstantSet getConstantSet(String name) {
ConstantSet constants = constantSets.get(name);
if (constants == null) {
synchronized (lock) {
if (!constantSets.containsKey(name)) {
Class enumClass = getEnumClass(name);
if (enumClass == null) {
return null;
}
if (!Constant.class.isAssignableFrom(enumClass)) {
throw new ClassCastException("class for " + name
+ " does not implement Constant interface");
}
constants = new ConstantSet(enumClass);
constantSets.put(name, constants);
}
}
}
return constants;
}
/**
* Gets the {@link Enum} class for the constant name space.
*
* @param name The name of the constants to locate.
* @return A Class.
*/
@SuppressWarnings("unchecked")
private static final Class getEnumClass(String name) {
String[] prefixes = {
Platform.getPlatform().getPackageName(),
Platform.getPlatform().getOSPackageName(),
Platform.class.getPackage().getName() + ".platform.fake",
};
for (String prefix : prefixes) {
try {
return (Class) Class.forName(prefix + "." + name).asSubclass(Enum.class);
} catch (ClassNotFoundException ex) {
}
}
return null;
}
/**
* Creates a new instance of ConstantSet
*
* @param enumClass The Enum subclass to load constants from.
*/
@SuppressWarnings("unchecked")
private ConstantSet(Class enumClass) {
this.enumClass = enumClass;
nameToConstant = new ConcurrentHashMap();
valueToConstant = new ConcurrentHashMap();
constants = (Set) EnumSet.allOf(enumClass);
}
/**
* Gets the constant for a name.
*
* @param name The name of the system constant (e.g. "EINVAL").
* @return A {@link Constant} instance.
*/
@SuppressWarnings("unchecked")
public Constant getConstant(String name) {
Constant c = nameToConstant.get(name);
if (c == null) {
try {
nameToConstant.put(name, c = Constant.class.cast(Enum.valueOf(enumClass, name)));
} catch (IllegalArgumentException ex) {
return null;
}
}
return c;
}
/**
* Gets the constant for a name.
*
* @param name The name of the system constant (e.g. "EINVAL").
* @return A {@link Constant} instance.
*/
@SuppressWarnings("unchecked")
public Constant getConstant(long value) {
Constant c = valueToConstant.get(value);
if (c == null) {
if (c == null) {
for (Constant c2 : constants) {
if (c2.longValue() == value) {
c = c2;
break;
}
}
if (c != null) {
valueToConstant.put(value, c);
}
}
}
return c;
}
/**
* Gets the integer value of a platform constant.
*
* @param name The name of the platform constant to look up (e.g. "EINVAL").
* @return The integer value of the constant.
*/
public long getValue(String name) {
Constant c = getConstant(name);
return c != null ? c.longValue() : 0;
}
/**
* Gets the name of a platform constant value.
*
* @param value The integer value to look up.
* @return The name of the constant.
*/
public String getName(int value) {
Constant c = getConstant(value);
return c != null ? c.name() : "unknown";
}
private Long getLongField(String name, long defaultValue) {
try {
Field f = enumClass.getField("MIN_VALUE");
return (Long) f.get(enumClass);
} catch (NoSuchFieldException ex) {
return defaultValue;
} catch (RuntimeException ex) {
throw ex;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public long minValue() {
if (minValue == null) {
minValue = getLongField("MIN_VALUE", Integer.MIN_VALUE);
}
return minValue.intValue();
}
public long maxValue() {
if (maxValue == null) {
maxValue = getLongField("MAX_VALUE", Integer.MAX_VALUE);
}
return maxValue.intValue();
}
private final class ConstantIterator implements Iterator {
private final Iterator it;
ConstantIterator(Collection constants) {
this.it = constants.iterator();
}
public boolean hasNext() {
return it.hasNext();
}
public void remove() {
throw new UnsupportedOperationException();
}
public Constant next() {
return it.next();
}
}
@Override
public Iterator iterator() {
return new ConstantIterator(constants);
}
@Override
public int size() {
return constants.size();
}
@Override
public boolean contains(Object o) {
return o != null && o.getClass().equals(enumClass);
}
}