[utils] Who doesn't need some general util classes...
This commit is contained in:
@@ -1,224 +0,0 @@
|
||||
package de.siphalor.tweed5.core.api.collection;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequiredArgsConstructor
|
||||
public class TypedMultimap<T> implements Collection<T> {
|
||||
private static final TypedMultimap<Object> EMPTY = unmodifiable(new TypedMultimap<>(Collections.emptyMap(), ArrayList::new));
|
||||
|
||||
protected final Map<Class<? extends T>, Collection<T>> delegate;
|
||||
protected final Supplier<Collection<T>> collectionSupplier;
|
||||
|
||||
public static <T> TypedMultimap<T> unmodifiable(TypedMultimap<T> map) {
|
||||
return new Unmodifiable<>(map.delegate, map.collectionSupplier);
|
||||
}
|
||||
|
||||
public static <T> TypedMultimap<T> empty() {
|
||||
return (TypedMultimap<T>) EMPTY;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return (int) delegate.values().stream().mapToLong(Collection::size).sum();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull Object o) {
|
||||
return delegate.getOrDefault(o.getClass(), Collections.emptyList()).contains(o);
|
||||
}
|
||||
|
||||
public Set<Class<? extends T>> classes() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
private final Iterator<Map.Entry<Class<? extends T>, Collection<T>>> classIterator = delegate.entrySet().iterator();
|
||||
private Iterator<? extends T> listIterator;
|
||||
private boolean keptElement;
|
||||
private boolean keptAnyElementInList;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return classIterator.hasNext() || (listIterator != null && listIterator.hasNext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (keptElement) {
|
||||
keptAnyElementInList = true;
|
||||
}
|
||||
if (listIterator == null || !listIterator.hasNext()) {
|
||||
if (listIterator != null && !keptAnyElementInList) {
|
||||
classIterator.remove();
|
||||
}
|
||||
listIterator = classIterator.next().getValue().iterator();
|
||||
keptAnyElementInList = false;
|
||||
}
|
||||
keptElement = true;
|
||||
return listIterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (listIterator == null) {
|
||||
throw new IllegalStateException("Iterator has not been called");
|
||||
}
|
||||
keptElement = false;
|
||||
listIterator.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object @NotNull [] toArray() {
|
||||
return delegate.values().stream().flatMap(Collection::stream).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public <S> S @NotNull [] toArray(@NotNull S @NotNull [] array) {
|
||||
Class<?> clazz = array.getClass().getComponentType();
|
||||
return delegate.values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
.toArray(size -> (S[]) Array.newInstance(clazz, size));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(@NotNull T value) {
|
||||
return delegate.computeIfAbsent(((Class<T>) value.getClass()), clazz -> collectionSupplier.get()).add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(@NotNull Object value) {
|
||||
Collection<T> values = delegate.get(value.getClass());
|
||||
if (values == null) {
|
||||
return false;
|
||||
}
|
||||
if (values.remove(value)) {
|
||||
if (values.isEmpty()) {
|
||||
delegate.remove(value.getClass());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <U extends T> Collection<U> getAll(Class<U> clazz) {
|
||||
return (Collection<U>) Collections.unmodifiableCollection(delegate.getOrDefault(clazz, Collections.emptyList()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<T> removeAll(Class<? extends T> clazz) {
|
||||
Collection<T> removed = delegate.remove(clazz);
|
||||
return removed == null ? Collections.emptyList() : Collections.unmodifiableCollection(removed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(@NotNull Collection<?> values) {
|
||||
for (Object value : values) {
|
||||
if (!contains(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends T> values) {
|
||||
boolean changed = false;
|
||||
for (T value : values) {
|
||||
changed = add(value) || changed;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> values) {
|
||||
boolean changed = false;
|
||||
for (Object value : values) {
|
||||
changed = remove(value) || changed;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> values) {
|
||||
Map<Class<?>, ? extends List<?>> valuesByClass = values.stream()
|
||||
.collect(Collectors.groupingBy(Object::getClass));
|
||||
delegate.putAll((Map<Class<? extends T>, List<T>>)(Object) valuesByClass);
|
||||
delegate.keySet().removeIf(key -> !valuesByClass.containsKey(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
protected static class Unmodifiable<T> extends TypedMultimap<T> {
|
||||
public Unmodifiable(
|
||||
Map<Class<? extends T>, Collection<T>> delegate,
|
||||
Supplier<Collection<T>> collectionSupplier
|
||||
) {
|
||||
super(delegate, collectionSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<T> iterator() {
|
||||
return delegate.values().stream().flatMap(Collection::stream).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(@NotNull T value) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(@NotNull Object value) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<T> removeAll(Class<? extends T> clazz) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends T> values) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> values) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> values) {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw createUnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected UnsupportedOperationException createUnsupportedOperationException() {
|
||||
return new UnsupportedOperationException("Map is unmodifiable");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
|
||||
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -15,10 +16,6 @@ import java.util.Map;
|
||||
* @see ConfigContainerSetupPhase
|
||||
*/
|
||||
public interface ConfigContainer<T> {
|
||||
ConfigContainerSetupPhase setupPhase();
|
||||
default boolean isReady() {
|
||||
return setupPhase() == ConfigContainerSetupPhase.READY;
|
||||
}
|
||||
|
||||
default void registerExtensions(TweedExtension... extensions) {
|
||||
for (TweedExtension extension : extensions) {
|
||||
@@ -28,6 +25,10 @@ public interface ConfigContainer<T> {
|
||||
|
||||
void registerExtension(TweedExtension extension);
|
||||
|
||||
@Nullable
|
||||
<E extends TweedExtension> E extension(Class<E> extensionClass);
|
||||
Collection<TweedExtension> extensions();
|
||||
|
||||
void finishExtensionSetup();
|
||||
|
||||
void attachAndSealTree(ConfigEntry<T> rootEntry);
|
||||
@@ -37,7 +38,5 @@ public interface ConfigContainer<T> {
|
||||
void initialize();
|
||||
|
||||
ConfigEntry<T> rootEntry();
|
||||
|
||||
Collection<TweedExtension> extensions();
|
||||
Map<Class<?>, ? extends RegisteredExtensionData<EntryExtensionsData, ?>> entryDataExtensions();
|
||||
}
|
||||
|
||||
@@ -9,33 +9,37 @@ import de.siphalor.tweed5.patchwork.api.PatchworkClassCreator;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClass;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
||||
import de.siphalor.tweed5.utils.api.collection.ClassToInstanceMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class DefaultConfigContainer<T> implements ConfigContainer<T> {
|
||||
@Getter
|
||||
private ConfigContainerSetupPhase setupPhase = ConfigContainerSetupPhase.EXTENSIONS_SETUP;
|
||||
private final Map<Class<? extends TweedExtension>, TweedExtension> extensions = new HashMap<>();
|
||||
private final ClassToInstanceMap<TweedExtension> extensions = new ClassToInstanceMap<>();
|
||||
private ConfigEntry<T> rootEntry;
|
||||
private PatchworkClass<EntryExtensionsData> entryExtensionsDataPatchworkClass;
|
||||
private Map<Class<?>, RegisteredExtensionDataImpl<EntryExtensionsData, ?>> registeredEntryDataExtensions;
|
||||
|
||||
@Override
|
||||
public <E extends TweedExtension> @Nullable E extension(Class<E> extensionClass) {
|
||||
return extensions.get(extensionClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TweedExtension> extensions() {
|
||||
return extensions.values();
|
||||
return Collections.unmodifiableCollection(extensions.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExtension(TweedExtension extension) {
|
||||
requireSetupPhase(ConfigContainerSetupPhase.EXTENSIONS_SETUP);
|
||||
|
||||
TweedExtension previous = extensions.put(extension.getClass(), extension);
|
||||
TweedExtension previous = extensions.put(extension);
|
||||
if (previous != null) {
|
||||
throw new IllegalArgumentException("Extension " + extension.getClass().getName() + " is already registered");
|
||||
}
|
||||
@@ -65,7 +69,7 @@ public class DefaultConfigContainer<T> implements ConfigContainer<T> {
|
||||
|
||||
@Override
|
||||
public void registerExtension(TweedExtension extension) {
|
||||
if (!extensions.containsKey(extension.getClass())) {
|
||||
if (!extensions.containsClass(extension.getClass())) {
|
||||
additionalExtensions.add(extension);
|
||||
}
|
||||
}
|
||||
@@ -78,7 +82,7 @@ public class DefaultConfigContainer<T> implements ConfigContainer<T> {
|
||||
}
|
||||
|
||||
for (TweedExtension additionalExtension : additionalExtensions) {
|
||||
extensions.put(additionalExtension.getClass(), additionalExtension);
|
||||
extensions.put(additionalExtension);
|
||||
}
|
||||
extensionsToSetup = new ArrayList<>(additionalExtensions);
|
||||
additionalExtensions.clear();
|
||||
|
||||
Reference in New Issue
Block a user