package amidst.mojangapi.world.versionfeatures; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Objects; import amidst.documentation.NotThreadSafe; import amidst.mojangapi.minecraftinterface.RecognisedVersion; @NotThreadSafe public class ListVersionFeatureBuilder { private static List concat(List values, List additionalValues) { List result = new ArrayList<>(values.size() + additionalValues.size()); result.addAll(values); result.addAll(additionalValues); return result; } private List defaultValue = null; private RecognisedVersion previous = null; private RecognisedVersion previousExact = null; private final List>> exactMatches = new LinkedList<>(); private final List>> entriesNewestFirst = new LinkedList<>(); @SafeVarargs public final ListVersionFeatureBuilder init(V... defaultValues) { return init(Arrays.asList(defaultValues)); } public ListVersionFeatureBuilder init(List defaultValue) { if (this.defaultValue == null) { this.defaultValue = defaultValue; return this; } else { throw new IllegalStateException("only one default value is allowed"); } } @SafeVarargs public final ListVersionFeatureBuilder exact(RecognisedVersion version, V... values) { return exact(version, Arrays.asList(values)); } public ListVersionFeatureBuilder exact(RecognisedVersion version, List value) { Objects.requireNonNull(version, "version cannot be null"); if (this.defaultValue == null) { throw new IllegalStateException("you need to specify a default value first"); } else if (previousExact != null && version == previousExact) { throw new IllegalStateException("you can only specify one value per version"); } else if (previousExact != null && RecognisedVersion.isOlder(version, previousExact)) { throw new IllegalStateException("you have to specify versions in ascending order"); } else if (!entriesNewestFirst.isEmpty()) { throw new IllegalStateException("you have to specify all exact matches before the first since"); } else { previousExact = version; exactMatches.add(0, new VersionFeatureEntry<>(version, Collections.unmodifiableList(value))); return this; } } @SafeVarargs public final ListVersionFeatureBuilder since(RecognisedVersion since, V... values) { return since(since, Arrays.asList(values)); } @SafeVarargs public final ListVersionFeatureBuilder sinceExtend(RecognisedVersion since, V... additionalValues) { return since(since, concat(getLatest(), Arrays.asList(additionalValues))); } public ListVersionFeatureBuilder since(RecognisedVersion version, List value) { Objects.requireNonNull(version, "version cannot be null"); if (this.defaultValue == null) { throw new IllegalStateException("you need to specify a default value first"); } else if (previous != null && version == previous) { throw new IllegalStateException("you can only specify one value per version"); } else if (previous != null && RecognisedVersion.isOlder(version, previous)) { throw new IllegalStateException("you have to specify versions in ascending order"); } else { previous = version; entriesNewestFirst.add(0, new VersionFeatureEntry<>(version, Collections.unmodifiableList(value))); return this; } } private List getLatest() { if (this.defaultValue == null) { throw new IllegalStateException("you need to specify a default value first"); } else if (entriesNewestFirst.isEmpty()) { return defaultValue; } else { return entriesNewestFirst.get(0).getValue(); } } public VersionFeature> construct() { return new VersionFeature<>( defaultValue, Collections.unmodifiableList(exactMatches), Collections.unmodifiableList(entriesNewestFirst)); } }