From 9b0e8fcb9410f1f96b8bcc9b8c56a9d27503a644 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 6 Sep 2023 19:06:27 -0300 Subject: [PATCH] Flag processing strategies --- .../splits/FeatureFlagProcessStrategy.java | 78 +++++++++++++++++++ .../service/splits/SplitChangeProcessor.java | 69 ++++------------ 2 files changed, 95 insertions(+), 52 deletions(-) create mode 100644 src/main/java/io/split/android/client/service/splits/FeatureFlagProcessStrategy.java diff --git a/src/main/java/io/split/android/client/service/splits/FeatureFlagProcessStrategy.java b/src/main/java/io/split/android/client/service/splits/FeatureFlagProcessStrategy.java new file mode 100644 index 000000000..91f979d25 --- /dev/null +++ b/src/main/java/io/split/android/client/service/splits/FeatureFlagProcessStrategy.java @@ -0,0 +1,78 @@ +package io.split.android.client.service.splits; + +import androidx.annotation.NonNull; + +import java.util.List; + +import io.split.android.client.dtos.Split; +import io.split.android.client.dtos.Status; + +interface FeatureFlagProcessStrategy { + + void process(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List filterValues); +} + +class StatusProcessStrategy implements FeatureFlagProcessStrategy { + + @Override + public void process(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List filterValues) { + if (featureFlag.status == Status.ACTIVE) { + activeFeatureFlags.add(featureFlag); + } else { + archivedFeatureFlags.add(featureFlag); + } + } +} + +class NamesProcessStrategy implements FeatureFlagProcessStrategy { + + private final List mConfiguredValues; + private final StatusProcessStrategy mStatusProcessStrategy; + + NamesProcessStrategy(@NonNull List configuredValues, @NonNull StatusProcessStrategy statusProcessStrategy) { + mConfiguredValues = configuredValues; + mStatusProcessStrategy = statusProcessStrategy; + } + + @Override + public void process(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List filterValues) { + // If the feature flag name is in the filter, we process it according to its status. Otherwise it is ignored + if (mConfiguredValues.contains(featureFlag.name)) { + mStatusProcessStrategy.process(activeFeatureFlags, archivedFeatureFlags, featureFlag, filterValues); + } + } +} + +class SetsProcessStrategy implements FeatureFlagProcessStrategy { + + private final List mConfiguredValues; + private final StatusProcessStrategy mStatusProcessStrategy; + + SetsProcessStrategy(@NonNull List configuredValues, @NonNull StatusProcessStrategy statusProcessStrategy) { + mConfiguredValues = configuredValues; + mStatusProcessStrategy = statusProcessStrategy; + } + + @Override + public void process(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List filterValues) { + if (featureFlag.sets == null || featureFlag.sets.isEmpty()) { + archivedFeatureFlags.add(featureFlag); + return; + } + + boolean shouldArchive = true; + for (String set : featureFlag.sets) { + if (mConfiguredValues.contains(set)) { + // If the feature flag has at least one set that matches the configured sets, + // we process it according to its status + mStatusProcessStrategy.process(activeFeatureFlags, archivedFeatureFlags, featureFlag, filterValues); + shouldArchive = false; + break; + } + } + + if (shouldArchive) { + archivedFeatureFlags.add(featureFlag); + } + } +} diff --git a/src/main/java/io/split/android/client/service/splits/SplitChangeProcessor.java b/src/main/java/io/split/android/client/service/splits/SplitChangeProcessor.java index 0b88c0b25..62eaa9660 100644 --- a/src/main/java/io/split/android/client/service/splits/SplitChangeProcessor.java +++ b/src/main/java/io/split/android/client/service/splits/SplitChangeProcessor.java @@ -18,6 +18,8 @@ public class SplitChangeProcessor { private final SplitFilter mSplitFilter; + private final StatusProcessStrategy mStatusProcessStrategy; + @VisibleForTesting SplitChangeProcessor() { this((SplitFilter) null); @@ -30,10 +32,13 @@ public SplitChangeProcessor(@Nullable List filters) { } else { mSplitFilter = filters.get(0); } + + mStatusProcessStrategy = new StatusProcessStrategy(); } public SplitChangeProcessor(@Nullable SplitFilter splitFilter) { mSplitFilter = splitFilter; + mStatusProcessStrategy = new StatusProcessStrategy(); } public ProcessedSplitChange process(SplitChange splitChange) { @@ -53,68 +58,28 @@ private ProcessedSplitChange buildProcessedSplitChange(List featureFlags, List activeFeatureFlags = new ArrayList<>(); List archivedFeatureFlags = new ArrayList<>(); + SplitFilter.Type filterType = (mSplitFilter != null) ? mSplitFilter.getType() : null; + List filterValues = (mSplitFilter != null) ? mSplitFilter.getValues() : null; + + FeatureFlagProcessStrategy processStrategy = getProcessStrategy(filterType, filterValues); + for (Split featureFlag : featureFlags) { if (featureFlag.name == null) { continue; } - - if (mSplitFilter == null || mSplitFilter.getValues().isEmpty()) { - processAccordingToStatus(activeFeatureFlags, archivedFeatureFlags, featureFlag); - } else { - if (mSplitFilter.getType() == SplitFilter.Type.BY_NAME) { - processAccordingToNames(activeFeatureFlags, archivedFeatureFlags, featureFlag, mSplitFilter.getValues()); - } else if (mSplitFilter.getType() == SplitFilter.Type.BY_SET) { - processAccordingToSets(activeFeatureFlags, archivedFeatureFlags, featureFlag, mSplitFilter.getValues()); - } - } + processStrategy.process(activeFeatureFlags, archivedFeatureFlags, featureFlag, filterValues); } return new ProcessedSplitChange(activeFeatureFlags, archivedFeatureFlags, changeNumber, System.currentTimeMillis() / 100); } - /** - * Process the feature flag according to its status - */ - private void processAccordingToStatus(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag) { - if (featureFlag.status == Status.ACTIVE) { - activeFeatureFlags.add(featureFlag); + private FeatureFlagProcessStrategy getProcessStrategy(SplitFilter.Type filterType, List filterValues) { + if (filterType == SplitFilter.Type.BY_SET) { + return new NamesProcessStrategy(filterValues, mStatusProcessStrategy); + } else if (filterType == SplitFilter.Type.BY_NAME) { + return new SetsProcessStrategy(filterValues, mStatusProcessStrategy); } else { - archivedFeatureFlags.add(featureFlag); - } - } - - /** - * Process the feature flag according to its name - */ - private void processAccordingToNames(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List configuredValues) { - // If the feature flag name is in the filter, we process it according to its status. Otherwise it's ignored - if (configuredValues.contains(featureFlag.name)) { - processAccordingToStatus(activeFeatureFlags, archivedFeatureFlags, featureFlag); - } - } - - /** - * Process the feature flag according to its sets - */ - private void processAccordingToSets(List activeFeatureFlags, List archivedFeatureFlags, Split featureFlag, List configuredValues) { - if (featureFlag.sets == null || featureFlag.sets.isEmpty()) { - archivedFeatureFlags.add(featureFlag); - return; - } - - boolean shouldArchive = true; - for (String set : featureFlag.sets) { - if (configuredValues.contains(set)) { - // If the feature flag has at least one set that matches the configured sets, - // we process it according to its status - processAccordingToStatus(activeFeatureFlags, archivedFeatureFlags, featureFlag); - shouldArchive = false; - break; - } - } - - if (shouldArchive) { - archivedFeatureFlags.add(featureFlag); + return mStatusProcessStrategy; } } }