Map<String, String> execute(ServerWebExchange exchange, StainingRule stainingRule) {
		if (stainingRule == null) {
			return Collections.emptyMap();
		}

		List<StainingRule.Rule> rules = stainingRule.getRules();
		if (CollectionUtils.isEmpty(rules)) {
			return Collections.emptyMap();
		}

		Map<String, String> parsedLabels = new HashMap<>();

		for (StainingRule.Rule rule : rules) {
			List<Condition> conditions = rule.getConditions();

			Set<String> keys = new HashSet<>();
			conditions.forEach(condition -> keys.add(condition.getKey()));
			Map<String, String> actualValues = SpringWebExpressionLabelUtils.resolve(exchange, keys);

			if (!ConditionUtils.match(actualValues, conditions)) {
				continue;
			}

			parsedLabels.putAll(KVPairUtils.toMap(rule.getLabels()));
		}

		return parsedLabels;
	}
@Test
	public void testMatchTwoRulesAndNotMatchOneRule() {
		Condition condition1 = new Condition();
		condition1.setKey("${http.header.uid}");
		condition1.setOperation(Operation.EQUALS.toString());
		condition1.setValues(Collections.singletonList("1000"));

		Condition condition2 = new Condition();
		condition2.setKey("${http.query.source}");
		condition2.setOperation(Operation.IN.toString());
		condition2.setValues(Collections.singletonList("wx"));

		// rule1 matched
		StainingRule.Rule rule1 = new StainingRule.Rule();
		rule1.setConditions(Arrays.asList(condition1, condition2));

		KVPair kvPair = new KVPair();
		kvPair.setKey("env");
		kvPair.setValue("blue");
		rule1.setLabels(Collections.singletonList(kvPair));

		// rule2 matched
		StainingRule.Rule rule2 = new StainingRule.Rule();
		rule2.setConditions(Collections.singletonList(condition1));

		KVPair kvPair2 = new KVPair();
		kvPair2.setKey("label1");
		kvPair2.setValue("value1");
		KVPair kvPair3 = new KVPair();
		kvPair3.setKey("label2");
		kvPair3.setValue("value2");
		rule2.setLabels(Arrays.asList(kvPair2, kvPair3));

		// rule3 not matched
		Condition condition3 = new Condition();
		condition3.setKey("${http.query.type}");
		condition3.setOperation(Operation.IN.toString());
		condition3.setValues(Collections.singletonList("wx"));

		StainingRule.Rule rule3 = new StainingRule.Rule();
		rule3.setConditions(Collections.singletonList(condition3));

		KVPair kvPair4 = new KVPair();
		kvPair4.setKey("label3");
		kvPair4.setValue("value3");
		rule3.setLabels(Collections.singletonList(kvPair4));

		StainingRule stainingRule = new StainingRule();
		stainingRule.setRules(Arrays.asList(rule1, rule2, rule3));

		MockServerHttpRequest request = MockServerHttpRequest.get("/users")
				.queryParam("source", "wx")
				.header("uid", "1000").build();
		MockServerWebExchange exchange = new MockServerWebExchange.Builder(request).build();

		RuleStainingExecutor executor = new RuleStainingExecutor();

		Map<String, String> stainedLabels = executor.execute(exchange, stainingRule);

		assertThat(stainedLabels).isNotNull();
		assertThat(stainedLabels.size()).isEqualTo(3);
		assertThat(stainedLabels.get("env")).isEqualTo("blue");
		assertThat(stainedLabels.get("label1")).isEqualTo("value1");
		assertThat(stainedLabels.get("label2")).isEqualTo("value2");
	}