/// <summary> /// Evaluates a condition group against a SifDataObject to determine if /// they are a match or not /// </summary> /// <param name="grp"></param> /// <param name="context"></param> /// <param name="culture"></param> /// <returns>True if the result of evaluating the condition groups is true</returns> /// <exception cref="OpenADK.Library.AdkSchemaException">If the condition contains references to invalid elements</exception> private bool EvaluateConditionGroup(SifXPathContext context, ConditionGroup grp, CultureInfo culture) { Condition[] conds = grp.Conditions; if (conds.Length > 0) { bool returnOnFirstMatch = grp.Operator == GroupOperator.Or ? true : false; foreach (Condition c in conds) { if ((EvaluateCondition(context, c, culture)) == returnOnFirstMatch) { // If this is an OR group, return true on the first match // If this is an AND Group, return false on the first failure return(returnOnFirstMatch); } } // None of the conditions matched the returnOnFirstMathValue. Therefore, // return the opposite value return(!returnOnFirstMatch); } else { return(EvaluateConditionGroups(context, grp.Operator, grp.Groups, culture)); } }
/// <summary> /// Add a condition to this query. /// </summary> /// <param name="condition">The condition to add. This condition is added to the root /// condition group.</param> /// <seealso cref="Query.RootConditionGroup"/> /// <seealso cref="Conditions"/> public void AddCondition(Condition condition) { if (fRoot == null) { fRoot = new ConditionGroup(GroupOperator.And); } fRoot.AddCondition(condition); }
/// <summary> Adds a nested ConditionGroup to this group</summary> /// <param name="group">The ConditionGroup to add to this group</param> public virtual void AddGroup(ConditionGroup group) { if (fConditions == null) { fConditions = new List <Object>(); } fConditions.Add(group); }
/// <summary> Constructs a Query object with no initial conditions or field /// restrictions. If conditions are subsequently added to the Query, they /// will be evaluated as a group with the logical AND operator. To specify /// that the logical OR operator be used, call the form of constructor that /// accepts an alternate operator. /// /// /// </summary> /// <param name="objectType">An ElementDef describing the object type to query (e.g. /// <c>Adk.Dtd.STUDENTPERSONAL</c>) /// </param> public Query(IElementDef objectType) { if (!objectType.Object) { throw new ArgumentException ("\"" + objectType.Name + "\" is not a root-level SIF Data Object"); } fObjType = objectType; fRoot = null; }
/// <summary> Constructs a Query object with one ConditionGroup where all conditions /// in the group are evaluated using the supplied grouping operator. All Conditions /// subsequently added to this Query will be placed into the ConditionGroup /// created by the constructor. /// /// This constructor is provided as a convenience so that callers do /// not have to explicitly create a ConditionGroup for simple queries. /// /// </summary> /// <param name="objectType">An ElementDef describing the object type to query (e.g. /// <c>StudentDTD.STUDENTPERSONAL</c>) /// </param> /// <param name="logicalOp">The logical operator that defines how to compare this group /// with other condition groups that comprise the query (e.g. Condition.OR) /// </param> public Query(IElementDef objectType, GroupOperator logicalOp) { if (!objectType.Object) { throw new ArgumentException ("\"" + objectType.Name + "\" is not a root-level SIF Data Object"); } fObjType = objectType; fRoot = new ConditionGroup(logicalOp); }
private void PopulateConditions(SIF_Query query, SIF_Condition[] clist, ConditionGroup target) { for (int i = 0; i < clist.Length; i++) { String o = clist[i].SIF_Operator; ComparisonOperators ops = Condition.ParseComparisionOperators(o); String val = clist[i].SIF_Value; String path = clist[i].SIF_Element; target.AddCondition(fObjType, path, ops, val); } }
/// <summary> Constructs a Query object from a SIF_QueryObject. /// /// This constructor is not typically called by agents but is used internally /// by the class framework. The other constructors can be used to safely /// create Query instances to request a specific SIF Data Object. Use the /// <c>addCondition</c> and <c>setFieldRestrictions</c> methods /// to further define the conditions and SIF elements specified by the query. /// /// </summary> /// <param name="query">A SIF_Query object received in a SIF_Request message /// </param> /// <exception cref="AdkUnknownOperatorException">If one of the operators in the SIF_Query is /// unrecognized by the ADK</exception> /// <exception cref="AdkSchemaException">If the object or elements defined in the query or /// not recognized by the ADK </exception> public Query(SIF_Query query) { SIF_QueryObject qo = query.SIF_QueryObject; if (qo == null) { throw new ArgumentException("SIF_Query must have a SIF_QueryObject element"); } fObjType = Adk.Dtd.LookupElementDef(qo.ObjectName); if (fObjType == null) { throw new AdkSchemaException (qo.ObjectName + " is not a recognized SIF Data Object, or the agent is not configured to support this object type"); } fRoot = null; SIF_ConditionGroup cg = query.SIF_ConditionGroup; if (cg != null && cg.GetSIF_Conditionses() != null) { GroupOperator grpOp; try { grpOp = Condition.ParseGroupOperator(cg.Type); } catch (AdkUnknownOperatorException) { grpOp = GroupOperator.None; } fRoot = new ConditionGroup(grpOp); SIF_Conditions[] sifConds = cg.GetSIF_Conditionses(); if (sifConds.Length == 1) { // There is one SIF_ConditionGroup with one SIF_Conditions, // so just add all of the conditions (no nested groups) string typ = sifConds[0].Type; if (typ == null) { throw new AdkSchemaException ("SIF_Conditions/@Type is a required attribute"); } fRoot.fOp = Condition.ParseGroupOperator(typ); SIF_Condition[] clist = sifConds[0].GetSIF_Conditions(); PopulateConditions(query, clist, fRoot); } else { // There are multiple SIF_Conditions, so add each as a nested // ConditionGroup of the fRoot for (int i = 0; i < sifConds.Length; i++) { ConditionGroup nested = new ConditionGroup(Condition.ParseGroupOperator(sifConds[i].Type)); PopulateConditions(query, sifConds[i].GetSIF_Conditions(), nested); fRoot.AddGroup(nested); } } } SifVersion[] reqVersions = null; // First, try to get the version from the SIF_Request Element parent = query.Parent; if (parent != null) { if (parent is SIF_Request) { SIF_Request request = (SIF_Request)parent; SifVersion[] versions = request.parseRequestVersions(Adk.Log); if (versions.Length > 0) { reqVersions = versions; } } } if (reqVersions == null) { SifVersion version = query.EffectiveSIFVersion; if (version != null) { reqVersions = new SifVersion[] { version }; } } if (reqVersions == null || reqVersions.Length == 0) { throw new ArgumentException( "SIF_Query is not contained in a SIF_Request that has a SIF_Version element; cannot determine version of SIF to associated with this Query object"); } else { fVersions = reqVersions; } SIF_Element[] fields = query.SIF_QueryObject.GetSIF_Elements(); if (fields != null && fields.Length > 0) { for (int i = 0; i < fields.Length; i++) { string xPath = fields[i].TextValue; if (xPath == null || xPath.Length == 0) { continue; } AddFieldRestriction(xPath); } } }
public void TestToXml() { // From the javadoc example ... // Query for student where the Last Name is Jones and the First Name is // Bob, and the graduation year is 2004, 2005, or 2006 ConditionGroup root = new ConditionGroup( GroupOperator.And ); ConditionGroup grp1 = new ConditionGroup( GroupOperator.And ); ConditionGroup grp2 = new ConditionGroup( GroupOperator.Or ); // For nested elements, you cannot reference a SifDtd constant. Instead, use // the lookupElementDefBySQL function to lookup an IElementDef constant // given a SIF Query Pattern (SQP) IElementDef lname = Adk.Dtd.LookupElementDefBySQP( StudentDTD.STUDENTPERSONAL, "Name/LastName" ); IElementDef fname = Adk.Dtd.LookupElementDefBySQP( StudentDTD.STUDENTPERSONAL, "Name/FirstName" ); grp1.AddCondition( lname, ComparisonOperators.EQ, "Jones" ); grp1.AddCondition( fname, ComparisonOperators.EQ, "Bob" ); grp2.AddCondition( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, ComparisonOperators.EQ, "2004" ); grp2.AddCondition( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, ComparisonOperators.EQ, "2005" ); grp2.AddCondition( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, ComparisonOperators.EQ, "2006" ); // Add condition groups to the root group root.AddGroup( grp1 ); root.AddGroup( grp2 ); // Query for student with the conditions prepared above by passing the // root ConditionGroup to the constructor Query query = new Query( StudentDTD.STUDENTPERSONAL, root ); query.AddFieldRestriction( StudentDTD.STUDENTPERSONAL_NAME ); // Now, call toXML() on the query object, reparse back into a Query object and assert all values String sifQueryXML = query.ToXml( SifVersion.LATEST ); Console.WriteLine( sifQueryXML ); SifParser parser = SifParser.NewInstance(); SIF_Request sifR = (SIF_Request) parser.Parse( "<SIF_Request>" + sifQueryXML + "</SIF_Request>", null ); Query reparsedQuery = new Query( sifR.SIF_Query ); Assert.AreEqual( StudentDTD.STUDENTPERSONAL, reparsedQuery.ObjectType, "Object Type should be StudentPersonal" ); Assert.AreEqual( 1, reparsedQuery.FieldRestrictions.Length, "Should have one field restriction" ); Assert.AreEqual( StudentDTD.STUDENTPERSONAL_NAME, reparsedQuery.FieldRestrictions[0], "Should be for StudentPersonal/Name" ); ConditionGroup newRoot = reparsedQuery.RootConditionGroup; Assert.AreEqual( StudentDTD.STUDENTPERSONAL, reparsedQuery.ObjectType, "Should be StudentPersonal" ); Assert.AreEqual( GroupOperator.And, newRoot.Operator, "Root should be an AND conditon" ); ConditionGroup[] groups = reparsedQuery.RootConditionGroup.Groups; Assert.AreEqual( 2, groups.Length, "Should have two groups" ); Assert.AreEqual( GroupOperator.And, groups[0].Operator, "First group should be AND" ); Assert.AreEqual( GroupOperator.Or, groups[1].Operator, "Second group should be OR" ); // Assert the first group conditions Condition[] newGrp1Conditions = groups[0].Conditions; Assert.AreEqual( 2, newGrp1Conditions.Length, "First group should have two conditions" ); // Assert the first condition Assert.AreEqual( ComparisonOperators.EQ, newGrp1Conditions[1].Operators, "First Condition EQ" ); Assert.AreEqual( lname, newGrp1Conditions[0].Field, "First Condition Field" ); Assert.AreEqual( "Jones", newGrp1Conditions[0].Value, "First Condition Value" ); // Assert the second condition Assert.AreEqual( ComparisonOperators.EQ, newGrp1Conditions[0].Operators, "Second Condition EQ" ); Assert.AreEqual( fname, newGrp1Conditions[1].Field, "First Condition Field" ); Assert.AreEqual( "Bob", newGrp1Conditions[1].Value, "First Condition Value" ); // Assert the second group conditions Condition[] newGrp2Conditions = groups[1].Conditions; Assert.AreEqual( 3, newGrp2Conditions.Length, "Second group should have three conditions" ); // Assert the first condition Assert.AreEqual( ComparisonOperators.EQ, newGrp2Conditions[0].Operators, "First Condition EQ" ); Assert.AreEqual( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, newGrp2Conditions[0].Field, "First Condition Field" ); Assert.AreEqual( "2004", newGrp2Conditions[0].Value, "First Condition Value" ); // Assert the second condition Assert.AreEqual( ComparisonOperators.EQ, newGrp2Conditions[1].Operators, "Second Condition EQ" ); Assert.AreEqual( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, newGrp2Conditions[1].Field, "Second Condition Field" ); Assert.AreEqual( "2005", newGrp2Conditions[1].Value, "Second Condition Value" ); // Assert the third condition Assert.AreEqual( ComparisonOperators.EQ, newGrp2Conditions[2].Operators, "Third Condition EQ" ); Assert.AreEqual( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR, newGrp2Conditions[2].Field, "Third Condition Field" ); Assert.AreEqual( "2006", newGrp2Conditions[2].Value, "Third Condition Value" ); }
/// <summary> /// Evaluates a condition group against a SifDataObject to determine if /// they are a match or not /// </summary> /// <param name="grp"></param> /// <param name="context"></param> /// <param name="culture"></param> /// <returns>True if the result of evaluating the condition groups is true</returns> /// <exception cref="OpenADK.Library.AdkSchemaException">If the condition contains references to invalid elements</exception> private bool EvaluateConditionGroup(SifXPathContext context, ConditionGroup grp, CultureInfo culture) { Condition[] conds = grp.Conditions; if (conds.Length > 0) { bool returnOnFirstMatch = grp.Operator == GroupOperator.Or ? true : false; foreach (Condition c in conds) { if ((EvaluateCondition(context, c, culture)) == returnOnFirstMatch) { // If this is an OR group, return true on the first match // If this is an AND Group, return false on the first failure return returnOnFirstMatch; } } // None of the conditions matched the returnOnFirstMathValue. Therefore, // return the opposite value return !returnOnFirstMatch; } else { return EvaluateConditionGroups(context, grp.Operator, grp.Groups, culture); } }
/// <summary> Constructs a Query object with a ConditionGroup. /// /// /// </summary> /// <param name="objectType">An ElementDef describing the object type to query (e.g. /// <c>StudentDtd.STUDENTPERSONAL</c>) /// </param> /// <param name="conditions">A ConditionGroup comprised of one or more query Conditions /// </param> public Query(IElementDef objectType, ConditionGroup conditions) { if (!objectType.Object) { throw new ArgumentException ("\"" + objectType.Name + "\" is not a root-level SIF Data Object"); } fObjType = objectType; fRoot = conditions; }
/// <summary> /// Evaluates the condition groups and returns True if the Operator is OR and at least /// one of the groups evaluates to TRUE. If the Operator is AND, all of the condition /// groups have to evaluate to TRUE /// </summary> /// <param name="op"></param> /// <param name="grps"></param> /// <param name="context"></param> /// <param name="culture"></param> /// <returns></returns> /// <exception cref="OpenADK.Library.AdkSchemaException">If the condition contains references to invalid elements</exception> private bool EvaluateConditionGroups(SifXPathContext context, GroupOperator op, ConditionGroup[] grps, CultureInfo culture) { bool isMatch = true; for (int c = 0; c < grps.Length; c++) { bool singleMatch = EvaluateConditionGroup(context, grps[c], culture); if (op == GroupOperator.Or) { if (singleMatch) { // In OR mode, return as soon as we evaluate to True return true; } isMatch |= singleMatch; } else { isMatch &= singleMatch; } // As soon as the evaluation fails, return if (!isMatch) { return false; } } return isMatch; }
public void testComplexOrWithGTFilter() { ConditionGroup fail = new ConditionGroup( GroupOperator.None ); // This condition should fail fail.AddCondition( InfrastructureDTD.AUTHENTICATION_REFID, ComparisonOperators.NE, REFID_GUID ); ConditionGroup pass = new ConditionGroup( GroupOperator.Or ); // This condition should fail pass.AddCondition( InfrastructureDTD.AUTHENTICATIONINFO_USERNAME, ComparisonOperators.EQ, "FAIL" ); pass.AddCondition( InfrastructureDTD.AUTHENTICATIONINFO_USERNAME, ComparisonOperators.GT, "a" ); ConditionGroup root = new ConditionGroup( GroupOperator.Or ); root.AddGroup( fail ); root.AddGroup( pass ); Query q = new Query( InfrastructureDTD.AUTHENTICATION, root ); Authentication auth = BuildAuthentication(); Assert.IsTrue( q.Evaluate( auth ) ); }
/// <summary> Adds a nested ConditionGroup to this group</summary> /// <param name="group">The ConditionGroup to add to this group</param> public virtual void AddGroup( ConditionGroup group ) { if ( fConditions == null ) { fConditions = new List<Object>(); } fConditions.Add( group ); }