All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.split.client.utils.LocalhostSanitizer Maven / Gradle / Ivy

The newest version!
package io.split.client.utils;

import com.google.common.base.Preconditions;
import io.split.client.dtos.Condition;
import io.split.client.dtos.ConditionType;
import io.split.client.dtos.KeySelector;
import io.split.client.dtos.Matcher;
import io.split.client.dtos.MatcherCombiner;
import io.split.client.dtos.MatcherGroup;
import io.split.client.dtos.MatcherType;
import io.split.client.dtos.Partition;
import io.split.client.dtos.SegmentChange;
import io.split.client.dtos.Split;
import io.split.client.dtos.SplitChange;
import io.split.client.dtos.Status;
import io.split.client.dtos.WhitelistMatcherData;
import io.split.client.dtos.RuleBasedSegment;
import io.split.client.dtos.ChangeDto;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public final class LocalhostSanitizer {
    private static final String DEFAULT_RULE = "default rule";

    private LocalhostSanitizer() {
        throw new IllegalStateException("Utility class");
    }

    public static SplitChange sanitization(SplitChange splitChange) {
        sanitizeTillAndSince(splitChange);
        splitChange.featureFlags.d = sanitizeFeatureFlags(splitChange.featureFlags.d);
        splitChange.ruleBasedSegments.d = sanitizeRuleBasedSegments(splitChange.ruleBasedSegments.d);

        return splitChange;
    }

    private static List sanitizeRuleBasedSegments(List ruleBasedSegments) {
        List ruleBasedSegmentsToRemove = new ArrayList<>();
        if (ruleBasedSegments != null) {
            for (RuleBasedSegment ruleBasedSegment : ruleBasedSegments) {
                if (ruleBasedSegment.name == null) {
                    ruleBasedSegmentsToRemove.add(ruleBasedSegment);
                    continue;
                }
                ruleBasedSegment.trafficTypeName = sanitizeIfNullOrEmpty(ruleBasedSegment.trafficTypeName, LocalhostConstants.USER);
                ruleBasedSegment.status = sanitizeStatus(ruleBasedSegment.status);
                ruleBasedSegment.changeNumber = sanitizeChangeNumber(ruleBasedSegment.changeNumber, 0);
                ruleBasedSegment.conditions = sanitizeConditions((ArrayList) ruleBasedSegment.conditions, false,
                        ruleBasedSegment.trafficTypeName);
                ruleBasedSegment.excluded.segments = sanitizeExcluded((ArrayList) ruleBasedSegment.excluded.segments);
                ruleBasedSegment.excluded.keys = sanitizeExcluded((ArrayList) ruleBasedSegment.excluded.keys);
            }
            ruleBasedSegments.removeAll(ruleBasedSegmentsToRemove);
        } else {
            ruleBasedSegments = new ArrayList<>();
        }
        return ruleBasedSegments;
    }

    private static List sanitizeFeatureFlags(List featureFlags) {
        List splitsToRemove = new ArrayList<>();
        if (featureFlags != null) {
            for (Split split : featureFlags) {
                if (split.name == null) {
                    splitsToRemove.add(split);
                    continue;
                }
                split.trafficTypeName = sanitizeIfNullOrEmpty(split.trafficTypeName, LocalhostConstants.USER);
                split.status = sanitizeStatus(split.status);
                split.defaultTreatment = sanitizeIfNullOrEmpty(split.defaultTreatment, LocalhostConstants.CONTROL);
                split.changeNumber = sanitizeChangeNumber(split.changeNumber, 0);
                split.trafficAllocation = sanitizeTrafficAllocation(split.trafficAllocation);
                split.trafficAllocationSeed = sanitizeSeed(split.trafficAllocationSeed);
                split.seed = sanitizeSeed(split.seed);
                split.algo = sanitizeAlgo(split.algo);
                split.conditions = sanitizeConditions((ArrayList) split.conditions, false, split.trafficTypeName);
            }
            featureFlags.removeAll(splitsToRemove);
        } else {
            featureFlags = new ArrayList<>();
        }
        return featureFlags;
    }

    private static int sanitizeSeed(Integer seed) {
        SecureRandom random = new SecureRandom();
        if (seed == null || seed == 0) {
            seed = -random.nextInt(10) * LocalhostConstants.MILLI_SECONDS;
        }
        return seed;
    }

    private static int sanitizeAlgo(int algo) {
        if (algo != LocalhostConstants.ALGO) {
            algo = LocalhostConstants.ALGO;
        }
        return algo;
    }

    private static int sanitizeTrafficAllocation(Integer trafficAllocation) {
        if (trafficAllocation == null || trafficAllocation < 0 || trafficAllocation > LocalhostConstants.SIZE_100) {
            trafficAllocation = LocalhostConstants.SIZE_100;
        }
        return trafficAllocation;
    }

    private static ArrayList sanitizeConditions(ArrayList conditions, boolean createPartition, String trafficTypeName) {
        if (conditions == null) {
            conditions = new ArrayList<>();
        }

        Condition condition = new Condition();
        if (!conditions.isEmpty()){
            condition = conditions.get(conditions.size() - 1);
        }

        if (conditions.isEmpty() || !condition.conditionType.equals(ConditionType.ROLLOUT) ||
                condition.matcherGroup.matchers == null ||
                condition.matcherGroup.matchers.isEmpty() ||
                !condition.matcherGroup.matchers.get(0).matcherType.equals(MatcherType.ALL_KEYS)) {
            Condition rolloutCondition = new Condition();
            conditions.add(createRolloutCondition(rolloutCondition, trafficTypeName, null, createPartition));
        }
        return conditions;
    }
    private static String sanitizeIfNullOrEmpty(String toBeSanitized, String defaultValue) {
        if (toBeSanitized == null || toBeSanitized.isEmpty()) {
            return defaultValue;
        }
        return toBeSanitized;
    }

    private static long sanitizeChangeNumber(long toBeSanitized, long defaultValue) {
        if (toBeSanitized < 0) {
            return defaultValue;
        }
        return toBeSanitized;
    }

    private static Status sanitizeStatus(Status toBeSanitized) {
        if (toBeSanitized == null || toBeSanitized != Status.ACTIVE && toBeSanitized != Status.ARCHIVED) {
            return Status.ACTIVE;
        }
        return toBeSanitized;

    }

    private static ArrayList sanitizeExcluded(ArrayList excluded)
    {
        if (excluded == null) {
            return new ArrayList<>();
        }
        return excluded;
    }

    private static SplitChange sanitizeTillAndSince(SplitChange splitChange) {
        if (checkTillConditions(splitChange.featureFlags)) {
            splitChange.featureFlags.t = LocalhostConstants.DEFAULT_TS;
        }
        if (checkSinceConditions(splitChange.featureFlags)) {
            splitChange.featureFlags.s = splitChange.featureFlags.t;
        }

        if (checkTillConditions(splitChange.ruleBasedSegments)) {
            splitChange.ruleBasedSegments.t = LocalhostConstants.DEFAULT_TS;
        }
        if (checkSinceConditions(splitChange.ruleBasedSegments)) {
            splitChange.ruleBasedSegments.s = splitChange.ruleBasedSegments.t;
        }
        return splitChange;
    }

    private static  boolean checkTillConditions(ChangeDto change) {
        return change.t < LocalhostConstants.DEFAULT_TS || change.t == 0;
    }

    private static  boolean checkSinceConditions(ChangeDto change) {
        return change.s < LocalhostConstants.DEFAULT_TS || change.s > change.t;
    }

    public static SegmentChange sanitization(SegmentChange segmentChange) {
        if (segmentChange.name == null || segmentChange.name.isEmpty()) {
            return null;
        }
        if (segmentChange.added == null) {
            segmentChange.added =  new ArrayList<>();
        }
        if (segmentChange.removed == null) {
            segmentChange.removed = new ArrayList<>();
        }
        List addedToRemoved = segmentChange.added.stream().filter(add -> segmentChange.removed.contains(add)).collect(Collectors.toList());
        segmentChange.removed.removeAll(addedToRemoved);

        if (segmentChange.till < LocalhostConstants.DEFAULT_TS || segmentChange.till == 0){
            segmentChange.till = LocalhostConstants.DEFAULT_TS;
        }
        if (segmentChange.since < LocalhostConstants.DEFAULT_TS || segmentChange.since > segmentChange.till) {
            segmentChange.since = segmentChange.till;
        }
        return segmentChange;
    }

    public static Condition createRolloutCondition(Condition condition, String trafficType, String treatment, boolean createPartition) {
        condition.conditionType = ConditionType.ROLLOUT;
        condition.matcherGroup = new MatcherGroup();
        condition.matcherGroup.combiner = MatcherCombiner.AND;
        Matcher matcher = new Matcher();
        KeySelector keySelector = new KeySelector();
        keySelector.trafficType = trafficType;

        matcher.keySelector = keySelector;
        matcher.matcherType = MatcherType.ALL_KEYS;
        matcher.negate = false;

        condition.matcherGroup.matchers = new ArrayList<>();
        condition.matcherGroup.matchers.add(matcher);

        if (createPartition) {
            condition.partitions = new ArrayList<>();
            Partition partition1 = new Partition();
            Partition partition2 = new Partition();
            partition1.size = LocalhostConstants.SIZE_100;
            partition2.size = LocalhostConstants.SIZE_0;
            if (treatment != null) {
                partition1.treatment = treatment;
            } else {
                partition1.treatment = LocalhostConstants.TREATMENT_OFF;
                partition2.treatment = LocalhostConstants.TREATMENT_ON;
            }
            condition.partitions.add(partition1);
            condition.partitions.add(partition2);
        }
        condition.label = DEFAULT_RULE;

        return condition;
    }

    public static Condition createCondition(Object keyOrKeys, String treatment) {
        Condition condition = new Condition();
        if (keyOrKeys == null) {
            return LocalhostSanitizer.createRolloutCondition(condition, "user", treatment, true);
        } else {
            if (keyOrKeys instanceof String) {
                List keys = new ArrayList<>();
                keys.add(keyOrKeys);
                return createWhitelistCondition(condition, "user", treatment, keys);
            } else {
                Preconditions.checkArgument(keyOrKeys instanceof List, "'keys' is not a String nor a List.");
                return createWhitelistCondition(condition, "user", treatment, (List) keyOrKeys);
            }
        }
    }

    public static Condition createWhitelistCondition(Condition condition, String trafficType, String treatment, List keys) {
        condition.conditionType = ConditionType.WHITELIST;
        condition.matcherGroup = new MatcherGroup();
        condition.matcherGroup.combiner = MatcherCombiner.AND;
        Matcher matcher = new Matcher();
        KeySelector keySelector = new KeySelector();
        keySelector.trafficType = trafficType;

        matcher.keySelector = keySelector;
        matcher.matcherType = MatcherType.WHITELIST;
        matcher.negate = false;
        matcher.whitelistMatcherData = new WhitelistMatcherData();
        matcher.whitelistMatcherData.whitelist = new ArrayList<>(keys);

        condition.matcherGroup.matchers = new ArrayList<>();
        condition.matcherGroup.matchers.add(matcher);

        condition.partitions = new ArrayList<>();
        Partition partition1 = new Partition();
        Partition partition2 = new Partition();
        partition1.size = LocalhostConstants.SIZE_100;
        partition2.size = LocalhostConstants.SIZE_0;
        if (treatment != null) {
            partition1.treatment = treatment;
        } else {
            partition1.treatment = LocalhostConstants.TREATMENT_OFF;
            partition2.treatment = LocalhostConstants.TREATMENT_ON;
        }
        condition.partitions.add(partition1);
        condition.partitions.add(partition2);
        condition.label = "default rule";

        return condition;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy