
cdc.enums.EnumType Maven / Gradle / Ivy
package cdc.enums;
import java.util.Comparator;
import java.util.Objects;
import cdc.util.lang.FailureReaction;
import cdc.util.lang.NotFoundException;
/**
* Interface describing an enumerated type.
*
* This can be used for standard enums but also for other kinds of enums.
*
* The semantic is more general than standard enums' semantic.
* Standard enums are flat. Here, values can have set inclusion semantic:
* An enum can be considered as a set of other enums.
* There is a partial or total order relation between values, depending on the implementation.
*
* Values can be created, removed, renamed, etc. at runtime, depending on implementation and enabled features.
*
* @author Damien Carbonne
*
* @param The enum value type.
*/
public interface EnumType extends DagType {
/**
* Returns the child that has a name.
*
* @param value The value.
* @param name The name.
* @return The child of [@code value} that has is named {@code name} or {@code null}.
*/
public default V getChildNamed(V value,
String name) {
for (final V child : getChildren(value)) {
if (Objects.equals(getName(child), name)) {
return child;
}
}
return null;
}
/**
* Returns {@code true} when a value has a child that has a given name.
*
* @param value The value.
* @param name The name.
* @return {@code true} when {@code value} has a child named {@code name}.
*/
public default boolean hasChildNamed(V value,
String name) {
return getChildNamed(value, name) != null;
}
/**
* Returns {@code true} when a value has a sibling (different from itself) that has a given name.
*
* @param value The value.
* @param name The sibling name.
* @return {@code true} when {@code value} has a sibling (other than {@code value}) that is named {@code name}.
*/
public default boolean hasSiblingNamed(V value,
String name) {
if (isRoot(value)) {
for (final V root : getRoots()) {
if (root != value && Objects.equals(getName(root), name)) {
return true;
}
}
return false;
} else {
for (final V parent : getParents(value)) {
final V matching = getChildNamed(parent, name);
if (matching != null && matching != value) {
return true;
}
}
return false;
}
}
/**
* Returns the name of a value.
*
* @param value The value.
* @return The name associated to {@code value} or {@code null}.
*/
public String getName(V value);
/**
* Returns the (preferred) qualified name (path) of a value.
*
* @param value The value.
* @return The qualified name (path) of {@code value} or {@code null}.
*/
public String getQName(V value);
/**
* Returns the value corresponding to a qualified name.
*
* @param qname The qualified name.
* @param reaction The reaction to adopt when {@code qname} is unknown.
* @return The value corresponding to {@code qname} or {@code null}.
* @throws NotFoundException When {@code qname} is unknown and {@code reaction} is {@link FailureReaction#FAIL}.
*/
public V valueOf(String qname,
FailureReaction reaction);
/**
* Returns the value associated to a qualified name (path).
*
* Notes
* Depending on implementation, several qualified names can correspond to the same value.
*
* @param qname The qualified name (path).
* @return The value associated to {@code qname}.
* @throws NotFoundException When {@code qname} is unknown.
*/
public default V valueOf(String qname) {
return valueOf(qname, FailureReaction.FAIL);
}
/**
* Returns {@code true} if a value with a qualified name is registered.
*
* @param qname The qualified name (path).
* @return {@code true} if a value with is registered under {@code qname}.
*/
public default boolean hasValue(String qname) {
return valueOf(qname, FailureReaction.DEFAULT) != null;
}
static String unknownQName(String qname) {
return "Unknown qname '" + qname + "'";
}
/**
* Creates a qualified name comparator.
*
* @param The enum value type.
* @param enumType The enum type.
* @return A comparator based on qualified names.
*/
public static Comparator createQNameComparator(EnumType enumType) {
return (o1,
o2) -> {
if (o1 == o2) {
return 0;
} else if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
} else {
return enumType.getQName(o1).compareTo(enumType.getQName(o2));
}
};
}
}