/// <summary>
        /// Writes the advice.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <param name="data">The data.</param>
        protected virtual void WriteAdvice(XmlWriter writer, XacmlAdvice data) {
            Contract.Requires<ArgumentNullException>(writer != null);
            Contract.Requires<ArgumentNullException>(data != null);

            writer.WriteStartElement(XacmlConstants.Prefixes.Policy, XacmlConstants.ElementNames.Advice, this.version.NamespacePolicy);
            writer.WriteAttributeString(XacmlConstants.AttributeNames.AdviceId, data.AdviceId.OriginalString);

            foreach (var attributeAssigment in data.AttributeAssignment) {
                this.WriteAttributeAssignment(writer, attributeAssigment);
            }

            writer.WriteEndElement();
        }
        public override XacmlDecisionResult PolicyEvaluate(XacmlPolicy policy) {
            XacmlPolicy previousPolicy = this.currentEvaluatingPolicy;
            this.currentEvaluatingPolicy = policy;

            ///// <Target>                <Rule>                                      <Policy>
            ///// "Match"                 Don’t care                                  Specified by the rulecombining algorithm
            ///// “No-match”              Don’t care                                  “NotApplicable”
            ///// “Indeterminate”         See Table 7                                 See Table 7
            XacmlDecisionResult algResult = XacmlDecisionResult.Indeterminate;
            // Wrap for Obligations and Advice, read more on AttributeAssignmentsWrapper class description
            using (AttributeAssignmentsWrapper<XacmlObligation> obligationWrapper = new AttributeAssignmentsWrapper<XacmlObligation>(() => this.obligations, o => this.obligations = o, () => algResult)) {
                using (AttributeAssignmentsWrapper<XacmlAdvice> adviceWrapper = new AttributeAssignmentsWrapper<XacmlAdvice>(() => this.advices, o => this.advices = o, () => algResult)) {
                    // Target
                    XacmlMatchResult targetResult;
                    targetResult = this.TargetEvaluate(policy.Target);

                    if (targetResult == XacmlMatchResult.NoMatch) {
                        return XacmlDecisionResult.NotApplicable;
                    }

                    // Rules
                    List<Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>> ruleResultsFunctions = new List<Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>>();

                    foreach (XacmlRule rule in policy.Rules) {
                        ruleResultsFunctions.Add(new Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>(
                            policy.RuleCombinerParameters.Where(o => string.Equals(o.RuleIdRef, rule.RuleId)).SelectMany(o => o.CombinerParameters),
                            new Dictionary<string, Func<object>>()
                            {
                                {
                                    "evaluate",
                                    () => this.RuleEvaluate(rule)
                                }
                            }));
                    }

                    algResult = this.algorithms[policy.RuleCombiningAlgId.ToString()].Invoke(ruleResultsFunctions,
                        policy.CombinerParameters.Concat(policy.ChoiceCombinerParameters));

                    this.currentEvaluatingPolicy = previousPolicy;

                    if (targetResult == XacmlMatchResult.Indeterminate) {
                        algResult = this.SpecifyCombiningAlgorithmResult(algResult);
                    }

                    // Permit
                    if (algResult == XacmlDecisionResult.Permit) {
                        if (policy.ObligationExpressions.Count > 0) {
                            IEnumerable<XacmlObligationExpression> obligationsWithPermit = policy.ObligationExpressions.Where(o => o.FulfillOn == XacmlEffectType.Permit);
                            foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return XacmlDecisionResult.Indeterminate;
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                this.obligations[expression.FulfillOn].Add(obligation);
                            }
                        }

                        if (policy.AdviceExpressions.Count > 0) {
                            IEnumerable<XacmlAdviceExpression> advicesWithPermit = policy.AdviceExpressions.Where(o => o.AppliesTo == XacmlEffectType.Permit);
                            foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return XacmlDecisionResult.Indeterminate;
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                this.advices[expression.AppliesTo].Add(advice);
                            }
                        }
                    }

                    // Deny
                    if (algResult == XacmlDecisionResult.Deny) {
                        if (policy.ObligationExpressions.Count > 0) {
                            IEnumerable<XacmlObligationExpression> obligationsWithPermit = policy.ObligationExpressions.Where(o => o.FulfillOn == XacmlEffectType.Deny);
                            foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return XacmlDecisionResult.Indeterminate;
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                this.obligations[expression.FulfillOn].Add(obligation);
                            }
                        }

                        if (policy.AdviceExpressions.Count > 0) {
                            IEnumerable<XacmlAdviceExpression> advicesWithPermit = policy.AdviceExpressions.Where(o => o.AppliesTo == XacmlEffectType.Deny);
                            foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return XacmlDecisionResult.Indeterminate;
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                this.advices[expression.AppliesTo].Add(advice);
                            }
                        }
                    }
                }
            }

            // add applicaple policies for PolicyIdentifierList in response
            if (algResult == XacmlDecisionResult.Permit) {
                this.applicablePolicies[XacmlEffectType.Permit].Add(new XacmlContextPolicyIdReference() {
                    Value = policy.PolicyId.OriginalString,
                    Version = new XacmlVersionMatchType(policy.Version)
                });
            }
            if (algResult == XacmlDecisionResult.Deny) {
                this.applicablePolicies[XacmlEffectType.Deny].Add(new XacmlContextPolicyIdReference() {
                    Value = policy.PolicyId.OriginalString,
                    Version = new XacmlVersionMatchType(policy.Version)
                });
            }

            return algResult;
        }
        protected override Tuple<XacmlDecisionResult, string> RuleEvaluate(XacmlRule rule) {
            ///// <Target>                        <Condition>         <Rule>
            ///// "Match" or no target            "True"              Effect
            ///// "Match" or no target            "False"             "NotApplicable"
            ///// "Match" or no target            "Indeterminate"     “Indeterminate{P}” if the Effect is Permit, or “Indeterminate{D}” if the Effect is Deny
            ///// "NoMatch"                        Don`t care          "NotApplicable"
            ///// "Indeternimate"                  Don`t care          “Indeterminate{P}” if the Effect is Permit, or “Indeterminate{D}” if the Effect is Deny
            XacmlDecisionResult ruleResult = XacmlDecisionResult.Indeterminate;

            // Wrap for Obligations and Advice, read more on AttributeAssignmentsWrapper class description
            using (AttributeAssignmentsWrapper<XacmlObligation> obligationWrapper = new AttributeAssignmentsWrapper<XacmlObligation>(() => this.obligations, o => this.obligations = o, () => ruleResult)) {
                using (AttributeAssignmentsWrapper<XacmlAdvice> adviceWrapper = new AttributeAssignmentsWrapper<XacmlAdvice>(() => this.advices, o => this.advices = o, () => ruleResult)) {
                    // Target
                    // If this element is omitted, then the target for the <Rule> SHALL be defined by the <Target> element of the enclosing <Policy> element.
                    XacmlTarget target = rule.Target ?? this.currentEvaluatingPolicy.Target;
                    XacmlMatchResult targetResult = this.TargetEvaluate(target);

                    if (targetResult == XacmlMatchResult.NoMatch) {
                        return new Tuple<XacmlDecisionResult, string>(XacmlDecisionResult.NotApplicable, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                    }

                    if (targetResult == XacmlMatchResult.Indeterminate) {
                        return new Tuple<XacmlDecisionResult, string>(rule.Effect == XacmlEffectType.Permit ? XacmlDecisionResult.IndeterminateP : XacmlDecisionResult.IndeterminateD, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                    }

                    // Condition
                    // if XACML v 1.0
                    // The condition value SHALL be "True" if the <Condition> element is absent
                    bool? conditionResult = true;
                    if (rule.Condition != null) {
                        conditionResult = this.ConditionEvaluate(rule.Condition);
                    }

                    // Target is Match
                    if (!conditionResult.HasValue) {
                        ruleResult = rule.Effect == XacmlEffectType.Permit ? XacmlDecisionResult.IndeterminateP : XacmlDecisionResult.IndeterminateD;
                    }
                    else if (conditionResult.Value) {
                        ruleResult = (XacmlDecisionResult)(Enum.Parse(typeof(XacmlDecisionResult), Enum.GetName(typeof(XacmlEffectType), rule.Effect)));
                    }
                    else {
                        ruleResult = XacmlDecisionResult.NotApplicable;
                    }

                    // Permit
                    if (ruleResult == XacmlDecisionResult.Permit) {
                        if (rule.Obligations.Count > 0) {
                            IEnumerable<XacmlObligationExpression> obligationsWithPermit = rule.Obligations.Where(o => o.FulfillOn == XacmlEffectType.Permit);
                            foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return new Tuple<XacmlDecisionResult, string>(XacmlDecisionResult.Indeterminate, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                this.obligations[expression.FulfillOn].Add(obligation);
                            }
                        }

                        if (rule.Advices.Count > 0) {
                            IEnumerable<XacmlAdviceExpression> advicesWithPermit = rule.Advices.Where(o => o.AppliesTo == XacmlEffectType.Permit);
                            foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return new Tuple<XacmlDecisionResult, string>(XacmlDecisionResult.Indeterminate, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                this.advices[expression.AppliesTo].Add(advice);
                            }
                        }
                    }

                    // Deny
                    if (ruleResult == XacmlDecisionResult.Deny) {
                        if (rule.Obligations.Count > 0) {
                            IEnumerable<XacmlObligationExpression> obligationsWithPermit = rule.Obligations.Where(o => o.FulfillOn == XacmlEffectType.Deny);
                            foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return new Tuple<XacmlDecisionResult, string>(XacmlDecisionResult.Indeterminate, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                this.obligations[expression.FulfillOn].Add(obligation);
                            }
                        }

                        if (rule.Advices.Count > 0) {
                            IEnumerable<XacmlAdviceExpression> advicesWithPermit = rule.Advices.Where(o => o.AppliesTo == XacmlEffectType.Deny);
                            foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                    IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                    // ja Indeterminate, tad rezultāts arī
                                    if (assignment == null) {
                                        return new Tuple<XacmlDecisionResult, string>(XacmlDecisionResult.Indeterminate, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
                                    }

                                    attributeAssigments.AddRange(assignment);
                                }

                                XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                this.advices[expression.AppliesTo].Add(advice);
                            }
                        }
                    }
                }
            }

            return new Tuple<XacmlDecisionResult, string>(ruleResult, Enum.GetName(typeof(XacmlEffectType), rule.Effect));
        }
        public override XacmlDecisionResult PolicySetEvaluate(XacmlPolicySet policySet) {
            ///// <Target>                <Policy>                                    <Policy Set>
            ///// "Match"                 Don’t care                                  Specified by the rulecombining algorithm
            ///// “No-match”              Don’t care                                  “NotApplicable”
            ///// “Indeterminate”         See Table 7                                 See Table 7
            XacmlDecisionResult algResult = XacmlDecisionResult.Indeterminate;
            // Wrap for Obligations and Advice, read more on AttributeAssignmentsWrapper class description
            using (AttributeAssignmentsWrapper<XacmlObligation> obligationWrapper = new AttributeAssignmentsWrapper<XacmlObligation>(() => this.obligations, o => this.obligations = o, () => algResult)) {
                using (AttributeAssignmentsWrapper<XacmlAdvice> adviceWrapper = new AttributeAssignmentsWrapper<XacmlAdvice>(() => this.advices, o => this.advices = o, () => algResult)) {
                    using (AttributeAssignmentsWrapper<XacmlContextPolicyIdReference> policyRefWrapper = new AttributeAssignmentsWrapper<XacmlContextPolicyIdReference>(() => this.applicablePolicies, o => this.applicablePolicies = o, () => algResult)) {
                        using (AttributeAssignmentsWrapper<XacmlContextPolicySetIdReference> policySetRefWrapper = new AttributeAssignmentsWrapper<XacmlContextPolicySetIdReference>(() => this.applicablePolicySets, o => this.applicablePolicySets = o, () => algResult)) {
                            // Target
                            XacmlMatchResult targetResult;
                            targetResult = this.TargetEvaluate(policySet.Target);

                            if (targetResult == XacmlMatchResult.NoMatch) {
                                return XacmlDecisionResult.NotApplicable;
                            }

                            // Policy
                            List<Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>> policyResultsFunctions = new List<Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>>();

                            bool atLeastOnePolicy = policySet.Policies.Any()
                                || policySet.PolicySets.Any()
                                || policySet.PolicyIdReferences_3_0.Any()
                                || policySet.PolicySetIdReferences_3_0.Any();

                            // Policies
                            foreach (XacmlPolicy pol in policySet.Policies) {
                                policyResultsFunctions.Add(new Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>(
                                    policySet.PolicyCombinerParameters.Where(o => string.Equals(o.PolicyIdRef.OriginalString, pol.PolicyId.OriginalString)).SelectMany(o => o.CombinerParameters),
                                    new Dictionary<string, Func<object>>()
                            {
                                {
                                    "evaluate",
                                    () => new Tuple<XacmlDecisionResult, string>(this.PolicyEvaluate(pol), string.Empty)
                                },
                                {
                                    "isApplicable",
                                    () =>
                                    {
                                        XacmlMatchResult policyTargetResult = this.TargetEvaluate(pol.Target);
                                        if(policyTargetResult == XacmlMatchResult.Indeterminate)
                                        {
                                            return null;
                                        }

                                        if (policyTargetResult == XacmlMatchResult.Match)
                                        {
                                            return true;
                                        }

                                        return false;
                                    }
                                }
                            }));
                            }

                            // PolicySets
                            foreach (XacmlPolicySet pol in policySet.PolicySets) {
                                policyResultsFunctions.Add(new Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>(
                                    policySet.PolicySetCombinerParameters.Where(o => string.Equals(o.PolicySetIdRef.OriginalString, pol.PolicySetId.OriginalString)).SelectMany(o => o.CombinerParameters),
                                    new Dictionary<string, Func<object>>()
                            {
                                {
                                    "evaluate",
                                    () => new Tuple<XacmlDecisionResult, string>(this.PolicySetEvaluate(pol), string.Empty)
                                },
                                {
                                    "isApplicable",
                                    () =>
                                    {
                                        XacmlMatchResult policyTargetResult = this.TargetEvaluate(pol.Target);
                                        if(policyTargetResult == XacmlMatchResult.Indeterminate)
                                        {
                                            return null;
                                        }

                                        if (policyTargetResult == XacmlMatchResult.Match)
                                        {
                                            return true;
                                        }

                                        return false;
                                    }
                                }
                            }));
                            }

                            // Policy References
                            foreach (XacmlContextPolicyIdReference polRef in policySet.PolicyIdReferences_3_0) {
                                Uri uri;
                                if (Uri.TryCreate(polRef.Value, UriKind.RelativeOrAbsolute, out uri)) {
                                    XacmlPolicy pol = this.ch.RequestPolicy(uri);
                                    if (pol == null) {
                                        throw new XacmlIndeterminateException("Unknown Policy reference: " + polRef.ToString());
                                    }

                                    policyResultsFunctions.Add(new Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>(
                                    policySet.PolicyCombinerParameters.Where(o => string.Equals(o.PolicyIdRef.OriginalString, pol.PolicyId.OriginalString)).SelectMany(o => o.CombinerParameters),
                                    new Dictionary<string, Func<object>>()
                            {
                                {
                                    "evaluate",
                                    () => new Tuple<XacmlDecisionResult, string>(this.PolicyEvaluate(pol), string.Empty)
                                },
                                {
                                    "isApplicable",
                                    () =>
                                    {
                                        XacmlMatchResult policyTargetResult = this.TargetEvaluate(pol.Target);
                                        if(policyTargetResult == XacmlMatchResult.Indeterminate)
                                        {
                                            return null;
                                        }

                                        if (policyTargetResult == XacmlMatchResult.Match)
                                        {
                                            return true;
                                        }

                                        return false;
                                    }
                                }
                            }));
                                }
                                else {
                                    throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperFatal("Policy reference not URI - Not implemented", new NotImplementedException("Policy reference not URI - Not implemented"));
                                }
                            }

                            // PolicySet References
                            foreach (XacmlContextPolicySetIdReference polRef in policySet.PolicySetIdReferences_3_0) {
                                Uri uri;
                                if (Uri.TryCreate(polRef.Value, UriKind.RelativeOrAbsolute, out uri)) {
                                    XacmlPolicySet pol = this.ch.RequestPolicySet(uri);
                                    if (pol == null) {
                                        throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperError(new XacmlIndeterminateException("Unknown PolicySet reference: " + polRef.ToString()));
                                    }

                                    policyResultsFunctions.Add(new Tuple<IEnumerable<XacmlCombinerParameter>, IDictionary<string, Func<object>>>(
                                    policySet.PolicySetCombinerParameters.Where(o => string.Equals(o.PolicySetIdRef.OriginalString, pol.PolicySetId.OriginalString)).SelectMany(o => o.CombinerParameters),
                                    new Dictionary<string, Func<object>>()
                            {
                                {
                                    "evaluate",
                                    () => new Tuple<XacmlDecisionResult, string>(this.PolicySetEvaluate(pol), string.Empty)
                                },
                                {
                                    "isApplicable",
                                    () =>
                                    {
                                        XacmlMatchResult policyTargetResult = this.TargetEvaluate(pol.Target);
                                        if(policyTargetResult == XacmlMatchResult.Indeterminate)
                                        {
                                            return null;
                                        }

                                        if (policyTargetResult == XacmlMatchResult.Match)
                                        {
                                            return true;
                                        }

                                        return false;
                                    }
                                }
                            }));
                                }
                                else {
                                    throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperFatal("PolicySet reference not URI - Not implemented", new NotImplementedException("PolicySet reference not URI - Not implemented"));
                                }
                            }

                            algResult = this.algorithms[policySet.PolicyCombiningAlgId.ToString()].Invoke(policyResultsFunctions,
                                policySet.CombinerParameters);

                            if (targetResult == XacmlMatchResult.Indeterminate) {
                                algResult = this.SpecifyCombiningAlgorithmResult(algResult);
                            }

                            // Permit
                            if (algResult == XacmlDecisionResult.Permit) {
                                if (policySet.Obligations_3_0.Count > 0) {
                                    IEnumerable<XacmlObligationExpression> obligationsWithPermit = policySet.Obligations_3_0.Where(o => o.FulfillOn == XacmlEffectType.Permit);
                                    foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                        List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                        foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                            IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                            // ja Indeterminate, tad rezultāts arī
                                            if (assignment == null) {
                                                return XacmlDecisionResult.Indeterminate;
                                            }

                                            attributeAssigments.AddRange(assignment);
                                        }

                                        XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                        this.obligations[expression.FulfillOn].Add(obligation);
                                    }
                                }

                                if (policySet.Advices.Count > 0) {
                                    IEnumerable<XacmlAdviceExpression> advicesWithPermit = policySet.Advices.Where(o => o.AppliesTo == XacmlEffectType.Permit);
                                    foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                        List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                        foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                            IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                            // ja Indeterminate, tad rezultāts arī
                                            if (assignment == null) {
                                                return XacmlDecisionResult.Indeterminate;
                                            }

                                            attributeAssigments.AddRange(assignment);
                                        }

                                        XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                        this.advices[expression.AppliesTo].Add(advice);
                                    }
                                }

                                this.applicablePolicySets[XacmlEffectType.Permit].Add(new XacmlContextPolicySetIdReference() {
                                    Value = policySet.PolicySetId.OriginalString,
                                    Version = new XacmlVersionMatchType(policySet.Version)
                                });
                            }

                            // Deny
                            if (algResult == XacmlDecisionResult.Deny) {
                                if (policySet.Obligations_3_0.Count > 0) {
                                    IEnumerable<XacmlObligationExpression> obligationsWithPermit = policySet.Obligations_3_0.Where(o => o.FulfillOn == XacmlEffectType.Deny);
                                    foreach (XacmlObligationExpression expression in obligationsWithPermit) {
                                        List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                        foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                            IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                            // ja Indeterminate, tad rezultāts arī
                                            if (assignment == null) {
                                                return XacmlDecisionResult.Indeterminate;
                                            }

                                            attributeAssigments.AddRange(assignment);
                                        }

                                        XacmlObligation obligation = new XacmlObligation(expression.ObligationId, attributeAssigments);
                                        this.obligations[expression.FulfillOn].Add(obligation);
                                    }
                                }

                                if (policySet.Advices.Count > 0) {
                                    IEnumerable<XacmlAdviceExpression> advicesWithPermit = policySet.Advices.Where(o => o.AppliesTo == XacmlEffectType.Deny);
                                    foreach (XacmlAdviceExpression expression in advicesWithPermit) {
                                        List<XacmlAttributeAssignment> attributeAssigments = new List<XacmlAttributeAssignment>();
                                        foreach (XacmlAttributeAssignmentExpression ex in expression.AttributeAssignmentExpressions) {
                                            IEnumerable<XacmlAttributeAssignment> assignment = this.AttributeAssignmentExpressionEvaluate(ex);
                                            // ja Indeterminate, tad rezultāts arī
                                            if (assignment == null) {
                                                return XacmlDecisionResult.Indeterminate;
                                            }

                                            attributeAssigments.AddRange(assignment);
                                        }

                                        XacmlAdvice advice = new XacmlAdvice(expression.AdviceId, attributeAssigments);
                                        this.advices[expression.AppliesTo].Add(advice);
                                    }
                                }

                                this.applicablePolicySets[XacmlEffectType.Deny].Add(new XacmlContextPolicySetIdReference() {
                                    Value = policySet.PolicySetId.OriginalString,
                                    Version = new XacmlVersionMatchType(policySet.Version)
                                });
                            }
                        }
                    }
                }
            }

            return algResult;
        }