Koooooo-7/KChain
:nut_and_bolt: A flexible and configurable check chain.
KChain
English | 中文
🔩
KChain, a flexible and configurable chain.
What is the problem
Sometimes, we will face a situations that we need to check various properties set such as Map<String,Object> or Entity entities ( named it as properties set).
Obviously, there will be one or more different verification rules for different properties.
So, it is necessary to have a chain structure to solve those problems.
KChain is an implementation to solve these problems.
The following two dimensions are usually considered:
Check Properties
- For a single
properties set, such asMap<String,Object>
It needs to check whether its different properties match one or more rules.
For example, the value of the key calledname in a Map<String,Object> can not be empty.
- For batch of
perperties set, such asList<User>
It is necessary to check whether they meet certain rules with each other.
For example, such as the same name of User can not exist in the batch of User set.
Rule Strategy
-
Fail fast
When one of the rule conditions is not met, return directly.
-
Full check
Running all the verification rules, verify all the rule items for its perperties.
How to solve it
There are some components which play an important role in KChain.
-
ChainContextThe context for the
chainwhich can hold the information you wanna use in the whole chain life circle.
Build in thecacheandinheritable cacheexpired in the current chain test life circle.
Such as some global parameters or special symbol. -
DataWrapperWrapping the
properties setand theRulecontexttogether. -
RuleContextIt is used to store the check result and the return flag bit of
Predicatebased on different check strategies. -
RuleIt contains some rules for checking.
There are three built-in rules for now:
-
testNotEmpty,whether the perperty value is empty based on the rule. -
testInCases,whether the perperty value is in the given collection (contains). -
testOnCustomized,the fully customized implementation rule extension.
-
-
RuleStrategyThe check strategy.
-
FULL_CHECK -
FAIL_FASTIt is usually used to check a single
perperties setto quickly know whether theperperties setis valid.
-
-
IChainThe interface of chain,build-in:
-
Predicatetest()
Mainly for the verification of a single
properties set, the verification rule of each property in theperperties setcan be configured.-
Functionapply()Mainly for the verification of batch of
properties set, the verification rule of the property between eachperperties setcan be configured.Build in the
duplicate rule.
-
-
ChainBuiler
Build the chain to use, build in.
How to use it
All the basic usage you can find in
demo/App.java.You can expand as much as you want, no matter the
Rule, or the implementations of getting property value.
Requests JDK8+, the core is using the @FunctionalInterface.
Import
- Maven
It has been published inGithub Packages, you can import it directly, more details see the packages.
<dependency>
<groupId>com.koy</groupId>
<artifactId>kchain</artifactId>
<version>${latest.version}</version>
</dependency>Demo
Map
Suppose that we need to verify the name and age in map. The rules are as follows:
In Single Map
namecannot emptyagecan not emptyageshould in the cases
In Map Collections
-
namecannot duplicate in collections -
agecannot duplicate in collections
Build the single properties set chain
namecannot emptyagecannot emptyageshould in[1,2,3,4,5]
@Override
public Predicate<MapDataWrapper> getPredicateChain(ChainContext ctx) {
return Rule.NOT_EMPTY.<MapDataWrapper>testNotEmpty("name"
, testEmptyRule("name")
, resultProcessor("name", CheckResultCode.NOT_EMPTY))
.and(Rule.NOT_EMPTY.testNotEmpty("age"
, testEmptyRule("age")
, resultProcessor("age", CheckResultCode.NOT_EMPTY)
))
.and(Rule.IN_CASES.testInCases("age",
CommonTestComponents.testInCasesRule(dataWrapper -> Integer.valueOf(dataWrapper.getString("age"))
, Arrays.asList(1, 2, 3, 4, 5))
, resultProcessor("age", CheckResultCode.IN_CASES)
));
}Build the batch properties sets chain
namecannot duplicated in batch of properties setsagecannot duplicated in batch of properties sets
@Override
public Function<List<MapDataWrapper>, List<MapDataWrapper>> getFunction(ChainContext ctx) {
return CommonTestComponents.<MapDataWrapper>testDuplicatedInCollection(ctx
, "name"
, dataWrapper -> true, dataWrapper -> dataWrapper.getString("name"))
.andThen(testDuplicatedInCollection(ctx
, "age"
, dataWrapper -> true
, dataWrapper -> dataWrapper.getString("age")));
}Usage
public static void demoOnMapBuilder(List<HashMap<String, Object>> maps) {
// Wrap data to DataWrapper
List<MapDataWrapper> mapDataWrappers = Lists.newArrayListWithCapacity(2);
for (HashMap<String, Object> map : maps) {
MapDataWrapper mapDataWrapper = new MapDataWrapper(map, new MapRuleContext(RuleStrategy.FULL_CHECK));
mapDataWrappers.add(mapDataWrapper);
}
// Build the chain with FULL_CHECK strategy
Chain<MapDataWrapper, List<MapDataWrapper>> chain = ChainBuilder.newBuilder()
.setChainContext(new ChainContext(RuleStrategy.FULL_CHECK))
.setChain(new MapPropertiesCheckChain())
.build();
// Verify the property in the map
// There use 6 threads execute it to make it speeder
chain.test(mapDataWrappers);
// Verify the rules between batch properties sets
chain.apply(mapDataWrappers);
// Show the result
for (MapDataWrapper mapDataWrapper : mapDataWrappers) {
System.out.println(mapDataWrapper.getRuleContext().getResult().toString());
}
}