/* * Copyright (c) 2014 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.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import org.opendaylight.groupbasedpolicy.util.MatcherUtils.GetLabelName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityMatcherName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionMatcherName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.LabelName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityMatcherName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RequirementMatcherName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RequirementName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TargetName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Label; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.capabilities.Capability; 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.condition.matchers.ConditionMatcherBuilder; 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.has.qualities.Quality; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.requirements.Requirement; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcher; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcherBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.quality.matcher.MatcherQuality; 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.TenantBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder; 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.ContractBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup.IntraGroupPolicy; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder; 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.ClauseBuilder; 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.SubjectBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Target; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.TargetBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchers; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ProviderMatchers; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ProviderMatchersBuilder; 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.GroupRequirementConstraintCaseBuilder; 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.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.RequirementMatcherBuilder; 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.requirement.matcher.MatcherRequirement; 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.GroupCapabilityConstraintCaseBuilder; 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 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.CapabilityMatcherBuilder; 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.capability.matcher.MatcherCapability; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.RuleBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelector; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerTargetSelector; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerTargetSelectorBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelector; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelectorBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderTargetSelector; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderTargetSelectorBuilder; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; /** * Utilities useful for resolving the inheritance rules for the various objects * in the system * * @author readams * */ public class InheritanceUtils { private InheritanceUtils() { throw new UnsupportedOperationException("Cannot create an instance"); } /** * Fully resolve the specified {@link Tenant}, returning a tenant with all * items fully normalized. This means that no items will have parent/child * relationships and can be interpreted simply without regard to inheritance * rules * * @param unresolvedTenant * the {@link Tenant} unresolved tenant to resolve * @return the fully-resolved {@link Tenant} * @throws NullPointerException if parameter {@code unresolvedTenant} is {@code null} */ public static Tenant resolveTenant(Tenant unresolvedTenant) { Preconditions.checkNotNull(unresolvedTenant); HashMap<EndpointGroupId, EndpointGroup> resolvedEgs = new HashMap<>(); HashMap<ContractId, Contract> resolvedContracts = new HashMap<>(); TenantBuilder resolvedTenantBuilder = new TenantBuilder().setId(unresolvedTenant.getId()) .setName(unresolvedTenant.getName()) .setDescription(unresolvedTenant.getDescription()); Policy unresolvedPolicy = unresolvedTenant.getPolicy(); if (unresolvedPolicy != null) { if (unresolvedPolicy.getEndpointGroup() != null) { for (EndpointGroup eg : unresolvedPolicy.getEndpointGroup()) { resolveEndpointGroup(unresolvedTenant, eg, resolvedEgs); } } if (unresolvedPolicy.getContract() != null) { for (Contract c : unresolvedPolicy.getContract()) { resolveContract(unresolvedTenant, c, resolvedContracts); } } resolvedTenantBuilder .setPolicy(new PolicyBuilder().setEndpointGroup(ImmutableList.copyOf(resolvedEgs.values())) .setContract(ImmutableList.copyOf(resolvedContracts.values())) .setContractRef(unresolvedPolicy.getContractRef()) .setExternalImplicitGroup(unresolvedPolicy.getExternalImplicitGroup()) .setSubjectFeatureInstances(unresolvedPolicy.getSubjectFeatureInstances()) .build()); } // XXX TODO - inherit from common tenant resolvedTenantBuilder.setForwardingContext(unresolvedTenant.getForwardingContext()); return resolvedTenantBuilder.build(); } // **************** // Helper functions // **************** private static void resolveEndpointGroup(Tenant unresolvedTenant, EndpointGroup unresolvedEg, HashMap<EndpointGroupId, EndpointGroup> resolvedEgs) { // put the unresolved object into the data structure to avoid loops resolvedEgs.put(unresolvedEg.getId(), unresolvedEg); // resolve parent if it hasn't been resolved already EndpointGroup parent = null; if (unresolvedEg.getParent() != null) { if (!resolvedEgs.containsKey(unresolvedEg.getParent())) { parent = TenantUtils.findEndpointGroup(unresolvedTenant, unresolvedEg.getParent()); if (parent != null) resolveEndpointGroup(unresolvedTenant, parent, resolvedEgs); } parent = resolvedEgs.get(unresolvedEg.getParent()); } HashMap<SelectorName, ConsumerTargetSelector> resolvedCts = new HashMap<>(); HashMap<SelectorName, ConsumerNamedSelector> resolvedCns = new HashMap<>(); HashMap<SelectorName, ProviderTargetSelector> resolvedPts = new HashMap<>(); HashMap<SelectorName, ProviderNamedSelector> resolvedPns = new HashMap<>(); NetworkDomainId domain = unresolvedEg.getNetworkDomain(); IntraGroupPolicy igp = unresolvedEg.getIntraGroupPolicy(); if (unresolvedEg.getConsumerTargetSelector() != null) { for (ConsumerTargetSelector s : unresolvedEg.getConsumerTargetSelector()) { resolveCts(unresolvedTenant, unresolvedEg, s, resolvedCts); } } if (unresolvedEg.getConsumerNamedSelector() != null) { for (ConsumerNamedSelector s : unresolvedEg.getConsumerNamedSelector()) { resolveCns(unresolvedTenant, unresolvedEg, s, resolvedCns); } } if (unresolvedEg.getProviderTargetSelector() != null) { for (ProviderTargetSelector s : unresolvedEg.getProviderTargetSelector()) { resolvePts(unresolvedTenant, unresolvedEg, s, resolvedPts); } } if (unresolvedEg.getProviderNamedSelector() != null) { for (ProviderNamedSelector s : unresolvedEg.getProviderNamedSelector()) { resolvePns(unresolvedTenant, unresolvedEg, s, resolvedPns); } } if (parent != null) { if (parent.getConsumerTargetSelector() != null) { for (ConsumerTargetSelector cts : parent.getConsumerTargetSelector()) { if (!resolvedCts.containsKey(cts.getName())) resolvedCts.put(cts.getName(), cts); } } if (parent.getConsumerNamedSelector() != null) { for (ConsumerNamedSelector cns : parent.getConsumerNamedSelector()) { if (!resolvedCns.containsKey(cns.getName())) resolvedCns.put(cns.getName(), cns); } } if (parent.getProviderTargetSelector() != null) { for (ProviderTargetSelector pts : parent.getProviderTargetSelector()) { if (!resolvedPts.containsKey(pts.getName())) resolvedPts.put(pts.getName(), pts); } } if (parent.getProviderNamedSelector() != null) { for (ProviderNamedSelector pns : parent.getProviderNamedSelector()) { if (!resolvedPns.containsKey(pns.getName())) resolvedPns.put(pns.getName(), pns); } } if (domain == null) { domain = parent.getNetworkDomain(); } if (igp == null) { igp = parent.getIntraGroupPolicy(); } } // Note: do not set parent, or any of the values that only exist // for inheritance EndpointGroup resolvedEg = new EndpointGroupBuilder() .setId(unresolvedEg.getId()) .setDescription(unresolvedEg.getDescription()) .setName(unresolvedEg.getName()) .setConsumerTargetSelector(ImmutableList.copyOf(resolvedCts.values())) .setConsumerNamedSelector(ImmutableList.copyOf(resolvedCns.values())) .setProviderTargetSelector(ImmutableList.copyOf(resolvedPts.values())) .setProviderNamedSelector(ImmutableList.copyOf(resolvedPns.values())) .setNetworkDomain(domain) .setIntraGroupPolicy(igp) .build(); resolvedEgs.put(resolvedEg.getId(), resolvedEg); } private static void resolveCts(Tenant unresolvedTenant, EndpointGroup unresolvedEg, ConsumerTargetSelector unresolvedTs, HashMap<SelectorName, ConsumerTargetSelector> resolvedCts) { HashMap<QualityMatcherName, QualityMatcher> matchers = new HashMap<>(); HashMap<RequirementName, Requirement> requirements = new HashMap<>(); HashSet<EndpointGroupId> visited = new HashSet<>(); resolveCtsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(), matchers, requirements, visited); ConsumerTargetSelector resolved = new ConsumerTargetSelectorBuilder() .setName(unresolvedTs.getName()) .setQualityMatcher(ImmutableList.copyOf(matchers.values())) .setRequirement(ImmutableList.copyOf(requirements.values())) .build(); resolvedCts.put(resolved.getName(), resolved); } private static void resolveCtsAttr(Tenant unresolvedTenant, EndpointGroup unresolvedEg, SelectorName name, HashMap<QualityMatcherName, QualityMatcher> matchers, HashMap<RequirementName, Requirement> requirements, HashSet<EndpointGroupId> visited) { if (unresolvedEg == null) return; if (visited.contains(unresolvedEg.getId())) return; visited.add(unresolvedEg.getId()); if (unresolvedEg.getParent() != null) { resolveCtsAttr(unresolvedTenant, TenantUtils.findEndpointGroup(unresolvedTenant, unresolvedEg.getParent()), name, matchers, requirements, visited); } resolveLabels(unresolvedEg.getRequirement(), requirements, MatcherUtils.getRequirementName); ConsumerTargetSelector unresolvedSelector = TenantUtils.findCts(unresolvedEg, name); if (unresolvedSelector == null) return; resolveLabels(unresolvedSelector.getRequirement(), requirements, MatcherUtils.getRequirementName); resolveQualityMatcher(unresolvedSelector.getQualityMatcher(), matchers); } private static void resolveCns(Tenant unresolvedTenant, EndpointGroup unresolvedEg, ConsumerNamedSelector unresolvedTs, HashMap<SelectorName, ConsumerNamedSelector> resolvedCns) { HashMap<RequirementName, Requirement> requirements = new HashMap<>(); HashSet<ContractId> contracts = new HashSet<>(); HashSet<EndpointGroupId> visited = new HashSet<>(); resolveCnsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(), requirements, contracts, visited); ConsumerNamedSelector resolved = new ConsumerNamedSelectorBuilder() .setName(unresolvedTs.getName()) .setRequirement(ImmutableList.copyOf(requirements.values())) .setContract(ImmutableList.copyOf(contracts)) .build(); resolvedCns.put(resolved.getName(), resolved); } private static void resolveCnsAttr(Tenant unresolvedTenant, EndpointGroup unresolvedEg, SelectorName name, HashMap<RequirementName, Requirement> requirements, HashSet<ContractId> contracts, HashSet<EndpointGroupId> visited) { if (unresolvedEg == null) return; if (visited.contains(unresolvedEg.getId())) return; visited.add(unresolvedEg.getId()); if (unresolvedEg.getParent() != null) { resolveCnsAttr(unresolvedTenant, TenantUtils.findEndpointGroup(unresolvedTenant, unresolvedEg.getParent()), name, requirements, contracts, visited); } resolveLabels(unresolvedEg.getRequirement(), requirements, MatcherUtils.getRequirementName); ConsumerNamedSelector unresolvedSelector = TenantUtils.findCns(unresolvedEg, name); if (unresolvedSelector == null) return; resolveLabels(unresolvedSelector.getRequirement(), requirements, MatcherUtils.getRequirementName); if (unresolvedSelector.getContract() != null) { contracts.addAll(unresolvedSelector.getContract()); } } private static void resolvePts(Tenant unresolvedTenant, EndpointGroup unresolvedEg, ProviderTargetSelector unresolvedTs, HashMap<SelectorName, ProviderTargetSelector> resolvedCts) { HashMap<QualityMatcherName, QualityMatcher> matchers = new HashMap<>(); HashMap<CapabilityName, Capability> capabilities = new HashMap<>(); HashSet<EndpointGroupId> visited = new HashSet<>(); resolvePtsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(), matchers, capabilities, visited); ProviderTargetSelector resolved = new ProviderTargetSelectorBuilder() .setName(unresolvedTs.getName()) .setQualityMatcher(ImmutableList.copyOf(matchers.values())) .setCapability(ImmutableList.copyOf(capabilities.values())) .build(); resolvedCts.put(resolved.getName(), resolved); } private static void resolvePtsAttr(Tenant unresolvedTenant, EndpointGroup unresolvedEg, SelectorName name, HashMap<QualityMatcherName, QualityMatcher> matchers, HashMap<CapabilityName, Capability> capabilities, HashSet<EndpointGroupId> visited) { if (unresolvedEg == null) return; if (visited.contains(unresolvedEg.getId())) return; visited.add(unresolvedEg.getId()); if (unresolvedEg.getParent() != null) { resolvePtsAttr(unresolvedTenant, TenantUtils.findEndpointGroup(unresolvedTenant, unresolvedEg.getParent()), name, matchers, capabilities, visited); } resolveLabels(unresolvedEg.getCapability(), capabilities, MatcherUtils.getCapabilityName); ProviderTargetSelector unresolvedSelector = TenantUtils.findPts(unresolvedEg, name); if (unresolvedSelector == null) return; resolveLabels(unresolvedSelector.getCapability(), capabilities, MatcherUtils.getCapabilityName); resolveQualityMatcher(unresolvedSelector.getQualityMatcher(), matchers); } private static void resolvePns(Tenant unresolvedTenant, EndpointGroup unresolvedEg, ProviderNamedSelector unresolvedTs, HashMap<SelectorName, ProviderNamedSelector> resolvedCns) { HashMap<CapabilityName, Capability> capabilities = new HashMap<>(); HashSet<ContractId> contracts = new HashSet<>(); HashSet<EndpointGroupId> visited = new HashSet<>(); resolvePnsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(), capabilities, contracts, visited); ProviderNamedSelector resolved = new ProviderNamedSelectorBuilder() .setName(unresolvedTs.getName()) .setCapability(ImmutableList.copyOf(capabilities.values())) .setContract(ImmutableList.copyOf(contracts)) .build(); resolvedCns.put(resolved.getName(), resolved); } private static void resolvePnsAttr(Tenant unresolvedTenant, EndpointGroup unresolvedEg, SelectorName name, HashMap<CapabilityName, Capability> capabilities, HashSet<ContractId> contracts, HashSet<EndpointGroupId> visited) { if (unresolvedEg == null) return; if (visited.contains(unresolvedEg.getId())) return; visited.add(unresolvedEg.getId()); if (unresolvedEg.getParent() != null) { resolvePnsAttr(unresolvedTenant, TenantUtils.findEndpointGroup(unresolvedTenant, unresolvedEg.getParent()), name, capabilities, contracts, visited); } resolveLabels(unresolvedEg.getCapability(), capabilities, MatcherUtils.getCapabilityName); ProviderNamedSelector unresolvedSelector = TenantUtils.findPns(unresolvedEg, name); if (unresolvedSelector == null) return; resolveLabels(unresolvedSelector.getCapability(), capabilities, MatcherUtils.getCapabilityName); if (unresolvedSelector.getContract() != null) { contracts.addAll(unresolvedSelector.getContract()); } } private static void resolveContract(Tenant unresolvedTenant, Contract unresolvedContract, HashMap<ContractId, Contract> resolvedContracts) { // put the unresolved object into the data structure to avoid loops resolvedContracts.put(unresolvedContract.getId(), unresolvedContract); // resolve parent if it hasn't been resolved already Contract parent = null; if (unresolvedContract.getParent() != null) { if (!resolvedContracts.containsKey(unresolvedContract.getParent())) { parent = TenantUtils.findContract(unresolvedTenant, unresolvedContract.getParent()); if (parent != null) resolveContract(unresolvedTenant, parent, resolvedContracts); } parent = resolvedContracts.get(unresolvedContract.getParent()); } HashMap<TargetName, Target> resolvedTargets = new HashMap<>(); HashMap<ClauseName, Clause> resolvedClauses = new HashMap<>(); HashMap<SubjectName, Subject> resolvedSubjects = new HashMap<>(); if (unresolvedContract.getTarget() != null) { for (Target t : unresolvedContract.getTarget()) { resolveTarget(unresolvedTenant, unresolvedContract, t, resolvedTargets); } } if (unresolvedContract.getClause() != null) { for (Clause c : unresolvedContract.getClause()) { resolveClause(unresolvedTenant, unresolvedContract, c, resolvedClauses); } } if (unresolvedContract.getSubject() != null) { for (Subject s : unresolvedContract.getSubject()) { resolveSubject(unresolvedTenant, unresolvedContract, s, resolvedSubjects); } } if (parent != null) { if (parent.getTarget() != null) { for (Target t : parent.getTarget()) { if (!resolvedTargets.containsKey(t.getName())) resolvedTargets.put(t.getName(), t); } } if (parent.getClause() != null) { for (Clause c : parent.getClause()) { if (!resolvedClauses.containsKey(c.getName())) resolvedClauses.put(c.getName(), c); } } if (parent.getSubject() != null) { for (Subject s : parent.getSubject()) { if (!resolvedSubjects.containsKey(s.getName())) resolvedSubjects.put(s.getName(), s); } } } Contract resolvedContract = new ContractBuilder() .setId(unresolvedContract.getId()) .setDescription(unresolvedContract.getDescription()) .setTarget(ImmutableList.copyOf(resolvedTargets.values())) .setClause(ImmutableList.copyOf(resolvedClauses.values())) .setSubject(ImmutableList.copyOf(resolvedSubjects.values())) .build(); resolvedContracts.put(resolvedContract.getId(), resolvedContract); } private static void resolveTarget(Tenant unresolvedTenant, Contract unresolvedContract, Target unresolvedTarget, HashMap<TargetName, Target> resolvedTargets) { HashMap<QualityName, Quality> qualities = new HashMap<>(); HashSet<ContractId> visited = new HashSet<>(); resolveTargetAttrs(unresolvedTenant, unresolvedContract, unresolvedTarget.getName(), qualities, visited); Target resolved = new TargetBuilder() .setName(unresolvedTarget.getName()) .setQuality(ImmutableList.copyOf(qualities.values())) .build(); resolvedTargets.put(resolved.getName(), resolved); } private static void resolveTargetAttrs(Tenant unresolvedTenant, Contract unresolvedContract, TargetName targetName, HashMap<QualityName, Quality> qualities, HashSet<ContractId> visited) { if (unresolvedContract == null) return; if (visited.contains(unresolvedContract.getId())) return; visited.add(unresolvedContract.getId()); if (unresolvedContract.getParent() != null) { resolveTargetAttrs(unresolvedTenant, TenantUtils.findContract(unresolvedTenant, unresolvedContract.getParent()), targetName, qualities, visited); } resolveLabels(unresolvedContract.getQuality(), qualities, MatcherUtils.getQualityName); Target unresolvedTarget = TenantUtils.findTarget(unresolvedContract, targetName); resolveLabels(unresolvedTarget.getQuality(), qualities, MatcherUtils.getQualityName); } private static void resolveQualityMatcher(Collection<QualityMatcher> toResolve, HashMap<QualityMatcherName, QualityMatcher> matchers) { if (toResolve == null) return; for (QualityMatcher qm : toResolve) { if (matchers.containsKey(qm.getName())) { QualityMatcher oqm = matchers.get(qm.getName()); QualityMatcherBuilder qmb = new QualityMatcherBuilder(); qmb.setName(qm.getName()); qmb.setMatchType(oqm.getMatchType()); if (qm.getMatchType() != null) qmb.setMatchType(qm.getMatchType()); HashMap<QualityName, MatcherQuality> qualities = new HashMap<>(); resolveLabels(oqm.getMatcherQuality(), qualities, MatcherUtils.getMatcherQualityName); resolveLabels(qm.getMatcherQuality(), qualities, MatcherUtils.getMatcherQualityName); qmb.setMatcherQuality(ImmutableList.copyOf(qualities.values())); matchers.put(qm.getName(), qmb.build()); } else { matchers.put(qm.getName(), qm); } } } private static void resolveCapabilityMatcher(Collection<CapabilityMatcher> toResolve, HashMap<CapabilityMatcherName, CapabilityMatcher> matchers) { if (toResolve == null) return; for (CapabilityMatcher m : toResolve) { if (matchers.containsKey(m.getName())) { CapabilityMatcher om = matchers.get(m.getName()); CapabilityMatcherBuilder mb = new CapabilityMatcherBuilder(); mb.setName(m.getName()); mb.setMatchType(om.getMatchType()); if (m.getMatchType() != null) mb.setMatchType(m.getMatchType()); HashMap<CapabilityName, MatcherCapability> labels = new HashMap<>(); resolveLabels(om.getMatcherCapability(), labels, MatcherUtils.getMatcherCapabilityName); resolveLabels(m.getMatcherCapability(), labels, MatcherUtils.getMatcherCapabilityName); mb.setMatcherCapability(ImmutableList.copyOf(labels.values())); matchers.put(m.getName(), mb.build()); } else { matchers.put(m.getName(), m); } } } private static void resolveRequirementMatcher(Collection<RequirementMatcher> toResolve, HashMap<RequirementMatcherName, RequirementMatcher> matchers) { if (toResolve == null) return; for (RequirementMatcher m : toResolve) { if (matchers.containsKey(m.getName())) { RequirementMatcher om = matchers.get(m.getName()); RequirementMatcherBuilder mb = new RequirementMatcherBuilder(); mb.setName(m.getName()); mb.setMatchType(om.getMatchType()); if (m.getMatchType() != null) mb.setMatchType(m.getMatchType()); HashMap<RequirementName, MatcherRequirement> labels = new HashMap<>(); resolveLabels(om.getMatcherRequirement(), labels, MatcherUtils.getMatcherRequirementName); resolveLabels(m.getMatcherRequirement(), labels, MatcherUtils.getMatcherRequirementName); mb.setMatcherRequirement(ImmutableList.copyOf(labels.values())); matchers.put(m.getName(), mb.build()); } else { matchers.put(m.getName(), m); } } } private static void resolveConditionMatcher(Collection<ConditionMatcher> toResolve, HashMap<ConditionMatcherName, ConditionMatcher> matchers) { if (toResolve == null) return; for (ConditionMatcher m : toResolve) { if (matchers.containsKey(m.getName())) { ConditionMatcher om = matchers.get(m.getName()); ConditionMatcherBuilder mb = new ConditionMatcherBuilder(); mb.setName(m.getName()); mb.setMatchType(om.getMatchType()); if (m.getMatchType() != null) mb.setMatchType(m.getMatchType()); HashMap<ConditionName, Condition> labels = new HashMap<>(); resolveLabels(om.getCondition(), labels, MatcherUtils.getConditionName); resolveLabels(m.getCondition(), labels, MatcherUtils.getConditionName); mb.setCondition(ImmutableList.copyOf(labels.values())); matchers.put(m.getName(), mb.build()); } else { matchers.put(m.getName(), m); } } } private static void resolveClause(Tenant unresolvedTenant, Contract unresolvedContract, Clause unresolvedClause, HashMap<ClauseName, Clause> resolvedClauses) { HashMap<CapabilityMatcherName, CapabilityMatcher> capMatchers = new HashMap<>(); HashMap<ConditionMatcherName, ConditionMatcher> provCondMatchers = new HashMap<>(); HashMap<RequirementMatcherName, RequirementMatcher> reqMatchers = new HashMap<>(); HashMap<ConditionMatcherName, ConditionMatcher> consCondMatchers = new HashMap<>(); HashSet<SubjectName> subjectRefs = new HashSet<>(); HashSet<ContractId> visited = new HashSet<>(); // TODO: Add GIC choices GroupNameConstraint and GroupAny // TODO: Add Inheritance for EIC (ie L3Prefix) constraint. resolveClauseAttr(unresolvedTenant, unresolvedContract, unresolvedClause.getName(), subjectRefs, capMatchers, provCondMatchers, reqMatchers, consCondMatchers, visited); Clause resolved = new ClauseBuilder() .setName(unresolvedClause.getName()) .setSubjectRefs(ImmutableList.copyOf(subjectRefs)) .setProviderMatchers(new ProviderMatchersBuilder() .setGroupIdentificationConstraints(new GroupCapabilityConstraintCaseBuilder() .setCapabilityMatcher(ImmutableList.copyOf(capMatchers.values())).build()) .setConditionMatcher(ImmutableList.copyOf(provCondMatchers.values())) .setEndpointIdentificationConstraints( unresolvedClause.getProviderMatchers() == null ? null : unresolvedClause.getProviderMatchers().getEndpointIdentificationConstraints()) .build()) .setConsumerMatchers(new ConsumerMatchersBuilder() .setGroupIdentificationConstraints(new GroupRequirementConstraintCaseBuilder() .setRequirementMatcher(ImmutableList.copyOf(reqMatchers.values())).build()) .setConditionMatcher(ImmutableList.copyOf(consCondMatchers.values())) .setEndpointIdentificationConstraints( unresolvedClause.getConsumerMatchers() == null ? null : unresolvedClause.getConsumerMatchers().getEndpointIdentificationConstraints()) .build()) .build(); resolvedClauses.put(resolved.getName(), resolved); } private static void resolveClauseAttr(Tenant unresolvedTenant, Contract unresolvedContract, ClauseName clauseName, HashSet<SubjectName> subjectRefs, HashMap<CapabilityMatcherName, CapabilityMatcher> capMatchers, HashMap<ConditionMatcherName, ConditionMatcher> provCondMatchers, HashMap<RequirementMatcherName, RequirementMatcher> reqMatchers, HashMap<ConditionMatcherName, ConditionMatcher> consCondMatchers, HashSet<ContractId> visited) { if (unresolvedContract == null) return; if (visited.contains(unresolvedContract.getId())) return; visited.add(unresolvedContract.getId()); if (unresolvedContract.getParent() != null) { resolveClauseAttr(unresolvedTenant, TenantUtils.findContract(unresolvedTenant, unresolvedContract.getParent()), clauseName, subjectRefs, capMatchers, provCondMatchers, reqMatchers, consCondMatchers, visited); } Clause unresolvedClause = TenantUtils.findClause(unresolvedContract, clauseName); if (unresolvedClause == null) return; if (unresolvedClause.getProviderMatchers() != null) { ProviderMatchers pms = unresolvedClause.getProviderMatchers(); org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.GroupIdentificationConstraints groupIdentificationConstraintsProvider = pms .getGroupIdentificationConstraints(); if (groupIdentificationConstraintsProvider instanceof GroupCapabilityConstraintCase) { resolveCapabilityMatcher( ((GroupCapabilityConstraintCase) groupIdentificationConstraintsProvider).getCapabilityMatcher(), capMatchers); } resolveConditionMatcher(pms.getConditionMatcher(), provCondMatchers); } if (unresolvedClause.getConsumerMatchers() != null) { ConsumerMatchers cms = unresolvedClause.getConsumerMatchers(); GroupIdentificationConstraints groupIdentificiationConstrainsConsumer = cms .getGroupIdentificationConstraints(); if (groupIdentificiationConstrainsConsumer instanceof GroupRequirementConstraintCase) { resolveRequirementMatcher( ((GroupRequirementConstraintCase) groupIdentificiationConstrainsConsumer) .getRequirementMatcher(), reqMatchers); } resolveConditionMatcher(cms.getConditionMatcher(), consCondMatchers); } if (unresolvedClause.getSubjectRefs() != null) subjectRefs.addAll(unresolvedClause.getSubjectRefs()); } private static class Mutable<O> { O value; } private static void resolveSubject(Tenant unresolvedTenant, Contract unresolvedContract, Subject unresolvedSubject, HashMap<SubjectName, Subject> resolvedSubjects) { Mutable<Integer> order = new Mutable<>(); Mutable<List<Rule>> rules = new Mutable<>(); rules.value = Collections.emptyList(); HashSet<ContractId> visited = new HashSet<>(); resolveSubjectAttr(unresolvedTenant, unresolvedContract, unresolvedSubject.getName(), order, rules, visited); Subject resolved = new SubjectBuilder() .setName(unresolvedSubject.getName()) .setOrder(order.value) .setRule(rules.value) .build(); resolvedSubjects.put(resolved.getName(), resolved); } private static Rule makeRule(Rule r, int order) { return new RuleBuilder() .setName(r.getName()) .setActionRef(r.getActionRef()) .setClassifierRef(r.getClassifierRef()) .setOrder(order) .build(); } private static void resolveSubjectAttr(Tenant unresolvedTenant, Contract unresolvedContract, SubjectName subjectName, Mutable<Integer> order, Mutable<List<Rule>> rules, HashSet<ContractId> visited) { if (unresolvedContract == null) return; if (visited.contains(unresolvedContract.getId())) return; visited.add(unresolvedContract.getId()); if (unresolvedContract.getParent() != null) { resolveSubjectAttr(unresolvedTenant, TenantUtils.findContract(unresolvedTenant, unresolvedContract.getParent()), subjectName, order, rules, visited); } Subject unresolvedSubject = TenantUtils.findSubject(unresolvedContract, subjectName); if (unresolvedSubject == null) return; if (unresolvedSubject.getOrder() != null) order.value = unresolvedSubject.getOrder(); if (unresolvedSubject.getRule() != null) { ImmutableList.Builder<Rule> rbuilder = new ImmutableList.Builder<Rule>(); ArrayList<Rule> nrules = new ArrayList<>(unresolvedSubject.getRule()); Collections.sort(nrules, TenantUtils.RULE_COMPARATOR); int index = 0; for (Rule r : nrules) { rbuilder.add(makeRule(r, index++)); } for (Rule r : rules.value) { rbuilder.add(makeRule(r, index++)); } rules.value = rbuilder.build(); } } /** * Given a partially-resolved set of labels, add the next item in the * inheritance ordering to the set of resolved labels. * * @param toResolve * the new set to add * @param labels * the partially-resolved set * @param getName * a function object to get the appropriate typed label name */ private static <L extends Label, LN extends LabelName> void resolveLabels(Collection<L> toResolve, HashMap<LN, L> labels, GetLabelName<L, LN> getName) { if (toResolve == null) return; for (L l : toResolve) { if (l.getInclusionRule() != null) { switch (l.getInclusionRule()) { case Include: // override labels.put(getName.getName(l), l); break; case Exclude: // remove labels.remove(getName.getName(l)); break; } } else { // default to Include labels.put(getName.getName(l), l); } } } }