org.xacml4j.v30.pdp.Policy.java Source code

Java tutorial

Introduction

Here is the source code for org.xacml4j.v30.pdp.Policy.java

Source

package org.xacml4j.v30.pdp;

/*
 * #%L
 * Xacml4J Core Engine Implementation
 * %%
 * Copyright (C) 2009 - 2014 Xacml4J.org
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.xacml4j.v30.CompositeDecisionRule;
import org.xacml4j.v30.CompositeDecisionRuleIDReference;
import org.xacml4j.v30.Decision;
import org.xacml4j.v30.DecisionRule;
import org.xacml4j.v30.EvaluationContext;
import org.xacml4j.v30.ValueExpression;
import org.xacml4j.v30.XPathVersion;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;

public class Policy extends BaseCompositeDecisionRule implements PolicyElement {
    private final PolicyDefaults policyDefaults;
    private final Map<String, VariableDefinition> variableDefinitions;
    private final List<Rule> rules;
    private final DecisionCombiningAlgorithm<Rule> combiningAlgorithm;
    private final Map<String, Multimap<String, CombinerParameter>> ruleCombiningParameters;

    /**
     * A reference to itself
     */
    private final PolicyIDReference reference;

    private Policy(Builder b) {
        super(b);
        Preconditions.checkNotNull(b.combiningAlgorithm, "Rule decision combining algorithm must be specified");
        this.combiningAlgorithm = b.combiningAlgorithm;
        this.policyDefaults = b.policyDefaults;
        this.reference = PolicyIDReference.builder(b.id).version(b.version).build();
        this.rules = b.rules.build();
        this.variableDefinitions = Maps.uniqueIndex(b.variables, new Function<VariableDefinition, String>() {
            @Override
            public String apply(VariableDefinition from) {
                return from.getVariableId();
            }
        });
        this.ruleCombiningParameters = Maps.newHashMap();
        for (Entry<String, Multimap<String, CombinerParameter>> p : b.ruleCombinerParameters.entrySet()) {
            ruleCombiningParameters.put(p.getKey(), ImmutableListMultimap.copyOf(p.getValue()));
        }
    }

    public static Builder builder(String policyId) {
        return new Builder(policyId);
    }

    /**
     * Gets policy defaults
     *
     * @return policy defaults
     */
    public PolicyDefaults getDefaults() {
        return policyDefaults;
    }

    public Collection<CombinerParameter> getRuleCombinerParams(String ruleId) {
        Multimap<String, CombinerParameter> p = ruleCombiningParameters.get(ruleId);
        return (p == null) ? ImmutableList.<CombinerParameter>of() : p.values();
    }

    public Collection<CombinerParameter> getRuleCombinerParam(String ruleId, String name) {
        Multimap<String, CombinerParameter> p = ruleCombiningParameters.get(ruleId);
        return (p == null) ? ImmutableList.<CombinerParameter>of() : p.get(name);
    }

    /**
     * Gets policy rule combining algorithm
     *
     * @return {@link DecisionCombiningAlgorithm} instance
     */
    public DecisionCombiningAlgorithm<Rule> getRuleCombiningAlgorithm() {
        return combiningAlgorithm;
    }

    /**
     * Gets policy variable definitions
     *
     * @return a collection of {@link VariableDefinition} instances
     */
    public Collection<VariableDefinition> getVariableDefinitions() {
        return variableDefinitions.values();
    }

    @Override
    public CompositeDecisionRuleIDReference getReference() {
        return reference;
    }

    /**
     * Gets {@link VariableDefinition} by identifier
     *
     * @param variableId variable identifier
     * @return {@link VariableDefinition} or {@code null}
     * if variable definition can not be resolved
     */
    public VariableDefinition getVariableDefinition(String variableId) {
        return variableDefinitions.get(variableId);
    }

    /**
     * Gets all policy rules
     *
     * @return a collection of {@link Rule}
     * instances
     */
    public List<Rule> getRules() {
        return rules;
    }

    public boolean contains(Rule r) {
        return rules.contains(r);
    }

    /**
     * Implementation creates policy-bound evaluation context
     */
    @Override
    public EvaluationContext createContext(EvaluationContext context) {
        Preconditions.checkNotNull(context);
        CompositeDecisionRule p = context.getCurrentPolicy();
        Preconditions.checkArgument(p == this || p == null);
        if (p == this) {
            return context;
        }
        return new PolicyDelegatingEvaluationContext(context);
    }

    protected Decision combineDecisions(EvaluationContext context) {
        return combiningAlgorithm.combine(context, rules);
    }

    @Override
    protected boolean isEvaluationContextValid(EvaluationContext context) {
        return this.equals(context.getCurrentPolicy());
    }

    @Override
    public String toString() {
        ToStringHelper h = Objects.toStringHelper(this);
        return toStringBuilder(h).add("variableDefinitions", variableDefinitions)
                .add("policyDefaults", policyDefaults).add("rules", rules)
                .add("combiningAlgorithm", combiningAlgorithm)
                .add("ruleCombiningParameters", ruleCombiningParameters).toString();
    }

    protected boolean equalsTo(Policy o) {
        return super.equalsTo(o) && Objects.equal(policyDefaults, o.policyDefaults)
                && Objects.equal(variableDefinitions, o.variableDefinitions) && Objects.equal(rules, o.rules)
                && Objects.equal(combiningAlgorithm, o.combiningAlgorithm)
                && Objects.equal(ruleCombiningParameters, o.ruleCombiningParameters);
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        return (o instanceof Policy) && ((Policy) o).equalsTo(this);
    }

    @Override
    public int hashCode() {
        return super.hashCode() * 31 + Objects.hashCode(policyDefaults, variableDefinitions, rules,
                combiningAlgorithm, ruleCombiningParameters);
    }

    @Override
    public void accept(PolicyVisitor v) {
        v.visitEnter(this);
        if (getTarget() != null) {
            getTarget().accept(v);
        }
        for (VariableDefinition var : variableDefinitions.values()) {
            var.accept(v);
        }
        for (ObligationExpression obligation : obligationExpressions) {
            obligation.accept(v);
        }
        for (AdviceExpression advice : adviceExpressions) {
            advice.accept(v);
        }
        for (DecisionRule rule : rules) {
            rule.accept(v);
        }
        v.visitLeave(this);
    }

    /**
     * An {@link EvaluationContext} implementation for evaluating
     * {@link Policy} instances
     */
    class PolicyDelegatingEvaluationContext extends DelegatingEvaluationContext {
        private final Map<String, ValueExpression> varDefEvalResults;

        /**
         * Creates policy evaluation context with a given parent context
         *
         * @param context a parent evaluation context
         */
        PolicyDelegatingEvaluationContext(EvaluationContext context) {
            super(context);
            this.varDefEvalResults = Maps.newHashMap();
        }

        @Override
        public ValueExpression getVariableEvaluationResult(String variableId) {
            return varDefEvalResults.get(variableId);
        }

        @Override
        public EvaluationContext getParentContext() {
            return getDelegate();
        }

        @Override
        public void setVariableEvaluationResult(String variableId, ValueExpression value) {
            Preconditions.checkNotNull(variableId);
            Preconditions.checkNotNull(value);
            Preconditions.checkArgument(variableDefinitions.containsKey(variableId),
                    "Given variable id=\"%s\" is not defined the policy id=\"%s\"", variableId, id);
            varDefEvalResults.put(variableId, value);
        }

        @Override
        public Policy getCurrentPolicy() {
            return Policy.this;
        }

        @Override
        public XPathVersion getXPathVersion() {
            PolicyDefaults defaults = Policy.this.getDefaults();
            if (defaults != null && defaults.getXPathVersion() != null) {
                return defaults.getXPathVersion();
            }
            return super.getXPathVersion();
        }
    }

    public final static class Builder extends BaseCompositeDecisionRule.Builder<Builder> {
        private DecisionCombiningAlgorithm<Rule> combiningAlgorithm;
        private Collection<VariableDefinition> variables = Lists.newLinkedList();
        private PolicyDefaults policyDefaults;

        private ImmutableList.Builder<Rule> rules = ImmutableList.builder();
        private Map<String, Multimap<String, CombinerParameter>> ruleCombinerParameters = Maps.newLinkedHashMap();

        public Builder(String policyId) {
            super(policyId);
        }

        public Builder ruleCombinerParameter(String ruleId, CombinerParameter p) {
            Preconditions.checkNotNull(ruleId);
            Preconditions.checkNotNull(p);
            Multimap<String, CombinerParameter> params = ruleCombinerParameters.get(ruleId);
            if (params == null) {
                params = LinkedHashMultimap.create();
                ruleCombinerParameters.put(ruleId, params);
            }
            params.put(p.getName(), p);
            return this;
        }

        public Builder ruleCombineParams(String ruleId, Iterable<CombinerParameter> params) {
            Preconditions.checkNotNull(ruleId);
            Preconditions.checkNotNull(params);
            for (CombinerParameter p : params) {
                ruleCombinerParameter(ruleId, p);
            }
            return this;
        }

        public Builder noRuleCombinerParams() {
            this.ruleCombinerParameters.clear();
            return this;
        }

        public Builder defaults(PolicyDefaults defaults) {
            this.policyDefaults = defaults;
            return this;
        }

        public Builder noDefaults() {
            this.policyDefaults = null;
            return this;
        }

        public Builder vars(Iterable<VariableDefinition> vars) {
            for (VariableDefinition var : vars) {
                var(var);
            }
            return this;
        }

        public Builder var(VariableDefinition var) {
            Preconditions.checkNotNull(var);
            this.variables.add(var);
            return this;
        }

        public Builder withoutVariables() {
            this.variables.clear();
            return this;
        }

        public Builder rule(Rule... rules) {
            this.rules.add(rules);
            return this;
        }

        public Builder rule(Rule.Builder b) {
            Preconditions.checkNotNull(b);
            this.rules.add(b.build());
            return this;
        }

        public Builder rules(Iterable<Rule> rules) {
            this.rules.addAll(rules);
            return this;
        }

        public Builder withoutRules() {
            this.rules = ImmutableList.builder();
            return this;
        }

        public Builder combiningAlgorithm(DecisionCombiningAlgorithm<Rule> alg) {
            Preconditions.checkNotNull(alg);
            this.combiningAlgorithm = alg;
            return this;
        }

        @Override
        protected Builder getThis() {
            return this;
        }

        public Policy build() {
            return new Policy(this);
        }
    }
}