(java) FlagGraph base class and tests
This commit is contained in:
@@ -5,18 +5,19 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* Represents a single flag defined in a {@link FlagGraph}.
|
* Represents a single flag defined in a {@link FlagGraph}.
|
||||||
*
|
*
|
||||||
|
* @param <V> The type of the flag's value.
|
||||||
* @param <S> A set of this type of flags.
|
* @param <S> A set of this type of flags.
|
||||||
*/
|
*/
|
||||||
public interface FlagDefinition<S> {
|
public interface FlagDefinition<V, S> {
|
||||||
/**
|
/**
|
||||||
* The alias of the flag.
|
* The alias of the flag. A composed flag always has an alias.
|
||||||
*/
|
*/
|
||||||
Optional<String> getAlias();
|
Optional<String> alias();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set containing the value of the flag, or multiple values if it is a composed flag.
|
* The value of the flag. A composed flag has no value.
|
||||||
*/
|
*/
|
||||||
S values();
|
Optional<V> value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if this flag and all its parents are present in the set.
|
* Test if this flag and all its parents are present in the set.
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package fr.louisdevie.tatsuki;
|
package fr.louisdevie.tatsuki;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.lang.reflect.Array;
|
||||||
import java.util.Optional;
|
import java.util.*;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a group of flags of type {@link V} and the relationships between
|
* Represents a group of flags of type {@link V} and the relationships between
|
||||||
@@ -11,71 +10,128 @@ import java.util.Set;
|
|||||||
* @param <V> The type of the flag values.
|
* @param <V> The type of the flag values.
|
||||||
* @param <S> The type used to contain the flags.
|
* @param <S> The type used to contain the flags.
|
||||||
*/
|
*/
|
||||||
public interface FlagGraph<V, S> {
|
public abstract class FlagGraph<V, S> {
|
||||||
|
private final HashMap<V, FlagDefinition<V, S>> definitionsByValue;
|
||||||
|
private final HashMap<String, FlagDefinition<V, S>> definitionsByAlias;
|
||||||
|
|
||||||
|
protected FlagGraph(Collection<? extends FlagDefinition<V, S>> c) {
|
||||||
|
this.definitionsByValue = new HashMap<>();
|
||||||
|
this.definitionsByAlias = new HashMap<>();
|
||||||
|
|
||||||
|
for (var definition : c) {
|
||||||
|
if (definition.value().isPresent()) {
|
||||||
|
V value = definition.value().get();
|
||||||
|
if (this.definitionsByValue.put(value, definition) != null) {
|
||||||
|
throw new IllegalArgumentException(String.format("Duplicate value \"%s\"", value));
|
||||||
|
}
|
||||||
|
if (definition.alias().isPresent()) {
|
||||||
|
String alias = definition.alias().get();
|
||||||
|
if (this.definitionsByAlias.put(alias, definition) != null) {
|
||||||
|
throw new IllegalArgumentException(String.format("Duplicate alias \"%s\"", alias));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String alias = definition.alias().orElseThrow(() ->
|
||||||
|
new IllegalArgumentException("Invalid flag definition: a composed flag must always have an alias")
|
||||||
|
);
|
||||||
|
if (this.definitionsByAlias.put(alias, definition) != null) {
|
||||||
|
throw new IllegalArgumentException(String.format("Duplicate alias \"%s\"", alias));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of definitions in this graph.
|
* Returns the number of definitions in this graph.
|
||||||
*/
|
*/
|
||||||
int size();
|
public int size() {
|
||||||
|
return this.definitionsByValue.size() +
|
||||||
|
(int) this.definitionsByAlias.values().stream()
|
||||||
|
.filter(d -> d.value().isEmpty())
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if this graph contains no definitions.
|
* Returns {@code true} if this graph contains no definitions.
|
||||||
*/
|
*/
|
||||||
boolean isEmpty();
|
public boolean isEmpty() {
|
||||||
|
return this.definitionsByValue.isEmpty() && this.definitionsByAlias.isEmpty();
|
||||||
/**
|
}
|
||||||
* Returns {@code true} if this graph contains a definition with the specified alias.
|
|
||||||
*/
|
|
||||||
boolean containsAlias(String alias);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if this graph contains a definition with the specified value.
|
* Returns {@code true} if this graph contains a definition with the specified value.
|
||||||
*/
|
*/
|
||||||
boolean containsValue(V value);
|
public boolean containsValue(V value) {
|
||||||
|
return this.definitionsByValue.containsKey(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if this graph contains a definition with the specified alias.
|
||||||
|
*/
|
||||||
|
public boolean containsAlias(String alias) {
|
||||||
|
return this.definitionsByAlias.containsKey(alias);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the specified definition belongs to this graph.
|
* Returns {@code true} if the specified definition belongs to this graph.
|
||||||
*/
|
*/
|
||||||
boolean containsDefinition(FlagDefinition<S> definition);
|
public boolean containsDefinition(FlagDefinition<V, S> definition) {
|
||||||
|
return this.definitionsByValue.containsValue(definition) || this.definitionsByAlias.containsValue(definition);
|
||||||
/**
|
}
|
||||||
* Returns the flag definition with the specified alias.
|
|
||||||
*
|
|
||||||
* @param alias The alias of the flag.
|
|
||||||
*
|
|
||||||
* @return An {@link Optional} of the corresponding definition, or an empty
|
|
||||||
* {@link Optional} if there is no definition with this alias.
|
|
||||||
*/
|
|
||||||
Optional<FlagDefinition<S>> definitionNamed(String alias);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the flag definition with the specified value.
|
* Returns the flag definition with the specified value.
|
||||||
*
|
*
|
||||||
* @param value The base value of the flag.
|
* @param value The base value of the flag.
|
||||||
*
|
|
||||||
* @return An {@link Optional} of the corresponding definition, or an empty
|
* @return An {@link Optional} of the corresponding definition, or an empty
|
||||||
* {@link Optional} if there is no definition with this value.
|
* {@link Optional} if there is no definition with this value.
|
||||||
*/
|
*/
|
||||||
Optional<FlagDefinition<S>> definitionOf(V value);
|
public Optional<FlagDefinition<V, S>> definitionOf(V value) {
|
||||||
|
return Optional.ofNullable(this.definitionsByValue.get(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the flag definition with the specified alias.
|
||||||
|
*
|
||||||
|
* @param alias The alias of the flag.
|
||||||
|
* @return An {@link Optional} of the corresponding definition, or an empty
|
||||||
|
* {@link Optional} if there is no definition with this alias.
|
||||||
|
*/
|
||||||
|
public Optional<FlagDefinition<V, S>> definitionNamed(String alias) {
|
||||||
|
return Optional.ofNullable(this.definitionsByAlias.get(alias));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Set} view of the aliases defined in this graph.
|
* Returns a {@link Set} view of the aliases defined in this graph.
|
||||||
*/
|
*/
|
||||||
Set<String> aliasSet();
|
public Set<String> aliasSet() {
|
||||||
|
return new ReadOnlyKeySet<>(this.definitionsByAlias);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Set} view of the values defined in this graph.
|
* Returns a {@link Set} view of the values defined in this graph.
|
||||||
*/
|
*/
|
||||||
Set<V> valueSet();
|
public Set<V> valueSet() {
|
||||||
|
return new ReadOnlyKeySet<>(this.definitionsByValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all the defined flags.
|
* Returns a {@link Set} view of all the defined flags.
|
||||||
*/
|
*/
|
||||||
Collection<FlagDefinition<S>> definitions();
|
public Set<FlagDefinition<V, S>> definitions() {
|
||||||
|
return new DefinitionSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a set of flags from a list of values.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public abstract S of(V... values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a set of flags from a list of aliases.
|
* Creates a set of flags from a list of aliases.
|
||||||
*/
|
*/
|
||||||
S named(String... aliases);
|
public abstract S named(String... aliases);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the first set of flags includes at least one of the flags
|
* Checks whether the first set of flags includes at least one of the flags
|
||||||
@@ -86,7 +142,7 @@ public interface FlagGraph<V, S> {
|
|||||||
* @param flags - A set of flags.
|
* @param flags - A set of flags.
|
||||||
* @param required - The flags to search for in the first set.
|
* @param required - The flags to search for in the first set.
|
||||||
*/
|
*/
|
||||||
boolean hasAny(S flags, S required);
|
public abstract boolean hasAny(S flags, S required);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the first set of flags includes all the flags from the
|
* Checks whether the first set of flags includes all the flags from the
|
||||||
@@ -97,7 +153,7 @@ public interface FlagGraph<V, S> {
|
|||||||
* @param flags - A set of flags.
|
* @param flags - A set of flags.
|
||||||
* @param required - The flags to search for in the first set.
|
* @param required - The flags to search for in the first set.
|
||||||
*/
|
*/
|
||||||
boolean hasAll(S flags, S required);
|
public abstract boolean hasAll(S flags, S required);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters a flag set so that it only contains the flags that were defined
|
* Filters a flag set so that it only contains the flags that were defined
|
||||||
@@ -108,7 +164,7 @@ public interface FlagGraph<V, S> {
|
|||||||
* @return A new set of flags.
|
* @return A new set of flags.
|
||||||
* @see #maximum
|
* @see #maximum
|
||||||
*/
|
*/
|
||||||
S minimum(S flags);
|
public abstract S minimum(S flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters a flag set so that it only contains the flags that were defined
|
* Filters a flag set so that it only contains the flags that were defined
|
||||||
@@ -119,5 +175,241 @@ public interface FlagGraph<V, S> {
|
|||||||
* @return A new set of flags.
|
* @return A new set of flags.
|
||||||
* @see #minimum
|
* @see #minimum
|
||||||
*/
|
*/
|
||||||
S maximum(S flags);
|
public abstract S maximum(S flags);
|
||||||
|
|
||||||
|
private static class ReadOnlyKeySet<K> implements Set<K> {
|
||||||
|
private final Set<K> underlying;
|
||||||
|
|
||||||
|
public ReadOnlyKeySet(HashMap<K, ?> map) {
|
||||||
|
this.underlying = map.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return this.underlying.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.underlying.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return this.underlying.contains(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<K> iterator() {
|
||||||
|
return this.underlying.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] toArray() {
|
||||||
|
return this.underlying.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T[] toArray(T[] a) {
|
||||||
|
return this.underlying.toArray(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(K key) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(Collection<?> c) {
|
||||||
|
return this.underlying.containsAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends K> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DefinitionIterator<V, S> implements Iterator<FlagDefinition<V, S>> {
|
||||||
|
private final Iterator<FlagDefinition<V, S>> byValueIterator;
|
||||||
|
private final Iterator<FlagDefinition<V, S>> byAliasIterator;
|
||||||
|
private FlagDefinition<V, S> nextDefinition;
|
||||||
|
|
||||||
|
public DefinitionIterator(HashMap<?, FlagDefinition<V, S>> byValue, HashMap<?, FlagDefinition<V, S>> byAlias) {
|
||||||
|
this.byValueIterator = byValue.values().iterator();
|
||||||
|
this.byAliasIterator = byAlias.values().iterator();
|
||||||
|
this.lookahead();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lookahead() {
|
||||||
|
FlagDefinition<V, S> found = null;
|
||||||
|
if (this.byValueIterator.hasNext()) {
|
||||||
|
found = this.byValueIterator.next();
|
||||||
|
}
|
||||||
|
while (found == null && this.byAliasIterator.hasNext()) {
|
||||||
|
found = this.byAliasIterator.next();
|
||||||
|
if (found.alias().isPresent()) {
|
||||||
|
found = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.nextDefinition = found;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return this.nextDefinition != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlagDefinition<V, S> next() {
|
||||||
|
var nextDefinition = this.nextDefinition;
|
||||||
|
if (nextDefinition == null) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
this.lookahead();
|
||||||
|
return nextDefinition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefinitionSet implements Set<FlagDefinition<V, S>> {
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return FlagGraph.this.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return FlagGraph.this.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
// noinspection SuspiciousMethodCalls
|
||||||
|
return FlagGraph.this.definitionsByValue.containsValue(o) ||
|
||||||
|
FlagGraph.this.definitionsByAlias.containsValue(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<FlagDefinition<V, S>> iterator() {
|
||||||
|
return new DefinitionIterator<>(FlagGraph.this.definitionsByValue, FlagGraph.this.definitionsByAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] toArray() {
|
||||||
|
int maxSize = FlagGraph.this.definitionsByValue.size() + FlagGraph.this.definitionsByAlias.size();
|
||||||
|
Object[] array = new Object[maxSize];
|
||||||
|
int i = 0;
|
||||||
|
for (var definition : FlagGraph.this.definitionsByValue.values()) {
|
||||||
|
array[i++] = definition;
|
||||||
|
}
|
||||||
|
for (var definition : FlagGraph.this.definitionsByAlias.values()) {
|
||||||
|
if (definition.value().isEmpty()) {
|
||||||
|
array[i++] = definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Arrays.copyOf(array, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T[] toArray(T[] a) {
|
||||||
|
int maxSize = FlagGraph.this.definitionsByValue.size() + FlagGraph.this.definitionsByAlias.size();
|
||||||
|
T[] array = (T[]) Array.newInstance(a.getClass().componentType(), maxSize);
|
||||||
|
;
|
||||||
|
int i = 0;
|
||||||
|
for (var definition : FlagGraph.this.definitionsByValue.values()) {
|
||||||
|
array[i++] = (T) definition;
|
||||||
|
}
|
||||||
|
for (var definition : FlagGraph.this.definitionsByAlias.values()) {
|
||||||
|
if (definition.value().isEmpty()) {
|
||||||
|
array[i++] = (T) definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i > a.length) {
|
||||||
|
return Arrays.copyOf(array, i);
|
||||||
|
} else {
|
||||||
|
Arrays.fill(a, null);
|
||||||
|
System.arraycopy(array, 0, a, 0, i);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(FlagDefinition<V, S> vsFlagDefinition) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(Collection<?> c) {
|
||||||
|
boolean result = true;
|
||||||
|
for (Object o : c) {
|
||||||
|
result = this.contains(o);
|
||||||
|
if (!result) break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends FlagDefinition<V, S>> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof Set<?> otherSet)) return false;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (var definition : FlagGraph.this.definitionsByValue.values()) {
|
||||||
|
if (!otherSet.contains(definition)) return false;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
for (var definition : FlagGraph.this.definitionsByAlias.values()) {
|
||||||
|
if (definition.value().isEmpty()) {
|
||||||
|
if (!otherSet.contains(definition)) return false;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count == otherSet.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,56 +9,15 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class BigBitFlagGraph implements FlagGraph<BigInteger, BigInteger> {
|
public class BigBitFlagGraph extends FlagGraph<BigInteger, BigInteger> {
|
||||||
|
|
||||||
@Override
|
protected BigBitFlagGraph(Collection<FlagDefinition<BigInteger, BigInteger>> c) {
|
||||||
public int size() {
|
super(c);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public BigInteger of(BigInteger... values) {
|
||||||
return false;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAlias(String alias) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(BigInteger value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsDefinition(FlagDefinition<BigInteger> definition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<BigInteger>> definitionNamed(String alias) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<BigInteger>> definitionOf(BigInteger value) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> aliasSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<BigInteger> valueSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<FlagDefinition<BigInteger>> definitions() {
|
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import java.math.BigInteger;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
public class BigBitFlagsIterator implements Iterator<BigInteger> {
|
public class BigBitFlagIterator implements Iterator<BigInteger> {
|
||||||
private BigInteger value;
|
private BigInteger value;
|
||||||
private BigInteger current;
|
private BigInteger current;
|
||||||
|
|
||||||
public BigBitFlagsIterator(BigInteger value) {
|
public BigBitFlagIterator(BigInteger value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.current = BigInteger.ONE;
|
this.current = BigInteger.ONE;
|
||||||
}
|
}
|
||||||
@@ -8,57 +8,16 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class BitFlagGraph implements FlagGraph<Integer, Integer> {
|
public class BitFlagGraph extends FlagGraph<Integer, Integer> {
|
||||||
|
protected BitFlagGraph(Collection<FlagDefinition<Integer, Integer>> c) {
|
||||||
|
super(c);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public Integer of(Integer... values) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAlias(String alias) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Integer value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsDefinition(FlagDefinition<Integer> definition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Integer>> definitionNamed(String alias) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Integer>> definitionOf(Integer value) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> aliasSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Integer> valueSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<FlagDefinition<Integer>> definitions() {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer named(String... aliases) {
|
public Integer named(String... aliases) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -83,4 +42,5 @@ public class BitFlagGraph implements FlagGraph<Integer, Integer> {
|
|||||||
public Integer maximum(Integer flags) {
|
public Integer maximum(Integer flags) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package fr.louisdevie.tatsuki.bitflags;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
public class BitFlagsIterator implements Iterator<Integer> {
|
public class BitFlagIterator implements Iterator<Integer> {
|
||||||
private int value;
|
private int value;
|
||||||
private int current;
|
private int current;
|
||||||
|
|
||||||
public BitFlagsIterator(int value) {
|
public BitFlagIterator(int value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.current = 1;
|
this.current = 1;
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ public final class BitFlags {
|
|||||||
|
|
||||||
private record IterableInteger(int value) implements Iterable<Integer> {
|
private record IterableInteger(int value) implements Iterable<Integer> {
|
||||||
public Iterator<Integer> iterator() {
|
public Iterator<Integer> iterator() {
|
||||||
return new BitFlagsIterator(this.value);
|
return new BitFlagIterator(this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public final class BitFlags {
|
|||||||
|
|
||||||
private record IterableLong(long value) implements Iterable<Long> {
|
private record IterableLong(long value) implements Iterable<Long> {
|
||||||
public Iterator<Long> iterator() {
|
public Iterator<Long> iterator() {
|
||||||
return new LongBitFlagsIterator(this.value);
|
return new LongBitFlagIterator(this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public final class BitFlags {
|
|||||||
|
|
||||||
private record IterableBigInteger(BigInteger value) implements Iterable<BigInteger> {
|
private record IterableBigInteger(BigInteger value) implements Iterable<BigInteger> {
|
||||||
public Iterator<BigInteger> iterator() {
|
public Iterator<BigInteger> iterator() {
|
||||||
return new BigBitFlagsIterator(this.value);
|
return new BigBitFlagIterator(this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,56 +8,15 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class LongBitFlagGraph implements FlagGraph<Long, Long> {
|
public class LongBitFlagGraph extends FlagGraph<Long, Long> {
|
||||||
|
|
||||||
@Override
|
protected LongBitFlagGraph(Collection<FlagDefinition<Long, Long>> c) {
|
||||||
public int size() {
|
super(c);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public Long of(Long... values) {
|
||||||
return false;
|
return 0L;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAlias(String alias) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Long value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsDefinition(FlagDefinition<Long> definition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Long>> definitionNamed(String alias) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Long>> definitionOf(Long value) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> aliasSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Long> valueSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<FlagDefinition<Long>> definitions() {
|
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package fr.louisdevie.tatsuki.bitflags;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
public class LongBitFlagsIterator implements Iterator<Long> {
|
public class LongBitFlagIterator implements Iterator<Long> {
|
||||||
private long value;
|
private long value;
|
||||||
private long current;
|
private long current;
|
||||||
|
|
||||||
public LongBitFlagsIterator(long value) {
|
public LongBitFlagIterator(long value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.current = 1L;
|
this.current = 1L;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package fr.louisdevie.tatsuki.builders;
|
||||||
|
|
||||||
|
import fr.louisdevie.tatsuki.builders.syntax.AsOrComposeValues;
|
||||||
|
import fr.louisdevie.tatsuki.builders.syntax.AsOrRequiresOrDefineOrComposeValues;
|
||||||
|
import fr.louisdevie.tatsuki.builders.syntax.RequiresOrDefineOrComposeValues;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public abstract class FlagSetBuilder<V, R> implements AsOrRequiresOrDefineOrComposeValues<V, R>, AsOrComposeValues<V, R> {
|
||||||
|
private final ArrayList<PartialFlagDefinition<V>> definitions;
|
||||||
|
private final HashMap<String, PartialFlagDefinition<V>> aliasToDefinition;
|
||||||
|
private final HashMap<V, PartialFlagDefinition<V>> valueToDefinition;
|
||||||
|
|
||||||
|
private PartialFlagDefinition<V> currentDefinition;
|
||||||
|
|
||||||
|
protected FlagSetBuilder() {
|
||||||
|
this.definitions = new ArrayList<>();
|
||||||
|
this.aliasToDefinition = new HashMap<>();
|
||||||
|
this.valueToDefinition = new HashMap<>();
|
||||||
|
|
||||||
|
this.currentDefinition = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequiresOrDefineOrComposeValues<V, R> as(String alias) {
|
||||||
|
if (this.currentDefinition == null) {
|
||||||
|
throw new IllegalStateException("Attempt to set an alias while there is no current definition");
|
||||||
|
}
|
||||||
|
this.currentDefinition.setAlias(alias);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequiresOrDefineOrComposeValues<V, R> requires(String... aliases) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public RequiresOrDefineOrComposeValues<V, R> requiresValues(V... values) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AsOrRequiresOrDefineOrComposeValues<V, R> defineValue(V value) {
|
||||||
|
this.finishCurrentDefinition();
|
||||||
|
this.currentDefinition = new PartialValueFlagDefinition<>(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AsOrComposeValues<V, R> compose(String... aliases) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public AsOrComposeValues<V, R> composeValues(V... values) {
|
||||||
|
if (this.currentDefinition != null && !this.currentDefinition.isComposition()) {
|
||||||
|
this.finishCurrentDefinition();
|
||||||
|
}
|
||||||
|
this.currentDefinition = new PartialComposedFlagDefinition<>();
|
||||||
|
|
||||||
|
for (V value: values) {
|
||||||
|
this.currentDefinition.addParent(this.referenceToValue(value));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finishCurrentDefinition() {
|
||||||
|
if (this.currentDefinition != null) {
|
||||||
|
this.definitions.add(this.currentDefinition);
|
||||||
|
this.currentDefinition = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<PartialFlagDefinition<V>> partialDefinitions() {
|
||||||
|
return this.definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PartialFlagDefinition<V> referenceToValue(V value) {
|
||||||
|
var definition = this.valueToDefinition.get(value);
|
||||||
|
if (definition == null) {
|
||||||
|
definition = new ForwardReferenceByValue<>(value);
|
||||||
|
}
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package fr.louisdevie.tatsuki.builders;
|
||||||
|
|
||||||
|
class ForwardReferenceByValue<V> implements PartialFlagDefinition<V> {
|
||||||
|
private final V value;
|
||||||
|
|
||||||
|
public ForwardReferenceByValue(V value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
throw new UnsupportedOperationException("Attempt to modify a forward reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addParent(PartialFlagDefinition<V> parent) {
|
||||||
|
throw new UnsupportedOperationException("Attempt to modify a forward reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComposition() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String alias() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V value() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package fr.louisdevie.tatsuki.builders;
|
||||||
|
|
||||||
|
class PartialComposedFlagDefinition<V> implements PartialFlagDefinition<V> {
|
||||||
|
public PartialComposedFlagDefinition() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addParent(PartialFlagDefinition<V> parent) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComposition() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String alias() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V value() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package fr.louisdevie.tatsuki.builders;
|
||||||
|
|
||||||
|
public interface PartialFlagDefinition<V> {
|
||||||
|
void setAlias(String alias);
|
||||||
|
|
||||||
|
void addParent(PartialFlagDefinition<V> parent);
|
||||||
|
|
||||||
|
boolean isComposition();
|
||||||
|
|
||||||
|
String alias();
|
||||||
|
|
||||||
|
V value();
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package fr.louisdevie.tatsuki.builders;
|
||||||
|
|
||||||
|
class PartialValueFlagDefinition<V> implements PartialFlagDefinition<V> {
|
||||||
|
private final V value;
|
||||||
|
private String alias;
|
||||||
|
|
||||||
|
public PartialValueFlagDefinition(V value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
if (alias == null) {
|
||||||
|
throw new NullPointerException("null flag alias");
|
||||||
|
}
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addParent(PartialFlagDefinition<V> parent) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComposition() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String alias() {
|
||||||
|
return this.alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V value() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.louisdevie.tatsuki.builders.syntax;
|
package fr.louisdevie.tatsuki.builders.syntax;
|
||||||
|
|
||||||
|
|
||||||
public interface DefineOrComposeValues<V, R> extends Root<R> {
|
public interface DefineOrComposeValues<V, R> {
|
||||||
/**
|
/**
|
||||||
* Define a flag with the given value.
|
* Define a flag with the given value.
|
||||||
*
|
*
|
||||||
@@ -26,4 +26,9 @@ public interface DefineOrComposeValues<V, R> extends Root<R> {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
AsOrComposeValues<V, R> composeValues(V... values);
|
AsOrComposeValues<V, R> composeValues(V... values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a flag set with the flags previously defined.
|
||||||
|
*/
|
||||||
|
R build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package fr.louisdevie.tatsuki.builders.syntax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder syntax root.
|
|
||||||
* @param <R> The result type produced by the builder.
|
|
||||||
*/
|
|
||||||
public interface Root<R> {
|
|
||||||
/**
|
|
||||||
* Build a flag set with the flags previously defined.
|
|
||||||
*/
|
|
||||||
R build();
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package fr.louisdevie.tatsuki.collections;
|
|
||||||
|
|
||||||
import fr.louisdevie.tatsuki.builders.syntax.AsOrComposeValues;
|
|
||||||
import fr.louisdevie.tatsuki.builders.syntax.AsOrRequiresOrDefineOrComposeValues;
|
|
||||||
import fr.louisdevie.tatsuki.builders.syntax.DefineOrComposeValues;
|
|
||||||
|
|
||||||
class CollectionFlagGraphBuilder<E> implements DefineOrComposeValues<E, SetFlagGraph<E>> {
|
|
||||||
@Override
|
|
||||||
public AsOrRequiresOrDefineOrComposeValues<E, SetFlagGraph<E>> defineValue(E value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AsOrComposeValues<E, SetFlagGraph<E>> compose(String... aliases) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AsOrComposeValues<E, SetFlagGraph<E>> composeValues(E... values) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SetFlagGraph<E> build() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,32 @@
|
|||||||
package fr.louisdevie.tatsuki.collections;
|
package fr.louisdevie.tatsuki.collections;
|
||||||
|
|
||||||
import fr.louisdevie.tatsuki.FlagDefinition;
|
import fr.louisdevie.tatsuki.FlagDefinition;
|
||||||
|
import fr.louisdevie.tatsuki.builders.PartialFlagDefinition;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
class SetFlagDefinition<E> implements FlagDefinition<Set<E>> {
|
class SetFlagDefinition<E> implements FlagDefinition<E, Set<E>> {
|
||||||
@Override
|
private final String alias;
|
||||||
public Optional<String> getAlias() {
|
private final E value;
|
||||||
return Optional.empty();
|
|
||||||
|
private SetFlagDefinition(String alias, E value) {
|
||||||
|
this.alias = alias;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> SetFlagDefinition<E> fromPartial(PartialFlagDefinition<E> partialFlagDefinition) {
|
||||||
|
return new SetFlagDefinition<>(partialFlagDefinition.alias(), partialFlagDefinition.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<E> values() {
|
public Optional<String> alias() {
|
||||||
return Set.of();
|
return Optional.ofNullable(this.alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<E> value() {
|
||||||
|
return Optional.ofNullable(this.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,71 +1,27 @@
|
|||||||
package fr.louisdevie.tatsuki.collections;
|
package fr.louisdevie.tatsuki.collections;
|
||||||
|
|
||||||
import fr.louisdevie.tatsuki.FlagGraph;
|
import fr.louisdevie.tatsuki.FlagGraph;
|
||||||
|
import fr.louisdevie.tatsuki.builders.FlagSetBuilder;
|
||||||
import fr.louisdevie.tatsuki.builders.syntax.DefineOrComposeValues;
|
import fr.louisdevie.tatsuki.builders.syntax.DefineOrComposeValues;
|
||||||
import fr.louisdevie.tatsuki.FlagDefinition;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class SetFlagGraph<E> implements FlagGraph<E, Set<E>> {
|
|
||||||
public static <E> DefineOrComposeValues<E, SetFlagGraph<E>> builder() {
|
|
||||||
return new CollectionFlagGraphBuilder<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public class SetFlagGraph<E> extends FlagGraph<E, Set<E>> {
|
||||||
SetFlagGraph(Collection<SetFlagDefinition<E>> c) {
|
SetFlagGraph(Collection<SetFlagDefinition<E>> c) {
|
||||||
|
super(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> DefineOrComposeValues<E, SetFlagGraph<E>> builder() {
|
||||||
|
return new Builder<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
@SuppressWarnings("unchecked")
|
||||||
return 0;
|
public Set<E> of(E... values) {
|
||||||
}
|
return Arrays.stream(values)
|
||||||
|
.filter(this::containsValue)
|
||||||
@Override
|
.collect(Collectors.toUnmodifiableSet());
|
||||||
public boolean isEmpty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAlias(String alias) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(E value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsDefinition(FlagDefinition<Set<E>> definition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Set<E>>> definitionNamed(String alias) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<FlagDefinition<Set<E>>> definitionOf(E value) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> aliasSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<E> valueSet() {
|
|
||||||
return Set.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<FlagDefinition<Set<E>>> definitions() {
|
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,4 +48,13 @@ public class SetFlagGraph<E> implements FlagGraph<E, Set<E>> {
|
|||||||
public Set<E> maximum(Set<E> flags) {
|
public Set<E> maximum(Set<E> flags) {
|
||||||
return Set.of();
|
return Set.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class Builder<E> extends FlagSetBuilder<E, SetFlagGraph<E>> {
|
||||||
|
@Override
|
||||||
|
public SetFlagGraph<E> build() {
|
||||||
|
this.finishCurrentDefinition();
|
||||||
|
var definitions = this.partialDefinitions().stream().map(SetFlagDefinition::fromPartial).toList();
|
||||||
|
return new SetFlagGraph<>(definitions);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package fr.louisdevie.tatsuki;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class FlagGraphTests {
|
||||||
|
@Test
|
||||||
|
public void size() {
|
||||||
|
final var noFlags = new MockFlagGraph();
|
||||||
|
|
||||||
|
assertEquals(0, noFlags.size());
|
||||||
|
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "1"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "2")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(3, flags.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isEmpty() {
|
||||||
|
final var noFlags = new MockFlagGraph();
|
||||||
|
|
||||||
|
assertTrue(noFlags.isEmpty());
|
||||||
|
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "x"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "y")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertFalse(flags.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsValue() {
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "x"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "y")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(flags.containsValue("A"));
|
||||||
|
assertTrue(flags.containsValue("B"));
|
||||||
|
assertFalse(flags.containsValue("C"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsAlias() {
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "x"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "y")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(flags.containsAlias("x"));
|
||||||
|
assertTrue(flags.containsAlias("y"));
|
||||||
|
assertFalse(flags.containsAlias("z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsDefinition() {
|
||||||
|
final var inGraph = new MockFlagDefinition("A", "x");
|
||||||
|
final var notInGraph = new MockFlagDefinition("B", "y");
|
||||||
|
final var flags = new MockFlagGraph(inGraph);
|
||||||
|
|
||||||
|
assertTrue(flags.containsDefinition(inGraph));
|
||||||
|
assertFalse(flags.containsDefinition(notInGraph));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void definitionOf() {
|
||||||
|
final var x = new MockFlagDefinition("A", "x");
|
||||||
|
final var y = new MockFlagDefinition("B", "y");
|
||||||
|
final var flags = new MockFlagGraph(x, y);
|
||||||
|
|
||||||
|
assertTrue(flags.definitionOf("A").isPresent());
|
||||||
|
assertSame(x, flags.definitionOf("A").get());
|
||||||
|
|
||||||
|
assertTrue(flags.definitionOf("B").isPresent());
|
||||||
|
assertSame(y, flags.definitionOf("B").get());
|
||||||
|
|
||||||
|
assertTrue(flags.definitionOf("C").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void definitionNamed() {
|
||||||
|
final var x = new MockFlagDefinition("A", "x");
|
||||||
|
final var y = new MockFlagDefinition("B", "y");
|
||||||
|
final var flags = new MockFlagGraph(x, y);
|
||||||
|
|
||||||
|
assertTrue(flags.definitionNamed("x").isPresent());
|
||||||
|
assertSame(x, flags.definitionNamed("x").get());
|
||||||
|
|
||||||
|
assertTrue(flags.definitionNamed("y").isPresent());
|
||||||
|
assertSame(y, flags.definitionNamed("y").get());
|
||||||
|
|
||||||
|
assertTrue(flags.definitionNamed("z").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void aliasSet() {
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "x"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "y")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(Set.of("x", "y"), flags.aliasSet());
|
||||||
|
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.aliasSet().remove("x"));
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.aliasSet().add("z"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void valueSet() {
|
||||||
|
final var flags = new MockFlagGraph(
|
||||||
|
new MockFlagDefinition("A", "x"),
|
||||||
|
new MockFlagDefinition("B", null),
|
||||||
|
new MockFlagDefinition(null, "y")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(Set.of("A", "B"), flags.valueSet());
|
||||||
|
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.valueSet().remove("A"));
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.valueSet().add("C"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void definitions() {
|
||||||
|
final var x = new MockFlagDefinition("A", "x");
|
||||||
|
final var B = new MockFlagDefinition("B", null);
|
||||||
|
final var y = new MockFlagDefinition(null, "y");
|
||||||
|
final var flags = new MockFlagGraph(x, B, y);
|
||||||
|
|
||||||
|
assertEquals(Set.of(x, B, y), flags.definitions());
|
||||||
|
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.valueSet().remove("A"));
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> flags.valueSet().add("C"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package fr.louisdevie.tatsuki;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class MockFlagDefinition implements FlagDefinition<String, String> {
|
||||||
|
private final String value;
|
||||||
|
private final String alias;
|
||||||
|
|
||||||
|
public MockFlagDefinition(String value, String alias) {
|
||||||
|
this.value = value;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> alias() {
|
||||||
|
return Optional.ofNullable(this.alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> value() {
|
||||||
|
return Optional.ofNullable(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIn(String set) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String addTo(String set) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String removeFrom(String set) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package fr.louisdevie.tatsuki;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class MockFlagGraph extends FlagGraph<String, String> {
|
||||||
|
@SafeVarargs
|
||||||
|
public MockFlagGraph(FlagDefinition<String, String>... definitions) {
|
||||||
|
super(Arrays.stream(definitions).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String of(String... values) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String named(String... aliases) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAny(String flags, String required) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAll(String flags, String required) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String minimum(String flags) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String maximum(String flags) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,20 @@ import java.util.Set;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
public class CollectionFlagGraphTests {
|
public class SetFlagGraphTests {
|
||||||
|
@Test
|
||||||
|
public void of() {
|
||||||
|
final var flags = SetFlagGraph.<Integer>builder()
|
||||||
|
.defineValue(12).as("a")
|
||||||
|
.defineValue(45).as("b")
|
||||||
|
.defineValue(78).as("c")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals(Set.of(), flags.of());
|
||||||
|
assertEquals(Set.of(12), flags.of(12));
|
||||||
|
assertEquals(Set.of(12, 78), flags.of(12, 54, 78));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void named() {
|
public void named() {
|
||||||
final var flags = SetFlagGraph.<Integer>builder()
|
final var flags = SetFlagGraph.<Integer>builder()
|
||||||
@@ -16,9 +29,9 @@ public class CollectionFlagGraphTests {
|
|||||||
.compose("a", "b").as("ab")
|
.compose("a", "b").as("ab")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertEquals(Set.of(), flags.named()) ;
|
assertEquals(Set.of(), flags.named());
|
||||||
assertEquals(Set.of(12), flags.named("a")) ;
|
assertEquals(Set.of(12), flags.named("a"));
|
||||||
assertEquals(Set.of(12, 45, 78), flags.named("ab", "c")) ;
|
assertEquals(Set.of(12, 45, 78), flags.named("ab", "c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -59,11 +72,11 @@ public class CollectionFlagGraphTests {
|
|||||||
.defineValue(78).requiresValues(45)
|
.defineValue(78).requiresValues(45)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertEquals(Set.of(), flags.maximum(Set.of())) ;
|
assertEquals(Set.of(), flags.maximum(Set.of()));
|
||||||
assertEquals(Set.of(12), flags.maximum(Set.of(12))) ;
|
assertEquals(Set.of(12), flags.maximum(Set.of(12)));
|
||||||
assertEquals(Set.of(12, 45), flags.maximum(Set.of(45))) ;
|
assertEquals(Set.of(12, 45), flags.maximum(Set.of(45)));
|
||||||
assertEquals(Set.of(12, 45, 78), flags.maximum(Set.of(78))) ;
|
assertEquals(Set.of(12, 45, 78), flags.maximum(Set.of(78)));
|
||||||
assertEquals(Set.of(), flags.maximum(Set.of(99))) ;
|
assertEquals(Set.of(), flags.maximum(Set.of(99)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,12 +87,12 @@ public class CollectionFlagGraphTests {
|
|||||||
.defineValue(78).requiresValues(45)
|
.defineValue(78).requiresValues(45)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertEquals(Set.of(), flags.minimum(Set.of())) ;
|
assertEquals(Set.of(), flags.minimum(Set.of()));
|
||||||
assertEquals(Set.of(12), flags.minimum(Set.of(12))) ;
|
assertEquals(Set.of(12), flags.minimum(Set.of(12)));
|
||||||
assertEquals(Set.of(), flags.minimum(Set.of(45))) ;
|
assertEquals(Set.of(), flags.minimum(Set.of(45)));
|
||||||
assertEquals(Set.of(12, 45), flags.minimum(Set.of(12, 45))) ;
|
assertEquals(Set.of(12, 45), flags.minimum(Set.of(12, 45)));
|
||||||
assertEquals(Set.of(12), flags.minimum(Set.of(12, 78))) ;
|
assertEquals(Set.of(12), flags.minimum(Set.of(12, 78)));
|
||||||
assertEquals(Set.of(12, 45, 78), flags.minimum(Set.of(12, 45, 78))) ;
|
assertEquals(Set.of(12, 45, 78), flags.minimum(Set.of(12, 45, 78)));
|
||||||
assertEquals(Set.of(), flags.minimum(Set.of(99))) ;
|
assertEquals(Set.of(), flags.minimum(Set.of(99)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user