目標:用組合模式實現規則的校驗。
首先設計一個規則表,包括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;
}
}