目标:用组合模式实现规则的校验。
首先设计一个规则表,包括member_level、rule_type、condition_key、condition_value等字段。然后用树形结构来拼装规则,根节点是道具规格版本的id,第一层树枝节点是member_level,第二层是rule_type,第三层就是叶节点了,叶节点存储的是个map,map的key是condition_key,value是condition_value。
注意:
1.每个规则类型rule_type下可以有很多对condition_key、condition_value,只要满足其中任意一对即是满足了这种rule_type规则了。
2.必须符合同一member_level下的所有的rule_type分支,如果某条记录的member_level字段为空,表示该规则适用于所有member_level,因此会将这条规则拼在所有等级的规则树里。
3.通过上述1和2两条规则实现了对规则的与、或的灵活组合,可根据实际业务需求调用不同的RuleOperate类中的静态方法isAllEmptyLeaves对并的规则进行验证、isHaveEmptyLeaves对与的规则进行校验。
public abstract class Node<T> {
private int position;
private String key;
private T value;
public Node(int _position,String _key,T _value){
this.position = _position;
this.key = _key;
this.value = _value;
}
public int getPosition(){
return position;
}
public String getKey(){
return key;
}
public T getValue(){
return value;
}
}
public class Branch<T> extends Node{
ArrayList<Node> children = new ArrayList<Node>();
public Branch(int _position,String _key,T _value){
super(_position,_key,_value);
}
public void addChild(Node node) {
this.children.add(node);
}
public ArrayList<Node> getChildren() {
return this.children;
}
public void setChildrenSizeTo0(){
this.children = new ArrayList<Node>();
}
public void print(){
String str = "position:"+getPosition()+" key:"+getKey()+" +value:"+getValue();
System.out.println(str);
}
}
public class Leaf<T> extends Node{
public Leaf(int _position,String _key,T _value){
super(_position,_key,_value);
}
public void print(){
String str = "position:"+getPosition()+" key:"+getKey()+" +value:"+getValue();
System.out.println(str);
}
}
public class RuleOperate {
public static Branch createRuleTree(List<TmallPropRuleConfineDO> lst){
if(lst!=null&&lst.size()>0){
Branch root = new Branch(0,"id",lst.get(0).getPropItemId()==0l?lst.get(0).getPropId():lst.get(0).getPropItemId());
for (TmallPropRuleConfineDO aLst : lst) {
Node matchNode = findContainsNode(root, aLst);
//遍历树,如果没有匹配的节点则新建,如果有匹配的节点则延该路径继续遍历
if (matchNode.getPosition() == 0) {
Branch f1 = new Branch(1, "member_level", aLst.getMemberLevel());
Branch f2 = new Branch(2, "rule_type", aLst.getRuleType());
Map leafPart = new HashMap();
leafPart.put(aLst.getConditionKey(), aLst.getConditionValue());
Leaf leaf = new Leaf(3, "condition", leafPart);
root.addChild(f1);
f1.addChild(f2);
f2.addChild(leaf);
} else if (matchNode.getPosition() == 1) {
Branch f2 = new Branch(2, "rule_type", aLst.getRuleType());
Map leafPart = new HashMap();
leafPart.put(aLst.getConditionKey(), aLst.getConditionValue());
Leaf leaf = new Leaf(3, "condition", leafPart);
((Branch) matchNode).addChild(f2);
f2.addChild(leaf);
} else if (matchNode.getPosition() == 2) {
ArrayList<Node> leafNodes = ((Branch) matchNode).getChildren();
if (leafNodes.size() == 0) {
Map leafPart = new HashMap();
leafPart.put(aLst.getConditionKey(), aLst.getConditionValue());
Leaf leaf = new Leaf(3, "condition", leafPart);
((Branch) matchNode).addChild(leaf);
} else {
Map existPart = (Map) leafNodes.get(0).getValue();
existPart.put(aLst.getConditionKey(), aLst.getConditionValue());
}
}
}
return root;
}else{
return null;
}
}
public static Node findContainsNode(Branch branch,TmallPropRuleConfineDO ruleConfineDO){
Node node = branch;
ArrayList<Node> children = branch.getChildren();
int i = 0;
for(Node node1 :children){
int position = node1.getPosition();
if(i<children.size()){
//依次遍历子节点中的每一个
switch(position){
case 1:
if((Integer)node1.getValue()==ruleConfineDO.getMemberLevel()){
node = findContainsNode((Branch)node1,ruleConfineDO);
}
break;
case 2:
if((Integer)node1.getValue()==ruleConfineDO.getRuleType()){
node = findContainsNode((Branch)node1,ruleConfineDO);
}
break;
case 3:
return node;//尽管已经匹配到叶子节点,但仍返回的是其上一层
default: i++;break;
}//switch
}else{//当i已经>=子节点数,即在children中没有找到,则返回上一层的node
return branch;
}
}
return node;
}
public static Branch deleteTree(Branch branch,List<TmallPropRuleConfineDO> ruleConfines){
Map map = new HashMap();
for(int i = 0 ; i < ruleConfines.size() ; i++){
TmallPropRuleConfineDO ruleConfine = ruleConfines.get(i);
Node matchNode = findContainsNode(branch,ruleConfine);
if(matchNode.getPosition()==2){
ArrayList<Leaf> leafNodes = ((Branch)matchNode).getChildren();
if(leafNodes!=null && leafNodes.size()>0){
Map existPart = (Map) leafNodes.get(0).getValue();
if(ruleConfine.getConditionValue()==null && (existPart.get(ruleConfine.getConditionKey())==null||"".equals(existPart.get(ruleConfine.getConditionKey())))){
((Branch)matchNode).setChildrenSizeTo0();
}else if(ruleConfine.getConditionValue().equals(existPart.get(ruleConfine.getConditionKey()))){
map.put(ruleConfine.getConditionKey(), ruleConfine.getConditionValue());
}
if(i == ruleConfines.size()-1 && existPart.equals(map)){
((Branch)matchNode).setChildrenSizeTo0();
}
}
}
}
return branch;
}
public static boolean isAllEmptyLeaves(Branch branch){
boolean boo = true;
ArrayList<Node> children = branch.getChildren();
for (Node childNode : children) {
if (childNode.getPosition()==2) {
if(((Branch)childNode).getChildren().size()==0){
continue;
}else{
boo = false;
break;
}
}
boo = isAllEmptyLeaves((Branch)childNode);
}
return boo;
}
public static boolean isHaveEmptyLeaves(Branch branch,TmallPropRuleConfineDO ruleConfineDO){
boolean boo = false;
Node matchNode= findContainsNode(branch,ruleConfineDO);
if(matchNode.getPosition()==2){
if(((Branch) matchNode).getChildren().size()==0){
boo = true;
}
}
return boo;
}
}