org.opendaylight.groupbasedpolicy.util.SubjectResolverUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.groupbasedpolicy.util.SubjectResolverUtils.java

Source

/*
 * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.groupbasedpolicy.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.opendaylight.groupbasedpolicy.dto.ConditionSet;
import org.opendaylight.groupbasedpolicy.dto.EgKey;
import org.opendaylight.groupbasedpolicy.dto.EndpointConstraint;
import org.opendaylight.groupbasedpolicy.dto.Policy;
import org.opendaylight.groupbasedpolicy.dto.RuleGroup;
import org.opendaylight.groupbasedpolicy.util.ContractResolverUtils.ContractMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Subject;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.GroupIdentificationConstraints;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.GroupRequirementConstraintCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.RequirementMatcher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.GroupCapabilityConstraintCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.CapabilityMatcher;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;

class SubjectResolverUtils {

    private SubjectResolverUtils() {
        throw new UnsupportedOperationException("Cannot create an instance");
    }

    /**
     * Choose the set of subjects that in scope for each possible set of
     * endpoint conditions
     */
    // TODO Li msunal do we really need contractMatches to be a type Table<EgKey, EgKey, List<ContractMatch>>
    // it should be sufficient to be just List<ContractMatch>
    static Table<EgKey, EgKey, Policy> selectSubjects(Table<EgKey, EgKey, List<ContractMatch>> contractMatches,
            Map<EgKey, Set<ConditionSet>> egConditions) {
        // TODO: Note that it's possible to further simplify the resulting
        // policy
        // in the case of things like repeated rules, condition sets that
        // cover other condition sets, etc. This would be a good thing to do
        // at some point
        Table<EgKey, EgKey, Policy> policy = HashBasedTable.create();

        for (List<ContractMatch> matches : contractMatches.values()) {
            for (ContractMatch match : matches) {
                List<Clause> clauses = match.contract.getClause();
                if (clauses == null)
                    continue;

                List<Subject> subjectList = match.contract.getSubject();
                if (subjectList == null)
                    continue;

                EgKey ckey = new EgKey(match.consumerTenant.getId(), match.consumer.getId());
                EgKey pkey = new EgKey(match.providerTenant.getId(), match.provider.getId());
                Policy existing = policy.get(ckey, pkey);

                HashMap<SubjectName, Subject> subjects = new HashMap<>();
                for (Subject s : subjectList) {
                    subjects.put(s.getName(), s);
                }

                Table<EndpointConstraint, EndpointConstraint, List<Subject>> subjectMap = HashBasedTable.create();

                for (Clause clause : clauses) {
                    if (clause.getSubjectRefs() != null
                            && clauseMatchesByGroupReqAndCapConstraints(clause, match)) {
                        ConditionSet consCSet = buildConsConditionSet(clause);
                        addConditionSet(ckey, consCSet, egConditions);
                        EndpointConstraint consEpConstraint = new EndpointConstraint(consCSet,
                                clause.getConsumerMatchers() == null ? null
                                        : clause.getConsumerMatchers().getEndpointIdentificationConstraints());
                        ConditionSet provCSet = buildProvConditionSet(clause);
                        addConditionSet(pkey, provCSet, egConditions);
                        EndpointConstraint provEpConstraint = new EndpointConstraint(provCSet,
                                clause.getProviderMatchers() == null ? null
                                        : clause.getProviderMatchers().getEndpointIdentificationConstraints());
                        List<Subject> clauseSubjects = subjectMap.get(consEpConstraint, provEpConstraint);
                        if (clauseSubjects == null) {
                            clauseSubjects = new ArrayList<>();
                            subjectMap.put(consEpConstraint, provEpConstraint, clauseSubjects);
                        }
                        for (SubjectName sn : clause.getSubjectRefs()) {
                            Subject s = subjects.get(sn);
                            if (s != null)
                                clauseSubjects.add(s);
                        }
                    }
                }

                policy.put(ckey, pkey, resolvePolicy(match.contractTenant, match.contract, existing, subjectMap));
            }
        }

        return policy;
    }

    private static boolean clauseMatchesByGroupReqAndCapConstraints(Clause clause, ContractMatch match) {
        if (clause.getConsumerMatchers() != null) {
            GroupIdentificationConstraints groupIdentificationConstraintsConsumer = clause.getConsumerMatchers()
                    .getGroupIdentificationConstraints();
            if (groupIdentificationConstraintsConsumer instanceof GroupRequirementConstraintCase) {
                List<RequirementMatcher> reqMatchers = ((GroupRequirementConstraintCase) groupIdentificationConstraintsConsumer)
                        .getRequirementMatcher();
                if (reqMatchers != null) {
                    for (RequirementMatcher reqMatcher : reqMatchers) {
                        if (!MatcherUtils.applyReqMatcher(reqMatcher, match.consumerRelator)) {
                            return false;
                        }
                    }
                }
            }
        }
        if (clause.getProviderMatchers() != null) {
            org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.GroupIdentificationConstraints groupIdentificationConstraintsProvider = clause
                    .getProviderMatchers().getGroupIdentificationConstraints();
            if (groupIdentificationConstraintsProvider instanceof GroupCapabilityConstraintCase) {
                List<CapabilityMatcher> capMatchers = ((GroupCapabilityConstraintCase) groupIdentificationConstraintsProvider)
                        .getCapabilityMatcher();

                if (capMatchers != null) {
                    for (CapabilityMatcher capMatcher : capMatchers) {
                        if (!MatcherUtils.applyCapMatcher(capMatcher, match.providerRelator)) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }

    private static void addConditionSet(EgKey eg, ConditionSet cs, Map<EgKey, Set<ConditionSet>> egConditions) {
        if (egConditions == null)
            return;
        Set<ConditionSet> cset = egConditions.get(eg);
        if (cset == null) {
            egConditions.put(eg, cset = new HashSet<>());
        }
        cset.add(cs);
    }

    private static ConditionSet buildConsConditionSet(Clause clause) {
        if (clause.getConsumerMatchers() != null) {
            List<ConditionMatcher> condMatchers = clause.getConsumerMatchers().getConditionMatcher();
            return buildConditionSet(condMatchers);
        }
        return ConditionSet.EMPTY;
    }

    private static ConditionSet buildProvConditionSet(Clause clause) {
        if (clause.getProviderMatchers() != null) {
            List<ConditionMatcher> condMatchers = clause.getProviderMatchers().getConditionMatcher();
            return buildConditionSet(condMatchers);
        }
        return ConditionSet.EMPTY;
    }

    private static ConditionSet buildConditionSet(List<ConditionMatcher> condMatchers) {
        if (condMatchers == null)
            return ConditionSet.EMPTY;

        ImmutableSet.Builder<ConditionName> allb = ImmutableSet.builder();
        ImmutableSet.Builder<ConditionName> noneb = ImmutableSet.builder();
        ImmutableSet.Builder<Set<ConditionName>> anyb = ImmutableSet.builder();
        for (ConditionMatcher condMatcher : condMatchers) {
            if (condMatcher.getCondition() == null)
                continue;
            MatchType type = condMatcher.getMatchType();
            if (type == null)
                type = MatchType.All;
            if (type.equals(MatchType.Any)) {
                ImmutableSet.Builder<ConditionName> a = ImmutableSet.builder();
                for (Condition c : condMatcher.getCondition()) {
                    a.add(c.getName());
                }
                anyb.add(a.build());
            } else {
                for (Condition c : condMatcher.getCondition()) {
                    switch (type) {
                    case Any:
                        break;
                    case None:
                        noneb.add(c.getName());
                        break;
                    case All:
                    default:
                        allb.add(c.getName());
                        break;
                    }
                }
            }
        }
        return new ConditionSet(allb.build(), noneb.build(), anyb.build());
    }

    private static Policy resolvePolicy(Tenant contractTenant, Contract contract, Policy merge,
            Table<EndpointConstraint, EndpointConstraint, List<Subject>> subjectMap) {
        Table<EndpointConstraint, EndpointConstraint, List<RuleGroup>> ruleMap = HashBasedTable.create();
        if (merge != null) {
            ruleMap.putAll(merge.getRuleMap());
        }
        for (Cell<EndpointConstraint, EndpointConstraint, List<Subject>> entry : subjectMap.cellSet()) {
            List<RuleGroup> rules = new ArrayList<>();
            EndpointConstraint consEpConstraint = entry.getRowKey();
            EndpointConstraint provEpConstraint = entry.getColumnKey();
            List<RuleGroup> oldrules = ruleMap.get(consEpConstraint, provEpConstraint);
            if (oldrules != null) {
                rules.addAll(oldrules);
            }
            for (Subject s : entry.getValue()) {
                if (s.getRule() == null)
                    continue;

                RuleGroup rg = new RuleGroup(s.getRule(), s.getOrder(), contractTenant, contract, s.getName());
                rules.add(rg);
            }
            Collections.sort(rules);
            ruleMap.put(consEpConstraint, provEpConstraint, Collections.unmodifiableList(rules));
        }
        return new Policy(ruleMap);
    }
}