Skip to content

Commit

Permalink
Add ImmutableEnumSet
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardehrenfried committed Dec 16, 2024
1 parent 5a3ef6a commit e035d5e
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.opentripplanner.utils.collection;

import java.util.HashSet;
import java.util.Set;
import org.opentripplanner.utils.lang.BitSetUtils;

public final class ImmutableEnumSet<T extends Enum<T>> {

private final int bitset;
private final Class<T> clazz;

private ImmutableEnumSet(Class<T> clazz, int bitset) {
this.bitset = bitset;
this.clazz = clazz;
}

@SafeVarargs
public static <E extends Enum<E>> ImmutableEnumSet<E> of(Class<E> clazz, E... elements) {
checkClass(clazz);

int bitset = 0;
for(E e : elements) {
bitset = BitSetUtils.set(bitset, e.ordinal(), true);
}
return new ImmutableEnumSet<>(clazz, bitset);
}
public static <E extends Enum<E>> ImmutableEnumSet<E> allOff(Class<E> clazz) {
return of(clazz, clazz.getEnumConstants());
}

private static <E extends Enum<E>> void checkClass(Class<E> clazz) {
if(!clazz.isEnum()) {
throw new IllegalArgumentException(String.format("Class %s is not an enum", clazz.getName()));
}
}

public boolean isEmpty() {
return bitset == 0;
}

public boolean contains(T value) {
return BitSetUtils.get(bitset, value.ordinal());
}

public Set<T> values() {
var set = new HashSet<T>();
for(var e: clazz.getEnumConstants()){
if(BitSetUtils.get(bitset, e.ordinal())) {
set.add(e);
}
}
return set;
}

@Override
public String toString() {
var builder = new StringBuilder();
builder.append("[");
for(var e: clazz.getEnumConstants()){
if(BitSetUtils.get(bitset, e.ordinal())) {
builder.append(e.name());
builder.append(",");
}
}
builder.append("]");
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.opentripplanner.utils.collection;

import static java.time.DayOfWeek.FRIDAY;
import static java.time.DayOfWeek.MONDAY;
import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;
import static java.time.DayOfWeek.THURSDAY;
import static java.time.DayOfWeek.TUESDAY;
import static java.time.DayOfWeek.WEDNESDAY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.time.DayOfWeek;
import java.util.Set;
import org.junit.jupiter.api.Test;

class ImmutableEnumSetTest {

@Test
void contains(){
var set = ImmutableEnumSet.of(DayOfWeek.class, MONDAY, WEDNESDAY);
assertFalse(set.isEmpty());
assertTrue(set.contains(MONDAY));
assertFalse(set.contains(TUESDAY));
assertTrue(set.contains(WEDNESDAY));
assertFalse(set.contains(THURSDAY));
assertFalse(set.contains(FRIDAY));
assertFalse(set.contains(SATURDAY));
assertFalse(set.contains(SUNDAY));
}

@Test
void allOf(){
var set = ImmutableEnumSet.allOff(DayOfWeek.class);
assertFalse(set.isEmpty());
assertTrue(set.contains(MONDAY));
assertTrue(set.contains(TUESDAY));
assertTrue(set.contains(WEDNESDAY));
assertTrue(set.contains(THURSDAY));
assertTrue(set.contains(FRIDAY));
assertTrue(set.contains(SATURDAY));
assertTrue(set.contains(SUNDAY));
}

@Test
void empty(){
assertFalse(ImmutableEnumSet.of(DayOfWeek.class, SUNDAY).isEmpty());
assertTrue(ImmutableEnumSet.of(DayOfWeek.class).isEmpty());
}

@Test
void string(){
var set = ImmutableEnumSet.of(DayOfWeek.class, SUNDAY, MONDAY, THURSDAY);
assertEquals("[MONDAY,THURSDAY,SUNDAY,]", set.toString());
}

@Test
void values(){
var set = ImmutableEnumSet.of(DayOfWeek.class, SUNDAY, THURSDAY, MONDAY).values();
assertEquals(Set.of(SUNDAY, MONDAY, THURSDAY), set);
}
}

0 comments on commit e035d5e

Please sign in to comment.