@@ -5,6 +5,7 @@ namespace ConstraintsMatcher
55 using System ;
66 using System . Collections . Generic ;
77 using System . Linq ;
8+ using System . Text . RegularExpressions ;
89
910 public class Matcher
1011 {
@@ -30,6 +31,7 @@ public Matcher(IModel model)
3031 public bool PreCheck ( IModel constraintsModel )
3132 {
3233 var Nodes = new List < INode > ( ) ;
34+ //Find the root
3335 foreach ( var node in constraintsModel . Nodes )
3436 {
3537 var inEdges = constraintsModel . Edges . Where ( x => x . To == node ) . ToList ( ) ;
@@ -44,11 +46,13 @@ public bool PreCheck(IModel constraintsModel)
4446 return false ;
4547 }
4648 this . root = Nodes . FirstOrDefault ( ) ;
49+ // Check if root is correct
4750 if ( ( this . root . Class . Name == "NotNode" ) || ( this . root . Class . Name == "OrNode" ) || ( this . root . Class . Name == "NoNodes" ) )
4851 {
49- this . ErrorMsg = "The root should be NodeType from modrl or AllNodes." ;
52+ this . ErrorMsg = "The root should be NodeType from model or AllNodes." ;
5053 return false ;
5154 }
55+ // Check ther there is only one outcoming edge from notNode
5256 var notNodes = constraintsModel . Nodes . Where ( x => x . Class . Name == "NotNode" ) ;
5357 foreach ( var notNode in notNodes )
5458 {
@@ -57,13 +61,42 @@ public bool PreCheck(IModel constraintsModel)
5761 return false ;
5862 }
5963 }
60- //TODO check if tree
64+ // Check if this constraint is a tree
65+ var visited = new HashSet < int > ( ) ;
66+ if ( ! this . CheckIffTree ( constraintsModel , this . root , visited ) )
67+ {
68+ this . ErrorMsg = "Constraints graph should have a tree structure." ;
69+ return false ;
70+ }
71+
6172 return true ;
6273 }
6374
75+ public bool CheckIffTree ( IModel constraintsModel , INode root , HashSet < int > visited )
76+ {
77+ visited . Add ( root . GetHashCode ( ) ) ;
78+ var outgoingEdges = constraintsModel . Edges . Where ( x => x . From == root ) ;
79+ foreach ( var edge in outgoingEdges )
80+ {
81+ if ( visited . Any ( x => x == edge . To . GetHashCode ( ) ) )
82+ {
83+ return false ;
84+ }
85+ if ( ! CheckIffTree ( constraintsModel , ( INode ) edge . To , visited ) )
86+ {
87+ return false ;
88+ }
89+ }
90+ return true ;
91+ }
6492 public bool Check ( INode originRoot , INode constraintsRoot , IModel constraintsModel )
6593 {
66- return this . InnerCheck ( originRoot , constraintsRoot , constraintsModel ) ;
94+ return this . InnerCheck ( originRoot , constraintsRoot , constraintsModel ) ;
95+ }
96+
97+ public bool AttrCheck ( INode originRoot , INode constraintsRoot )
98+ {
99+ return this . AttributesAreIdentic ( originRoot , constraintsRoot ) ;
67100 }
68101
69102 private bool InnerCheck ( INode targetRoot , INode constraintsRoot , IModel constraintsModel )
@@ -104,7 +137,7 @@ private bool InnerCheck(INode targetRoot, INode constraintsRoot, IModel constrai
104137 var constraintsToRoot = ( INode ) outConstraintsEdges . FirstOrDefault ( ) . To ;
105138 var targetParentRoot = ( INode ) this . targetModel . Edges . Where ( x => x . To == targetRoot ) . FirstOrDefault ( ) . From ;
106139 var outParentTargetEdges = this . targetModel . Edges . Where ( x => x . From == targetParentRoot ) ;
107- var innerCheck = outParentTargetEdges . Any ( x => ElementsAreIdentic ( constraintParentEdge , x ) && this . InnerCheck ( ( INode ) x . To , constraintsToRoot , constraintsModel ) ) ;
140+ var innerCheck = outParentTargetEdges . Any ( x => ElementsAreIdentic ( x , constraintParentEdge ) && this . InnerCheck ( ( INode ) x . To , constraintsToRoot , constraintsModel ) ) ;
108141 return ! innerCheck ;
109142 }
110143 if ( ( outConstraintsEdges . Count ( ) > 0 ) && ( outConstraintsEdges . FirstOrDefault ( ) . To . Class . Name == "NoNodes" ) )
@@ -161,5 +194,19 @@ public bool ElementsAreIdentic(IElement firstElement, IElement secondElement)
161194 }
162195 return true ;
163196 }
197+
198+ public bool AttributesAreIdentic ( IElement targetElement , IElement constraintsElement )
199+ {
200+ foreach ( var targetAttr in targetElement . Attributes )
201+ {
202+ var constraintsAttr = constraintsElement . Attributes . Where ( x => x . Name == targetAttr . Name ) . FirstOrDefault ( ) ;
203+ Regex regEx = new Regex ( constraintsAttr . StringValue ) ;
204+ if ( ! regEx . IsMatch ( targetAttr . StringValue ) )
205+ {
206+ return false ;
207+ }
208+ }
209+ return true ;
210+ }
164211 }
165212}
0 commit comments