repository
workspace
*~
+#*
target
.classpath
.project
<dependencies>
<dependency>
- <groupId>com.google.collections</groupId>
- <artifactId>google-collections</artifactId>
- <version>1.0</version>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <!-- Project reporting -->
+ <reporting>
+ <plugins>
+ <!-- Code coverage analysis -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <!-- project build -->
<build>
<plugins>
<plugin>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>org.opendaylight.controller.config.yang.config.endpoint_provider</Export-Package>
- <!-- <Bundle-Activator>
- org.opendaylight.groupbasedpolicy.plugin.Activator
- </Bundle-Activator> -->
</instructions>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</configuration>
</plugin>
+ <!-- Code coverage analysis -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <instrumentation>
+ <excludes>
+ <exclude>org/opendaylight/yang/**/*.class</exclude>
+ <exclude>org/opendaylight/controller/config/yang/**/*.class</exclude>
+ </excludes>
+ </instrumentation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ <!-- needed for cobertura -->
+ <argLine>-XX:-UseSplitVerifier</argLine>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
+/*
+ * 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.endpoint;
import java.util.ArrayList;
@Override
public Future<RpcResult<Void>>
registerEndpoint(RegisterEndpointInput input) {
- Endpoint ep = new EndpointBuilder(input).build();
+ long timestamp = System.currentTimeMillis();
+ Endpoint ep = new EndpointBuilder(input)
+ .setTimestamp(timestamp)
+ .build();
+
EndpointKey key =
new EndpointKey(ep.getL2Namespace(), ep.getMacAddress());
InstanceIdentifier<Endpoint> iid =
EndpointL3 ep3 = new EndpointL3Builder(input)
.setIpAddress(key3.getIpAddress())
.setL3Namespace(l3addr.getL3Namespace())
+ .setTimestamp(timestamp)
.build();
InstanceIdentifier<EndpointL3> iid_l3 =
InstanceIdentifier.builder(Endpoints.class)
--- /dev/null
+/*
+ * 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.resolver;
+
+/**
+ * An interface for an object that can listen for events related to group-based
+ * policy resolution.
+ * @author readams
+ */
+public interface PolicyListener {
+
+
+}
--- /dev/null
+/*
+ * 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.resolver;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+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.contract.subject.Rule;
+
+/**
+ * The policy resolver is a utility for renderers to help in resolving
+ * group-based policy into a form that is easier to apply to the actual network.
+ *
+ * <p>For any pair of endpoint groups, there is a set of rules that could apply
+ * to the endpoints on that group based on the policy configuration. The exact
+ * list of rules that apply to a given pair of endpoints depends on the
+ * conditions that are active on the endpoints.
+ *
+ * In a more formal sense: Let there be endpoint groups G_n, and for each G_n a
+ * set of conditions C_n that can apply to endpoints in G_n. Further, let S be
+ * the set of lists of rules defined in the policy. Our policy can be
+ * represented as a function F: (G_n, 2^C_n, G_m, 2^C_m) -> S, where 2^C_n
+ * represents the power set of C_n. In other words, we want to map all the
+ * possible tuples of pairs of endpoints along with their active conditions
+ * onto the right list of rules to apply.
+ *
+ * <p>We need to be able to query against this policy model, enumerate the
+ * relevant classes of traffic and endpoints, and notify renderers when there
+ * are changes to policy as it applies to active sets of endpoints and
+ * endpoint groups.
+ *
+ * <p>The policy resolver will maintain the necessary state for all tenants
+ * in its control domain, which is the set of tenants for which
+ * policy listeners have been registered.
+ *
+ * @author readams
+ */
+public interface PolicyResolverService {
+
+ /**
+ * Get the policy that currently applies to a endpoints.
+ * with the specified groups and conditions. The rules are normalized
+ * such that rules with a direction of "out" apply to traffic from the
+ * first endpoint to the second endpoint.
+ *
+ * @param ep1Group the endpoint group for the first endpoint
+ * @param ep1Conds The conditions that apply to the first endpoint
+ * @param ep2Group the endpoint group for the second endpoint
+ * @param ep2Conds The conditions that apply to the second endpoint.
+ * @return a list of {@link Rule} that apply to the endpoints.
+ */
+ public List<Rule> getPolicy(EndpointGroupId ep1Group,
+ Collection<Condition> ep1Conds,
+ EndpointGroupId ep2Group,
+ Collection<Condition> ep2Conds);
+
+ /**
+ * Register a listener to receive update events.
+ * @param listener the {@link PolicyListener} object to receive the update
+ * events
+ */
+ public PolicyScope registerListener(PolicyListener listener);
+
+ /**
+ * Remove the listener registered for the given {@link PolicyScopeImpl}.
+ * @param scope the scope to remove
+ * @see PolicyResolver#registerListener(PolicyListener)
+ */
+ public void removeListener(PolicyScope scope);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.resolver;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+
+/**
+ * The policy scope object represents a scope for policy-related information.
+ * A renderer that addresses a particular scope can express this as a
+ * {@link PolicyScopeImpl} with an associates {@link PolicyListener} that can
+ * receive relevant updates.
+ * @see PolicyResolver
+ * @author readams
+ */
+public interface PolicyScope {
+
+ /**
+ * Add the endpoint group from the given tenant to the scope of updates
+ * @param tenant the tenant for the endpoint group
+ * @param endpointGroup the endpoint group to add
+ */
+ public void addToScope(TenantId tenant,
+ EndpointGroupId endpointGroup);
+
+ /**
+ * Add all endpoint groups in the given tenant to the scope of updates
+ * @param tenant the tenant to add.
+ */
+ public void addToScope(TenantId tenant);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+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.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.groupbasedpolicy.resolver.internal.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.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.common.rev140421.TenantId;
+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.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.TargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirement;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelectorBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+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 {
+ /**
+ * 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 tenantId the {@link TenantId} of the {@link Tenant}
+ * @param transaction a {@link DataModificationTransaction} to use for
+ * reading the data from the policy store
+ * @return the fully-resolved {@link Tenant}
+ */
+ public static Tenant resolveTenant(TenantId tenantId,
+ DataModificationTransaction transaction) {
+ InstanceIdentifier<Tenant> tenantIid = TenantUtils.tenantIid(tenantId);
+ DataObject tObject = transaction.readConfigurationData(tenantIid);
+ if (tObject == null || !(tObject instanceof Tenant))
+ return null;
+
+ Tenant unresolvedTenant = (Tenant)tObject;
+ HashMap<EndpointGroupId, EndpointGroup> resolvedEgs = new HashMap<>();
+ HashMap<ContractId, Contract> resolvedContracts = new HashMap<>();
+
+ if (unresolvedTenant.getEndpointGroup() != null) {
+ for (EndpointGroup eg : unresolvedTenant.getEndpointGroup()) {
+ resolveEndpointGroup(unresolvedTenant, eg, resolvedEgs);
+ }
+ }
+ if (unresolvedTenant.getContract() != null) {
+ for (Contract c : unresolvedTenant.getContract()) {
+ resolveContract(unresolvedTenant, c, resolvedContracts);
+ }
+ }
+
+ // XXX TODO - inherit from common tenant
+
+ return new TenantBuilder()
+ .setId(unresolvedTenant.getId())
+ .setName(unresolvedTenant.getName())
+ .setDescription(unresolvedTenant.getDescription())
+ .setEndpointGroup(ImmutableList.copyOf(resolvedEgs.values()))
+ .setContract(ImmutableList.copyOf(resolvedContracts.values()))
+ .setContractRef(unresolvedTenant.getContractRef())
+ .setSubjectFeatureInstances(unresolvedTenant.getSubjectFeatureInstances())
+ .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<>();
+
+ 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);
+ }
+ }
+ }
+
+ // 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())
+ .setConsumerTargetSelector(ImmutableList.copyOf(resolvedCts.values()))
+ .setConsumerNamedSelector(ImmutableList.copyOf(resolvedCns.values()))
+ .setProviderTargetSelector(ImmutableList.copyOf(resolvedPts.values()))
+ .setProviderNamedSelector(ImmutableList.copyOf(resolvedPns.values()))
+ .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) {
+ 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) {
+ 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) {
+ 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) {
+ 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<>();
+
+ 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()
+ .setCapabilityMatcher(ImmutableList.copyOf(capMatchers.values()))
+ .setConditionMatcher(ImmutableList.copyOf(provCondMatchers.values()))
+ .build())
+ .setConsumerMatchers(new ConsumerMatchersBuilder()
+ .setRequirementMatcher(ImmutableList.copyOf(reqMatchers.values()))
+ .setConditionMatcher(ImmutableList.copyOf(consCondMatchers.values()))
+ .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();
+ resolveCapabilityMatcher(pms.getCapabilityMatcher(), capMatchers);
+ resolveConditionMatcher(pms.getConditionMatcher(), provCondMatchers);
+ }
+ if (unresolvedClause.getConsumerMatchers() != null) {
+ ConsumerMatchers cms = unresolvedClause.getConsumerMatchers();
+ resolveRequirementMatcher(cms.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);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.LabelName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RelatorName;
+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.TargetName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ConsumerSelectionRelator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ProviderSelectionRelator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Relator;
+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.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.quality.matcher.MatcherQuality;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirement;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapability;
+
+/**
+ * Utilities related to matchers and labels
+ * @author readams
+ */
+public class MatcherUtils {
+ /**
+ * Apply a quality matcher to a normalized target
+ * @param matcher the {@link QualityMatcher} to apply
+ * @param target the {@link Target} to match against
+ * @return <code>true</code> if the matcher matches the target
+ */
+ public static boolean applyQualityMatcher(QualityMatcher matcher,
+ Target target) {
+ List<MatcherLabel<QualityName,TargetName>> mls = new ArrayList<>();
+ if (matcher.getMatcherQuality() != null) {
+ for (MatcherQuality ml : matcher.getMatcherQuality()) {
+ mls.add(new MatcherLabel<>(ml.getName(),
+ ml.getTargetNamespace()));
+ }
+ }
+ Set<QualityName> toMatch = new HashSet<>();
+ for (Quality q : target.getQuality()) {
+ toMatch.add(q.getName());
+ }
+ return applyLabelMatcher(mls, matcher.getMatchType(),
+ toMatch, target.getName());
+ }
+
+ /**
+ * Apply a requirement matcher to a normalized consumer selection relator
+ * @param matcher the {@link RequirementMatcher} to apply
+ * @param target the {@link ConsumerSelectionRelator} to match against
+ * @return <code>true</code> if the matcher matches the target
+ */
+ public static boolean applyReqMatcher(RequirementMatcher matcher,
+ ConsumerSelectionRelator relator) {
+ List<MatcherLabel<RequirementName,SelectorName>> mls = new ArrayList<>();
+ if (matcher.getMatcherRequirement() != null) {
+ for (MatcherRequirement ml : matcher.getMatcherRequirement()) {
+ mls.add(new MatcherLabel<>(ml.getName(),
+ ml.getSelectorNamespace()));
+ }
+ }
+ Set<RequirementName> toMatch = new HashSet<>();
+ for (Requirement q : relator.getRequirement()) {
+ toMatch.add(q.getName());
+ }
+ return applyLabelMatcher(mls, matcher.getMatchType(),
+ toMatch, relator.getName());
+ }
+
+ /**
+ * Apply a capability matcher to a normalized provider selection relator
+ * @param matcher the {@link RequirementMatcher} to apply
+ * @param target the {@link ProviderSelectionRelator} to match against
+ * @return <code>true</code> if the matcher matches the target
+ */
+ public static boolean applyCapMatcher(CapabilityMatcher matcher,
+ ProviderSelectionRelator relator) {
+ List<MatcherLabel<CapabilityName,SelectorName>> mls = new ArrayList<>();
+ if (matcher.getMatcherCapability() != null) {
+ for (MatcherCapability ml : matcher.getMatcherCapability()) {
+ mls.add(new MatcherLabel<>(ml.getName(),
+ ml.getSelectorNamespace()));
+ }
+ }
+ Set<CapabilityName> toMatch = new HashSet<>();
+ for (Capability q : relator.getCapability()) {
+ toMatch.add(q.getName());
+ }
+ return applyLabelMatcher(mls, matcher.getMatchType(),
+ toMatch, relator.getName());
+ }
+
+ /**
+ * Functional interface used for generic label methods
+ * @author readams
+ *
+ * @param <L> The specific label type
+ * @param <LN> the related label name type
+ */
+ public interface GetLabelName<L extends Label, LN extends LabelName> {
+ /**
+ * Get the appropriate typed name for the given label
+ * @param label the label
+ * @return the name
+ */
+ public LN getName(L label);
+ }
+
+ /**
+ * A {@link GetLabelName} for qualities
+ */
+ public static final GetLabelName<Quality, QualityName> getQualityName =
+ new GetLabelName<Quality, QualityName>() {
+ @Override
+ public QualityName getName(Quality label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for matcher qualities
+ */
+ public static final GetLabelName<MatcherQuality, QualityName> getMatcherQualityName =
+ new GetLabelName<MatcherQuality, QualityName>() {
+ @Override
+ public QualityName getName(MatcherQuality label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for requirements
+ */
+ public static final GetLabelName<Requirement, RequirementName> getRequirementName =
+ new GetLabelName<Requirement, RequirementName>() {
+ @Override
+ public RequirementName getName(Requirement label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for matcher requirements
+ */
+ public static final GetLabelName<MatcherRequirement, RequirementName> getMatcherRequirementName =
+ new GetLabelName<MatcherRequirement, RequirementName>() {
+ @Override
+ public RequirementName getName(MatcherRequirement label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for capabilities
+ */
+ public static final GetLabelName<Capability, CapabilityName> getCapabilityName =
+ new GetLabelName<Capability, CapabilityName>() {
+ @Override
+ public CapabilityName getName(Capability label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for matcher capabilities
+ */
+ public static final GetLabelName<MatcherCapability, CapabilityName> getMatcherCapabilityName =
+ new GetLabelName<MatcherCapability, CapabilityName>() {
+ @Override
+ public CapabilityName getName(MatcherCapability label) {
+ return label.getName();
+ }
+ };
+
+ /**
+ * A {@link GetLabelName} for capabilities
+ */
+ public static final GetLabelName<Condition, ConditionName> getConditionName =
+ new GetLabelName<Condition, ConditionName>() {
+ @Override
+ public ConditionName getName(Condition label) {
+ return label.getName();
+ }
+ };
+
+ @Immutable
+ private static class MatcherLabel<LN extends LabelName,
+ NS extends RelatorName> {
+ final LN name;
+ final NS namespace;
+
+ public MatcherLabel(LN name, NS namespace) {
+ super();
+ this.name = name;
+ this.namespace = namespace;
+ }
+ }
+ private static <LN extends LabelName, L extends Label,
+ NS extends RelatorName, R extends Relator>
+ boolean applyLabelMatcher(Collection<MatcherLabel<LN, NS>> matcherLabels,
+ MatchType matchType,
+ Set<LN> toMatch,
+ NS matchNamespace) {
+ int matches = 0;
+ int matchersize = 0;
+ if (matcherLabels != null) {
+ matchersize = matcherLabels.size();
+ for (MatcherLabel<LN, NS> matcherLabel : matcherLabels) {
+ if (matcherLabel.namespace != null &&
+ !matcherLabel.namespace.equals(matchNamespace))
+ continue;
+ if (!toMatch.contains(matcherLabel.name))
+ continue;
+ matches += 1;
+ }
+ }
+ if (matchType == null) matchType = MatchType.All;
+ switch (matchType) {
+ case Any:
+ return matches > 0;
+ case None:
+ return matches == 0;
+ case All:
+ default:
+ return matches == matchersize;
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.resolver.internal;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+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.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Table;
+
+/**
+ * Represent the policy relationships between endpoint groups
+ * @author readams
+ *
+ */
+class PolicyCache {
+
+ /**
+ * Store a policy object for each endpoint group pair. The table
+ * is stored with the key as (consumer, provider). Two endpoints could
+ * appear in both roles at the same time, in which case both policies would
+ * apply.
+ */
+ AtomicReference<Table<EgKey, EgKey, Policy>> policy =
+ new AtomicReference<>();
+
+
+ protected void updatePolicy(Table<EgKey, EgKey, Policy> newPolicy) {
+ Table<EgKey, EgKey, Policy> oldPolicy = policy.getAndSet(newPolicy);
+
+ // TODO compute delta between old and new policy and notify listeners
+ }
+
+ // **************
+ // Helper classes
+ // **************
+
+ @Immutable
+ protected static class Policy {
+ final Table<ConditionSet, ConditionSet, List<RuleGroup>> ruleMap;
+ public Policy(Table<ConditionSet, ConditionSet, List<RuleGroup>> ruleMap) {
+ super();
+ this.ruleMap = ruleMap;
+ }
+ @Override
+ public String toString() {
+ return "Policy [ruleMap=" + ruleMap + "]";
+ }
+ }
+
+ @Immutable
+ protected static class RuleGroup implements Comparable<RuleGroup> {
+ final List<Rule> rules;
+ final Integer order;
+ final Tenant contractTenant;
+ final Contract relatedContract;
+ final SubjectName relatedSubject;
+
+ public RuleGroup(List<Rule> rules, Integer order,
+ Tenant contractTenant, Contract contract,
+ SubjectName subject) {
+ super();
+ this.rules = rules;
+ this.order = order;
+ this.contractTenant = contractTenant;
+ this.relatedContract = contract;
+ this.relatedSubject = subject;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((order == null) ? 0 : order.hashCode());
+ result = prime * result + ((rules == null) ? 0 : rules.hashCode());
+ result = prime * result +
+ ((relatedSubject == null) ? 0 : relatedSubject.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RuleGroup other = (RuleGroup) obj;
+ if (order == null) {
+ if (other.order != null)
+ return false;
+ } else if (!order.equals(other.order))
+ return false;
+ if (rules == null) {
+ if (other.rules != null)
+ return false;
+ } else if (!rules.equals(other.rules))
+ return false;
+ if (relatedSubject == null) {
+ if (other.relatedSubject != null)
+ return false;
+ } else if (!relatedSubject.equals(other.relatedSubject))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(RuleGroup o) {
+ return ComparisonChain.start()
+ .compare(order, o.order,
+ Ordering.natural().nullsLast())
+ .result();
+ }
+
+ @Override
+ public String toString() {
+ return "RuleGroup [rules=" + rules + ", order=" + order +
+ ", contractTenant=" + contractTenant.getId() +
+ ", relatedContract=" + relatedContract.getId() +
+ ", relatedSubject=" + relatedSubject + "]";
+ }
+
+ }
+
+ @Immutable
+ protected static class EgKey {
+ private final TenantId tenantId;
+ private final EndpointGroupId egId;
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((egId == null) ? 0 : egId.hashCode());
+ result = prime * result +
+ ((tenantId == null) ? 0 : tenantId.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ EgKey other = (EgKey) obj;
+ if (egId == null) {
+ if (other.egId != null)
+ return false;
+ } else if (!egId.equals(other.egId))
+ return false;
+ if (tenantId == null) {
+ if (other.tenantId != null)
+ return false;
+ } else if (!tenantId.equals(other.tenantId))
+ return false;
+ return true;
+ }
+ public EgKey(TenantId tenantId, EndpointGroupId egId) {
+ super();
+ this.tenantId = tenantId;
+ this.egId = egId;
+ }
+ @Override
+ public String toString() {
+ return "EgKey [tenantId=" + tenantId + ", egId=" + egId + "]";
+ }
+ }
+
+ /**
+ * Represents a set of conditions for endpoint groups. For an endpoint
+ * to match the condition set, all the conditions in "all" must match,
+ * and none of the conditions in "none" can match. Additionally, in
+ * each set of "any" conditions, at least one condition must match.
+ * Note that if all sets are empty, then the condition set matches
+ * automatically
+ * @author readams
+ */
+ @Immutable
+ public static class ConditionSet {
+ private final Set<ConditionName> all;
+ private final Set<ConditionName> none;
+ private final Set<? extends Set<ConditionName>> any;
+ private final int hashCode;
+
+ public static final ConditionSet EMPTY =
+ new ConditionSet(Collections.<ConditionName>emptySet(),
+ Collections.<ConditionName>emptySet(),
+ Collections.<Set<ConditionName>>emptySet());
+
+ public ConditionSet(Set<ConditionName> all,
+ Set<ConditionName> none,
+ Set<? extends Set<ConditionName>> any) {
+ super();
+ this.all = all;
+ this.none = none;
+ this.any = any;
+ this.hashCode = computeHashCode();
+ }
+
+ private int computeHashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((all == null) ? 0 : all.hashCode());
+ result = prime * result + ((any == null) ? 0 : any.hashCode());
+ result = prime * result + ((none == null) ? 0 : none.hashCode());
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ConditionSet other = (ConditionSet) obj;
+ if (all == null) {
+ if (other.all != null)
+ return false;
+ } else if (!all.equals(other.all))
+ return false;
+ if (any == null) {
+ if (other.any != null)
+ return false;
+ } else if (!any.equals(other.any))
+ return false;
+ if (none == null) {
+ if (other.none != null)
+ return false;
+ } else if (!none.equals(other.none))
+ return false;
+ return true;
+ }
+ @Override
+ public String toString() {
+ return "ConditionSet [all=" + all + ", none=" + none + ", any=" +
+ any + "]";
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+/**
+ * An error in resolving policy
+ * @author readams
+ */
+public class PolicyResolutionException extends Exception {
+
+ private static final long serialVersionUID = -5737401204099404140L;
+
+ public PolicyResolutionException() {
+ super();
+ }
+
+ public PolicyResolutionException(String message, Throwable cause,
+ boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public PolicyResolutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PolicyResolutionException(String message) {
+ super(message);
+ }
+
+ public PolicyResolutionException(Throwable cause) {
+ super(cause);
+ }
+
+}
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyListener;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyResolverService;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.ConditionSet;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.Policy;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.RuleGroup;
+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.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ConsumerSelectionRelator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ProviderSelectionRelator;
+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.target.selector.QualityMatcher;
+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.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
+
+/**
+ * Implementation for {@link PolicyResolverService}
+ * @author readams
+ */
+public class PolicyResolver implements PolicyResolverService {
+ private final DataBrokerService dataProvider;
+
+ /**
+ * Keep track of the current relevant policy scopes.
+ */
+ private CopyOnWriteArrayList<PolicyScopeImpl> scopes;
+
+ private ConcurrentMap<TenantId, TenantContext> resolvedTenants;
+
+ private PolicyCache policyCache = new PolicyCache();
+
+ public PolicyResolver(DataBrokerService dataProvider) {
+ super();
+ this.dataProvider = dataProvider;
+ scopes = new CopyOnWriteArrayList<>();
+ resolvedTenants = new ConcurrentHashMap<>();
+ }
+
+ // *********************
+ // PolicyResolverService
+ // *********************
+
+ @Override
+ public List<Rule> getPolicy(EndpointGroupId ep1Group,
+ Collection<Condition> ep1Conds,
+ EndpointGroupId ep2Group,
+ Collection<Condition> ep2Conds) {
+ return null;
+ }
+
+ @Override
+ public PolicyScope registerListener(PolicyListener listener) {
+ PolicyScopeImpl ps = new PolicyScopeImpl(this, listener);
+ scopes.add(ps);
+
+ return ps;
+ }
+
+ @Override
+ public void removeListener(PolicyScope scope) {
+ scopes.remove(scope);
+ }
+
+ // *****************
+ // Protected methods
+ // *****************
+
+ private void updateTenant(TenantId tenantId) {
+ TenantContext context = resolvedTenants.get(tenantId);
+ if (context == null) {
+ ListenerRegistration<DataChangeListener> registration =
+ dataProvider.registerDataChangeListener(TenantUtils.tenantIid(tenantId),
+ new PolicyChangeListener(tenantId));
+
+ context = new TenantContext(tenantId, registration);
+ TenantContext oldContext =
+ resolvedTenants.putIfAbsent(tenantId, context);
+ if (oldContext != null) {
+ // already registered in a different thread; just use the other
+ // context
+ registration.close();
+ context = oldContext;
+ }
+ }
+ // Resolve the new tenant and update atomically
+ boolean cont = true;
+ Tenant t = null;
+ while (cont) {
+ Tenant ot = context.tenant.get();
+ DataModificationTransaction transaction =
+ dataProvider.beginTransaction();
+ t = InheritanceUtils.resolveTenant(tenantId, transaction);
+ cont = !context.tenant.compareAndSet(ot, t);
+ }
+
+ // Update the policy cache and notify listeners
+ Table<EgKey, EgKey, Policy> policy = resolvePolicy(t);
+ policyCache.updatePolicy(policy);
+ }
+
+ /**
+ * Resolve the policy in three phases:
+ * (1) select contracts that in scope based on contract selectors.
+ * (2) select subjects that are in scope for each contract based on
+ * matchers in clauses
+ * (3) resolve the set of in-scope contracts into a list of subjects that
+ * apply for each pair of endpoint groups and the conditions that can
+ * apply for for each endpoint in those groups.
+ */
+ protected Table<EgKey, EgKey, Policy> resolvePolicy(Tenant t) {
+ // select contracts that apply for the given tenant
+ Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
+ selectContracts(t);
+
+ // select subjects for the matching contracts and resolve the policy
+ // for endpoint group pairs. This does phase (2) and (3) as one step
+ return selectSubjects(contractMatches);
+ }
+
+ /**
+ * Choose the contracts that are in scope for each pair of endpoint
+ * groups, then perform subject selection for the pair
+ */
+ protected Table<EgKey, EgKey, List<ContractMatch>>
+ selectContracts(Tenant tenant) {
+ // For each endpoint group, match consumer selectors
+ // against contracts to get a set of matching consumer selectors
+ Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches =
+ HashBasedTable.create();
+ if (tenant.getEndpointGroup() == null) return HashBasedTable.create();
+ for (EndpointGroup group : tenant.getEndpointGroup()) {
+ List<ConsumerContractMatch> r =
+ matchConsumerContracts(tenant, group);
+ for (ConsumerContractMatch ccm : r) {
+ List<ConsumerContractMatch> cms =
+ consumerMatches.get(tenant.getId(),
+ ccm.contract.getId());
+ if (cms == null) {
+ cms = new ArrayList<>();
+ consumerMatches.put(tenant.getId(),
+ ccm.contract.getId(), cms);
+ }
+ cms.add(ccm);
+ }
+ }
+
+ // Match provider selectors, and check each match for a corresponding
+ // consumer selector match.
+ Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
+ HashBasedTable.create();
+ for (EndpointGroup group : tenant.getEndpointGroup()) {
+ List<ContractMatch> matches =
+ matchProviderContracts(tenant, group, consumerMatches);
+ for (ContractMatch cm : matches) {
+ EgKey consumerKey = new EgKey(cm.consumerTenant.getId(),
+ cm.consumer.getId());
+ EgKey providerKey = new EgKey(cm.providerTenant.getId(),
+ cm.provider.getId());
+ List<ContractMatch> egPairMatches =
+ contractMatches.get(consumerKey, providerKey);
+ if (egPairMatches == null) {
+ egPairMatches = new ArrayList<>();
+ contractMatches.put(consumerKey, providerKey,
+ egPairMatches);
+ }
+
+ egPairMatches.add(cm);
+ }
+ }
+ return contractMatches;
+ }
+
+ private boolean clauseMatches(Clause clause, ContractMatch match) {
+ if (clause.getConsumerMatchers() != null) {
+ List<RequirementMatcher> reqMatchers =
+ clause.getConsumerMatchers().getRequirementMatcher();
+ if (reqMatchers != null) {
+ for (RequirementMatcher reqMatcher : reqMatchers) {
+ if (!MatcherUtils.applyReqMatcher(reqMatcher,
+ match.consumerRelator)) {
+ return false;
+ }
+ }
+ }
+ }
+ if (clause.getProviderMatchers() != null) {
+ List<CapabilityMatcher> capMatchers =
+ clause.getProviderMatchers().getCapabilityMatcher();
+ if (capMatchers != null) {
+ for (CapabilityMatcher capMatcher : capMatchers) {
+ if (!MatcherUtils.applyCapMatcher(capMatcher,
+ match.providerRelator)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private 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 ConditionSet buildConsConditionSet(Clause clause) {
+ if (clause.getConsumerMatchers() != null) {
+ List<ConditionMatcher> condMatchers =
+ clause.getConsumerMatchers().getConditionMatcher();
+ return buildConditionSet(condMatchers);
+ }
+ return ConditionSet.EMPTY;
+ }
+
+ private ConditionSet buildProvConditionSet(Clause clause) {
+ if (clause.getProviderMatchers() != null) {
+ List<ConditionMatcher> condMatchers =
+ clause.getProviderMatchers().getConditionMatcher();
+ return buildConditionSet(condMatchers);
+ }
+ return ConditionSet.EMPTY;
+ }
+
+ private Policy resolvePolicy(Tenant contractTenant,
+ Contract contract,
+ Policy merge,
+ Table<ConditionSet, ConditionSet, List<Subject>> subjectMap) {
+ Table<ConditionSet, ConditionSet, List<RuleGroup>> ruleMap =
+ HashBasedTable.create();
+ if (merge != null) {
+ ruleMap.putAll(merge.ruleMap);
+ }
+ for (Cell<ConditionSet, ConditionSet, List<Subject>> entry :
+ subjectMap.cellSet()) {
+ List<RuleGroup> rules = new ArrayList<>();
+ List<RuleGroup> oldrules =
+ ruleMap.get(entry.getRowKey(), entry.getColumnKey());
+ if (oldrules != null) {
+ rules.addAll(oldrules);
+ }
+ for (Subject s : entry.getValue()) {
+ if (s.getRule() == null) continue;
+ List<Rule> srules = Ordering
+ .from(TenantUtils.RULE_COMPARATOR)
+ .immutableSortedCopy(s.getRule());
+ RuleGroup rg = new RuleGroup(srules, s.getOrder(),
+ contractTenant, contract,
+ s.getName());
+ rules.add(rg);
+ }
+ Collections.sort(rules);
+ ruleMap.put(entry.getRowKey(), entry.getColumnKey(),
+ Collections.unmodifiableList(rules));
+ }
+ return new Policy(ruleMap);
+ }
+
+ /**
+ * Choose the set of subjects that in scope for each possible set of
+ * endpoint conditions
+ */
+ protected Table<EgKey, EgKey, Policy>
+ selectSubjects(Table<EgKey, EgKey,
+ List<ContractMatch>> contractMatches) {
+ // 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);
+ boolean alreadyMatched = false;
+ if (existing != null) {
+ for (List<RuleGroup> rgl : existing.ruleMap.values()) {
+ for (RuleGroup rg : rgl) {
+ if (rg.relatedContract == match.contract) {
+ alreadyMatched = true;
+ break;
+ }
+ }
+ if (alreadyMatched) break;
+ }
+ if (alreadyMatched) continue;
+ }
+
+ HashMap<SubjectName, Subject> subjects = new HashMap<>();
+ for (Subject s : subjectList) {
+ subjects.put(s.getName(), s);
+ }
+
+ Table<ConditionSet, ConditionSet, List<Subject>> subjectMap =
+ HashBasedTable.create();
+
+ for (Clause clause : clauses) {
+ if (clause.getSubjectRefs() != null &&
+ clauseMatches(clause, match)) {
+ ConditionSet consCSet = buildConsConditionSet(clause);
+ ConditionSet provCSet = buildProvConditionSet(clause);
+ List<Subject> clauseSubjects =
+ subjectMap.get(consCSet, provCSet);
+ if (clauseSubjects == null) {
+ clauseSubjects = new ArrayList<>();
+ subjectMap.put(consCSet, provCSet, 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 List<ConsumerContractMatch> matchConsumerContracts(Tenant tenant,
+ EndpointGroup consumer) {
+ List<ConsumerContractMatch> matches = new ArrayList<>();
+ if (consumer.getConsumerNamedSelector() != null) {
+ for (ConsumerNamedSelector cns : consumer.getConsumerNamedSelector()) {
+ if (cns.getContract() == null) continue;
+ for (ContractId contractId : cns.getContract()) {
+ Contract contract =
+ TenantUtils.findContract(tenant, contractId);
+ if (contract == null) continue;
+ matches.add(new ConsumerContractMatch(tenant, contract,
+ tenant, consumer,
+ cns));
+ }
+ }
+ }
+ if (consumer.getConsumerTargetSelector() != null) {
+ for (ConsumerTargetSelector cts : consumer.getConsumerTargetSelector()) {
+ if (tenant.getContract() == null) continue;
+ for (Contract contract : tenant.getContract()) {
+ if (contract.getTarget() == null) continue;
+ for (Target t : contract.getTarget()) {
+ boolean match = true;
+ if (cts.getQualityMatcher() != null) {
+ for (QualityMatcher m : cts.getQualityMatcher()) {
+ if (!MatcherUtils.applyQualityMatcher(m, t)) {
+ match = false;
+ break;
+ }
+ }
+ }
+ if (match) {
+ matches.add(new ConsumerContractMatch(tenant,
+ contract,
+ tenant,
+ consumer,
+ cts));
+ }
+ }
+ }
+ }
+ }
+ // TODO match selectors also against contract references
+// for (ConsumerTargetSelector cts : consumer.getConsumerTargetSelector()) {
+// if (tenant.getContractRef() == null) continue;
+// for (ContractRef c : tenant.getContractRef()) {
+//
+// }
+// }
+ return matches;
+ }
+
+ private void amendContractMatches(List<ContractMatch> matches,
+ List<ConsumerContractMatch> cMatches,
+ Tenant tenant, EndpointGroup provider,
+ ProviderSelectionRelator relator) {
+ if (cMatches == null) return;
+ for (ConsumerContractMatch cMatch : cMatches) {
+ matches.add(new ContractMatch(cMatch, tenant, provider, relator));
+ }
+ }
+
+ private List<ContractMatch>
+ matchProviderContracts(Tenant tenant, EndpointGroup provider,
+ Table<TenantId,
+ ContractId,
+ List<ConsumerContractMatch>> consumerMatches) {
+ List<ContractMatch> matches = new ArrayList<>();
+ if (provider.getProviderNamedSelector() != null) {
+ for (ProviderNamedSelector pns : provider.getProviderNamedSelector()) {
+ if (pns.getContract() == null) continue;
+ for (ContractId contractId : pns.getContract()) {
+ Contract c = TenantUtils.findContract(tenant, contractId);
+ if (c == null) continue;
+ List<ConsumerContractMatch> cMatches =
+ consumerMatches.get(tenant.getId(), c.getId());
+ amendContractMatches(matches, cMatches, tenant, provider, pns);
+ }
+ }
+ }
+ if (provider.getProviderTargetSelector() != null) {
+ for (ProviderTargetSelector pts : provider.getProviderTargetSelector()) {
+ if (tenant.getContract() == null) continue;
+ for (Contract c : tenant.getContract()) {
+ if (c.getTarget() == null) continue;
+ for (Target t : c.getTarget()) {
+ boolean match = true;
+ if (pts.getQualityMatcher() != null) {
+ for (QualityMatcher m : pts.getQualityMatcher()) {
+ if (!MatcherUtils.applyQualityMatcher(m, t)) {
+ match = false;
+ break;
+ }
+ }
+ }
+ if (match) {
+ List<ConsumerContractMatch> cMatches =
+ consumerMatches.get(tenant.getId(),
+ c.getId());
+ amendContractMatches(matches, cMatches, tenant,
+ provider, pts);
+
+ }
+ }
+ }
+ }
+ }
+ return matches;
+ }
+
+ private static class TenantContext {
+ TenantId tenantId;
+ ListenerRegistration<DataChangeListener> registration;
+
+ AtomicReference<Tenant> tenant = new AtomicReference<Tenant>();
+
+ public TenantContext(TenantId tenantId,
+ ListenerRegistration<DataChangeListener> registration) {
+ super();
+ this.tenantId = tenantId;
+ this.registration = registration;
+ }
+ }
+
+ /**
+ * Represents a selected contract made by endpoint groups matching it
+ * using selection relators. This is the result of the contract selection
+ * phase.
+ * @author readams
+ *
+ */
+ @Immutable
+ protected static class ContractMatch extends ConsumerContractMatch {
+ /**
+ * The tenant ID of the provider endpoint group
+ */
+ final Tenant providerTenant;
+
+ /**
+ * The provider endpoint group
+ */
+ final EndpointGroup provider;
+
+ /**
+ * The provider selection relator that was used to match the contract
+ */
+ final ProviderSelectionRelator providerRelator;
+
+ public ContractMatch(ConsumerContractMatch consumerMatch,
+ Tenant providerTenant, EndpointGroup provider,
+ ProviderSelectionRelator providerRelator) {
+ super(consumerMatch.contractTenant,
+ consumerMatch.contract,
+ consumerMatch.consumerTenant,
+ consumerMatch.consumer,
+ consumerMatch.consumerRelator);
+ this.providerTenant = providerTenant;
+ this.provider = provider;
+ this.providerRelator = providerRelator;
+ }
+ }
+
+ @Immutable
+ private static class ConsumerContractMatch {
+ /**
+ * The tenant of the matching contract
+ */
+ final Tenant contractTenant;
+
+ /**
+ * The matching contract
+ */
+ final Contract contract;
+
+ /**
+ * The tenant for the endpoint group
+ */
+ final Tenant consumerTenant;
+
+ /**
+ * The consumer endpoint group
+ */
+ final EndpointGroup consumer;
+
+ /**
+ * The consumer selection relator that was used to match the contract
+ */
+ final ConsumerSelectionRelator consumerRelator;
+
+
+ public ConsumerContractMatch(Tenant contractTenant,
+ Contract contract,
+ Tenant consumerTenant,
+ EndpointGroup consumer,
+ ConsumerSelectionRelator consumerRelator) {
+ super();
+ this.contractTenant = contractTenant;
+ this.contract = contract;
+ this.consumerTenant = consumerTenant;
+ this.consumer = consumer;
+ this.consumerRelator = consumerRelator;
+ }
+ }
+
+ @Immutable
+ private class PolicyChangeListener implements DataChangeListener {
+ final TenantId tenantId;
+
+ public PolicyChangeListener(TenantId tenantId) {
+ super();
+ this.tenantId = tenantId;
+ }
+
+ @Override
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>,
+ DataObject> change) {
+ updateTenant(tenantId);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.groupbasedpolicy.resolver.PolicyListener;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyResolverService;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+
+/**
+ * Implementation for {@link PolicyScope}
+ * @author readams
+ */
+public class PolicyScopeImpl implements PolicyScope {
+ /**
+ * The parent resolver for this scope.
+ */
+ private final PolicyResolverService resolver;
+
+ /**
+ * The listener for this policy scope
+ */
+ private final PolicyListener listener;
+
+ /**
+ * The set of policy scope elements that we want to listen to.
+ */
+ private Set<PolicyScopeElement> scopeElements;
+
+ public PolicyScopeImpl(PolicyResolverService resolver,
+ PolicyListener listener) {
+ super();
+ this.resolver = resolver;
+ this.listener = listener;
+ Map<PolicyScopeElement,Boolean> smap = new ConcurrentHashMap<>();
+ scopeElements = Collections.newSetFromMap(smap);
+ }
+
+ // ***********
+ // PolicyScope
+ // ***********
+
+ @Override
+ public void addToScope(TenantId tenant, EndpointGroupId endpointGroup) {
+ scopeElements.add(new PolicyScopeElement(tenant, endpointGroup));
+ }
+
+ @Override
+ public void addToScope(TenantId tenant) {
+ scopeElements.add(new PolicyScopeElement(tenant, null));
+ }
+
+ // ***************
+ // PolicyScopeImpl
+ // ***************
+
+ protected Set<PolicyScopeElement> getScopeElements() {
+ return scopeElements;
+ }
+
+ protected static class PolicyScopeElement {
+ private final TenantId tenant;
+ private final EndpointGroupId endpointGroup;
+ public PolicyScopeElement(TenantId tenant,
+ EndpointGroupId endpointGroup) {
+ super();
+ this.tenant = tenant;
+ this.endpointGroup = endpointGroup;
+ }
+ public TenantId getTenant() {
+ return tenant;
+ }
+ public EndpointGroupId getEndpointGroup() {
+ return endpointGroup;
+ }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result +
+ ((endpointGroup == null) ? 0 : endpointGroup.hashCode());
+ result = prime * result + ((tenant == null) ? 0 : tenant.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PolicyScopeElement other = (PolicyScopeElement) obj;
+ if (endpointGroup == null) {
+ if (other.endpointGroup != null)
+ return false;
+ } else if (!endpointGroup.equals(other.endpointGroup))
+ return false;
+ if (tenant == null) {
+ if (other.tenant != null)
+ return false;
+ } else if (!tenant.equals(other.tenant))
+ return false;
+ return true;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.Comparator;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+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.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.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+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.TenantKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+
+/**
+ * Static methods for manipulating group-based policy tenants
+ * @author readams
+ */
+public class TenantUtils {
+ /**
+ * A comparator that assigns the natural ordering for rules, null-aware
+ * @author readams
+ */
+ public static class RuleComparator implements Comparator<Rule> {
+
+ @Override
+ public int compare(Rule o1, Rule o2) {
+ return ComparisonChain.start()
+ .compare(o1.getOrder(), o2.getOrder(),
+ Ordering.natural().nullsLast())
+ .result();
+ }
+
+ }
+
+ /**
+ * An instance of RuleComparator
+ */
+ public static final RuleComparator RULE_COMPARATOR = new RuleComparator();
+
+ /**
+ * Generate an {@link InstanceIdentifier} for an {@link Tenant}
+ * @param tenantKey a tenant key
+ * @return the {@link InstanceIdentifier}
+ */
+ public static InstanceIdentifier<Tenant> tenantIid(TenantKey tenantKey) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, tenantKey)
+ .build();
+ }
+
+ /**
+ * Generate an {@link InstanceIdentifier} for an {@link Tenant}
+ * @param tenantId a tenant id
+ * @return the {@link InstanceIdentifier}
+ */
+ public static InstanceIdentifier<Tenant> tenantIid(TenantId tenantId) {
+ return tenantIid(new TenantKey(tenantId));
+ }
+
+ /**
+ * Find a contract with a specified ID within a tenant
+ * @param tenant the {@link Tenant} to search
+ * @param contractId the {@link ContractId} to search for
+ * @return the {@link Contract} if it exists, null otherwise
+ */
+ public static Contract findContract(Tenant tenant,
+ ContractId contractId) {
+ if (tenant.getContract() != null) {
+ for (Contract c : tenant.getContract()) {
+ if (contractId.equals(c.getId())) {
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a clause with a specified name within a contract
+ * @param tenant the {@link Contract} to search
+ * @param contractId the {@link ClauseName} to search for
+ * @return the {@link Clause} if it exists, null otherwise
+ */
+ public static Clause findClause(Contract contract,
+ ClauseName clauseName) {
+ if (contract.getClause() != null) {
+ for (Clause c : contract.getClause()) {
+ if (clauseName.equals(c.getName())) {
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a subject with a specified name within a contract
+ * @param tenant the {@link Contract} to search
+ * @param subjectName the {@link SubjectName} to search for
+ * @return the {@link Subject} if it exists, null otherwise
+ */
+ public static Subject findSubject(Contract contract,
+ SubjectName subjectName) {
+ if (contract.getSubject() != null) {
+ for (Subject c : contract.getSubject()) {
+ if (subjectName.equals(c.getName())) {
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a target with a specified name within a contract
+ * @param contract the {@link Contract} to search
+ * @param targetName the {@link TargetName} to search for
+ * @return the {@link Target} if it exists, null otherwise
+ */
+ public static Target findTarget(Contract contract,
+ TargetName targetName) {
+ if (contract.getTarget() != null) {
+ for (Target t : contract.getTarget()) {
+ if (targetName.equals(t.getName())) {
+ return t;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find an endpoint group with a specified ID within a tenant
+ * @param tenant the {@link Tenant} to search
+ * @param egId the {@link EndpointGroupId} to search for
+ * @return the {@link EndpointGroup} if it exists, null otherwise
+ */
+ public static EndpointGroup findEndpointGroup(Tenant tenant,
+ EndpointGroupId egId) {
+ if (tenant.getEndpointGroup() != null) {
+ for (EndpointGroup eg : tenant.getEndpointGroup()) {
+ if (egId.equals(eg.getId())) {
+ return eg;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a consumer named selector in an endpoint group
+ * @param eg the {@link EndpointGroup} to search
+ * @param name the {@link NamedSelectorName} to search for
+ * @return the {@link ConsumerNamedSelector} if it exists, null otherwise
+ */
+ public static ConsumerNamedSelector findCns(EndpointGroup eg,
+ SelectorName name) {
+ if (eg.getConsumerNamedSelector() != null) {
+ for (ConsumerNamedSelector s : eg.getConsumerNamedSelector()) {
+ if (name.equals(s.getName()))
+ return s;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a consumer target selector in an endpoint group
+ * @param eg the {@link EndpointGroup} to search
+ * @param name the {@link SelectorName} to search for
+ * @return the {@link ConsumerNamedSelector} if it exists, null otherwise
+ */
+ public static ConsumerTargetSelector findCts(EndpointGroup eg,
+ SelectorName name) {
+ if (eg.getConsumerTargetSelector() != null) {
+ for (ConsumerTargetSelector s : eg.getConsumerTargetSelector()) {
+ if (name.equals(s.getName()))
+ return s;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a provider named selector in an endpoint group
+ * @param eg the {@link EndpointGroup} to search
+ * @param name the {@link NamedSelectorName} to search for
+ * @return the {@link ProviderNamedSelector} if it exists, null otherwise
+ */
+ public static ProviderNamedSelector findPns(EndpointGroup eg,
+ SelectorName name) {
+ if (eg.getProviderNamedSelector() != null) {
+ for (ProviderNamedSelector s : eg.getProviderNamedSelector()) {
+ if (name.equals(s.getName()))
+ return s;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a provider target selector in an endpoint group
+ * @param eg the {@link EndpointGroup} to search
+ * @param name the {@link TargetSelectorName} to search for
+ * @return the {@link ProviderNamedSelector} if it exists, null otherwise
+ */
+ public static ProviderTargetSelector findPts(EndpointGroup eg,
+ SelectorName name) {
+ if (eg.getProviderTargetSelector() != null) {
+ for (ProviderTargetSelector s : eg.getProviderTargetSelector()) {
+ if (name.equals(s.getName()))
+ return s;
+ }
+ }
+ return null;
+ }
+}
description "A name for a selector.";
}
- typedef named-selector-name {
- type selector-name;
- description "A name for a named selector.";
- }
-
- typedef target-selector-name {
- type selector-name;
- description "A name for a target selector.";
- }
-
// *****************
// Unique object IDs
// *****************
description "A unique ID for a contract";
}
- typedef matcher-id {
- type unique-id;
- description "A unique ID for a matcher";
+ // *************
+ // Matcher names
+ // *************
+
+ typedef matcher-name {
+ type name;
+ description "A name for a matcher";
}
- typedef quality-matcher-id {
- type matcher-id;
- description "A unique ID for a quality matcher";
+ typedef quality-matcher-name {
+ type matcher-name;
+ description "A name for a quality matcher";
}
- typedef requirement-matcher-id {
- type matcher-id;
- description "A unique ID for a matcher";
+ typedef requirement-matcher-name {
+ type matcher-name;
+ description "A name for a requirement matcher";
}
- typedef condition-matcher-id {
- type matcher-id;
- description "A unique ID for a condition matcher";
+ typedef condition-matcher-name {
+ type matcher-name;
+ description "A name for a condition matcher";
}
- typedef capability-matcher-id {
- type matcher-id;
- description "A unique ID for a capability matcher";
+ typedef capability-matcher-name {
+ type matcher-name;
+ description "A name for a capability matcher";
}
// *************
}
}
- typedef name-inheritance {
- description
- "Determines how names are inherited by matchers. Names are
- used by matchers to narrow the scope of labels against
- which they match to only particular targets or selectors.";
-
- type enumeration {
- enum inherit {
- description
- "Inherit the name parameter from the parent
- matcher. If there is no parent matcher, then
- acts as if 'specified' were selected.";
- }
- enum specified {
- description
- "Match against only the specied target or selector
- name, as appropriate for the context.";
- }
- }
- }
-
grouping quality-base {
description "Base type for qualities and matcher qualities.";
leaf name {
}
}
+ grouping has-condition-matchers {
+ description "Objects with condition matchers";
+ list condition-matcher {
+ description "Match against conditions on endpoints.";
+
+ key "name";
+ leaf name {
+ description
+ "A name for the condition matcher";
+ type gbp-common:condition-matcher-name;
+ mandatory true;
+ }
+
+ uses matcher;
+ uses has-conditions;
+ }
+ }
+
// ************************
// Endpoint group groupings
// ************************
"Selection relators allow endpoint groups to select
contracts based on their name or on their qualities.";
uses relator;
+
+ leaf name {
+ description "A name for the selector";
+ type gbp-common:selector-name;
+ mandatory true;
+ }
}
grouping consumer-selection-relator {
"A selection relator for matching contracts to meet
endpoint group requirements. See consumer-named-selector
and consumer-target-selector for more details.";
-
+ uses selection-relator;
uses has-requirements;
}
"A selection relator for matching contracts to meet
endpoint group requirements. See provider-named-selector
and provider-named-selector for more details.";
-
+ uses selection-relator;
uses has-capabilities;
}
endpoint group, and provider named selectors select
contracts to provide capabilities for the endpoint group.";
- uses selection-relator;
-
leaf name {
description "A name for the named selector.";
- type gbp-common:named-selector-name;
+ type gbp-common:selector-name;
mandatory true;
}
contracts to provide capabilities to other endpoint
groups.";
- uses selection-relator;
-
- leaf name {
- description "A name for the target selector";
- type gbp-common:target-selector-name;
- mandatory true;
- }
-
list quality-matcher {
description
"A quality matcher is used in a target selector to
match or if a match can be made with any of the
qualities.";
- key "id";
- leaf id {
- description "A unique ID for the quality matcher";
- type gbp-common:quality-matcher-id;
+ key "name";
+ leaf name {
+ description "A unique name for the quality matcher";
+ type gbp-common:quality-matcher-name;
mandatory true;
}
key name;
uses quality-base;
- leaf name-inheritance {
- description
- "Determine how the target name should be inherited
- from any parent matchers.";
-
- type name-inheritance;
- default inherit;
- }
-
- leaf target-name {
+ leaf target-namespace {
description
"The name of the target to match. This allows
us to specify that we want to match only
qualities scoped to a particular target name.
This parameter is optional; if not specified,
- match against any selector name.";
+ use an inherited target name if it exists, or
+ match against any target name.";
type gbp-common:target-name;
}
An active subject can then apply its rules to
the traffic between the endpoints.";
+ key "name";
leaf name {
description "A name for the subject";
type gbp-common:subject-name;
"Match against requirements in the consumer
endpoint group.";
- key "id";
- leaf id {
+ key "name";
+ leaf name {
description
- "A unique ID for the requirement matcher";
- type gbp-common:requirement-matcher-id;
+ "A name for the requirement matcher";
+ type gbp-common:requirement-matcher-name;
mandatory true;
}
key name;
uses requirement-base;
- leaf name-inheritance {
- description
- "Determine how the selector
- name should be inherited from
- any parent matchers.";
- type name-inheritance;
- default inherit;
- }
- leaf selector-name {
+ leaf selector-namespace {
description
"The name of the selector to
match. This allows us to
specify that we want to match
only requirements scoped to a
particular selector name.
+
This parameter is optional;
- if not specified, match
+ if not specified, use an
+ inherited selector namespace
+ if it exists, or match
against any selector name.";
type gbp-common:selector-name;
}
}
}
-
- list consumer-condition-matcher {
- description
- "Match against conditions on endpoints in the
- consumer endpoint group.";
-
- key "id";
- leaf id {
- description
- "A unique ID for the condition matcher";
- type gbp-common:condition-matcher-id;
- mandatory true;
- }
-
- uses matcher;
- uses has-conditions;
- leaf parent {
- description
- "Parent condition matcher from which
- we inherit.";
- type leafref {
- path "/tenants/tenant/contract/clause/consumer-matchers/consumer-condition-matcher/id";
- }
- }
- }
+ uses has-condition-matchers;
}
container provider-matchers {
"Match against capabilities in the provider
endpoint group.";
- key "id";
- leaf id {
+ key "name";
+ leaf name {
description
- "A unique ID for the capability matcher";
- type gbp-common:capability-matcher-id;
+ "A name for the capability matcher";
+ type gbp-common:capability-matcher-name;
mandatory true;
}
key name;
uses capability-base;
- leaf name-inheritance {
- description
- "Determine how the selector
- name should be inherited from
- any parent matchers.";
- type name-inheritance;
- default inherit;
- }
- leaf selector-name {
+
+ leaf selector-namespace {
description
"The name of the selector to
match. This allows us to
specify that we want to match
only capabilities scoped to a
particular selector name.
+
This parameter is optional;
- if not specified, match
+ if not specified, use an
+ inherited selector namespace
+ if it exists, or match
against any selector name.";
type gbp-common:selector-name;
}
}
}
-
- list provider-condition-matcher {
- description
- "Match against conditions on endpoints in the
- provider endpoint group.";
-
- key "id";
- leaf id {
- description
- "A unique ID for the condition matcher";
- type gbp-common:condition-matcher-id;
- mandatory true;
- }
-
- uses matcher;
- uses has-conditions;
-
- leaf parent {
- description
- "Parent condition matcher from which
- we inherit.";
- type leafref {
- path "/tenants/tenant/contract/clause/provider-matchers/provider-condition-matcher/id";
- }
- }
- }
+ uses has-condition-matchers;
}
// ******************
}
}
- list contract-refs {
+ list contract-ref {
description
"Contract references allow forming contracts
between endpoint groups in different tenants.
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+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.ClassifierName;
+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.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.RuleName;
+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.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.CapabilityBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Label.InclusionRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.QualityBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.RequirementBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;
+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.capabilities.CapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
+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.conditions.ConditionBuilder;
+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.qualities.QualityBuilder;
+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.has.requirements.RequirementBuilder;
+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.target.selector.quality.matcher.MatcherQualityBuilder;
+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.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.TargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelectorBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import static org.junit.Assert.*;
+
+import static org.mockito.Mockito.*;
+
+public class InheritanceUtilsTest {
+ // ******
+ // Labels
+ // ******
+
+ Quality q1 = new QualityBuilder()
+ .setName(new QualityName("q1"))
+ .build();
+ Quality q1Include = new QualityBuilder(q1)
+ .setInclusionRule(InclusionRule.Include)
+ .build();
+ Quality q1Exclude = new QualityBuilder(q1)
+ .setInclusionRule(InclusionRule.Exclude)
+ .build();
+ Quality q2 = new QualityBuilder()
+ .setName(new QualityName("q2"))
+ .build();
+ Quality q2Exclude = new QualityBuilder()
+ .setName(new QualityName("q2"))
+ .setInclusionRule(InclusionRule.Exclude)
+ .build();
+ Quality q3 = new QualityBuilder()
+ .setName(new QualityName("q3"))
+ .build();
+
+ Requirement r1 = new RequirementBuilder()
+ .setName(new RequirementName("r1"))
+ .build();
+ Requirement r2 = new RequirementBuilder()
+ .setName(new RequirementName("r2"))
+ .build();
+ Requirement r1exclude = new RequirementBuilder()
+ .setName(new RequirementName("r1"))
+ .setInclusionRule(InclusionRule.Exclude)
+ .build();
+ Requirement r3 = new RequirementBuilder()
+ .setName(new RequirementName("r3"))
+ .build();
+
+ Capability c1 = new CapabilityBuilder()
+ .setName(new CapabilityName("c1"))
+ .build();
+ Capability c2 = new CapabilityBuilder()
+ .setName(new CapabilityName("c2"))
+ .build();
+ Capability c1exclude = new CapabilityBuilder()
+ .setName(new CapabilityName("c1"))
+ .setInclusionRule(InclusionRule.Exclude)
+ .build();
+ Capability c3 = new CapabilityBuilder()
+ .setName(new CapabilityName("c3"))
+ .build();
+
+ Condition cond1 = new ConditionBuilder()
+ .setName(new ConditionName("cond1"))
+ .build();
+ Condition cond2 = new ConditionBuilder()
+ .setName(new ConditionName("cond2"))
+ .build();
+ Condition cond2exlude = new ConditionBuilder()
+ .setName(new ConditionName("cond2"))
+ .setInclusionRule(InclusionRule.Exclude)
+ .build();
+
+ // *********
+ // Contracts
+ // *********
+
+ TargetName q2TargetName = new TargetName("q2");
+ Target q2Target = new TargetBuilder()
+ .setName(q2TargetName)
+ .setQuality(ImmutableList.of(q2))
+ .build();
+
+ TargetName q1ExcludeTargetName = new TargetName("q1_exclude");
+ Target q1ExcludeTarget = new TargetBuilder()
+ .setName(q1ExcludeTargetName)
+ .setQuality(ImmutableList.of(q1Exclude, q2))
+ .build();
+
+ TargetName q1IncludeTargetName = new TargetName("q1_include");
+ Target q1IncludeTarget = new TargetBuilder()
+ .setName(q1IncludeTargetName)
+ .setQuality(ImmutableList.of(q1Include))
+ .build();
+
+ Target q2PlusTarget = new TargetBuilder()
+ .setName(q2TargetName)
+ .setQuality(ImmutableList.of(q3))
+ .build();
+
+ SubjectName subject1 = new SubjectName("subject1");
+ SubjectName subject2 = new SubjectName("subject2");
+
+ RequirementMatcher rm_r1 = new RequirementMatcherBuilder()
+ .setName(new RequirementMatcherName("rm_r1"))
+ .setMatcherRequirement(ImmutableList.of(new MatcherRequirementBuilder(r1)
+ .build()))
+ .build();
+ RequirementMatcher rm_r1_plus = new RequirementMatcherBuilder()
+ .setName(new RequirementMatcherName("rm_r1"))
+ .setMatchType(MatchType.All)
+ .setMatcherRequirement(ImmutableList.of(new MatcherRequirementBuilder(r2)
+ .build()))
+ .build();
+
+ CapabilityMatcher capm_c1 = new CapabilityMatcherBuilder()
+ .setName(new CapabilityMatcherName("capm_c1"))
+ .setMatcherCapability(ImmutableList.of(new MatcherCapabilityBuilder(c1)
+ .build()))
+ .build();
+
+ ConditionMatcher cm_c1 = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("cm_c1"))
+ .setCondition(ImmutableList.of(cond1))
+ .build();
+ ConditionMatcher cm_c2 = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("cm_c2"))
+ .setMatchType(MatchType.All)
+ .setCondition(ImmutableList.of(cond2))
+ .build();
+ ConditionMatcher cm_c2_plus = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("cm_c2"))
+ .setCondition(ImmutableList.of(cond2exlude))
+ .build();
+
+ ClauseName clauseName1 = new ClauseName("clauseName1");
+ Clause clause1 = new ClauseBuilder()
+ .setName(clauseName1)
+ .setSubjectRefs(ImmutableList.of(subject1))
+ .setProviderMatchers(new ProviderMatchersBuilder()
+ .setCapabilityMatcher(ImmutableList.of(capm_c1))
+ .setConditionMatcher(ImmutableList.of(cm_c1))
+ .build())
+ .setConsumerMatchers(new ConsumerMatchersBuilder()
+ .setRequirementMatcher(ImmutableList.of(rm_r1))
+ .setConditionMatcher(ImmutableList.of(cm_c2))
+ .build())
+ .build();
+
+ Clause clause1plus = new ClauseBuilder()
+ .setName(clauseName1)
+ .setSubjectRefs(ImmutableList.of(subject2))
+ .setConsumerMatchers(new ConsumerMatchersBuilder()
+ .setRequirementMatcher(ImmutableList.of(rm_r1_plus))
+ .setConditionMatcher(ImmutableList.of(cm_c2_plus))
+ .build())
+ .build();
+
+ ActionRef a1 = new ActionRefBuilder()
+ .setName(new ActionName("a1"))
+ .build();
+ ClassifierRef cr1 = new ClassifierRefBuilder()
+ .setName(new ClassifierName("cr1"))
+ .build();
+ Rule rule1 = new RuleBuilder()
+ .setName(new RuleName("r1"))
+ .setActionRef(ImmutableList.of(a1))
+ .setClassifierRef(ImmutableList.of(cr1))
+ .build();
+ Rule rule2 = new RuleBuilder()
+ .setName(new RuleName("r2"))
+ .setOrder(5)
+ .build();
+ Rule rule3 = new RuleBuilder()
+ .setName(new RuleName("r3"))
+ .setOrder(7)
+ .build();
+ Rule rule4 = new RuleBuilder()
+ .setName(new RuleName("r4"))
+ .setOrder(1)
+ .build();
+
+ Subject s1 = new SubjectBuilder()
+ .setName(new SubjectName("s1"))
+ .setRule(ImmutableList.of(rule1, rule2))
+ .build();
+ Subject s1_plus = new SubjectBuilder()
+ .setName(s1.getName())
+ .setRule(ImmutableList.of(rule3, rule4))
+ .setOrder(4)
+ .build();
+ Subject s2 = new SubjectBuilder()
+ .setName(new SubjectName("s2"))
+ .setOrder(5)
+ .build();
+
+ ContractId contractId1 =
+ new ContractId("e7e6804f-7fcb-46cf-9bc6-abfec0896d95");
+ Contract contract1 = new ContractBuilder()
+ .setId(contractId1)
+ .setQuality(ImmutableList.of(q1))
+ .setTarget(ImmutableList.of(q2Target,
+ q1IncludeTarget,
+ q1ExcludeTarget))
+ .setClause(ImmutableList.of(clause1))
+ .setSubject(ImmutableList.of(s1))
+ .build();
+
+ ContractId contractId2 =
+ new ContractId("3f56ae44-d1e4-4617-95af-c809dfc50149");
+ ContractKey contractKey2 = new ContractKey(contractId2);
+ Contract contract2 = new ContractBuilder()
+ .setId(contractId2)
+ .setParent(contractId1)
+ .setTarget(ImmutableList.of(q2PlusTarget, q1IncludeTarget))
+ .setClause(ImmutableList.of(clause1plus))
+ .setSubject(ImmutableList.of(s1_plus, s2))
+ .build();
+
+ ContractId cloop2Id = new ContractId("89700928-7316-4216-a853-a7ea3934b8f4");
+ Contract cloop1 = new ContractBuilder()
+ .setId(new ContractId("56bbce36-e60b-473d-92de-bb63b5a6dbb5"))
+ .setParent(cloop2Id)
+ .setClause(ImmutableList.of(clause1))
+ .setSubject(ImmutableList.of(s1, s2))
+ .build();
+ Contract cloop2 = new ContractBuilder()
+ .setId(cloop2Id)
+ .setParent(cloop1.getId())
+ .build();
+ ContractId cselfloopid =
+ new ContractId("63edead2-d6f1-4acf-9f78-831595d194ee");
+ Contract cselfloop = new ContractBuilder()
+ .setId(cselfloopid)
+ .setParent(cselfloopid)
+ .build();
+ Contract corphan = new ContractBuilder()
+ .setId(new ContractId("f72c15f3-76ab-4c7e-a817-eb5f6efcb654"))
+ .setParent(new ContractId("eca4d0d5-8c62-4f46-ad42-71c1f4d3da12"))
+ .build();
+
+ // ***************
+ // Endpoint Groups
+ // ***************
+
+ SelectorName cnsName1 = new SelectorName("cns1");
+ ConsumerNamedSelector cns1 = new ConsumerNamedSelectorBuilder()
+ .setName(cnsName1)
+ .setContract(ImmutableList.of(contractId1))
+ .setRequirement(ImmutableList.of(r2))
+ .build();
+
+ ConsumerNamedSelector cns1_plus = new ConsumerNamedSelectorBuilder()
+ .setName(cnsName1)
+ .setContract(ImmutableList.of(contractId2))
+ .setRequirement(ImmutableList.of(r3))
+ .build();
+
+ SelectorName pnsName1 = new SelectorName("cns1");
+ ProviderNamedSelector pns1 = new ProviderNamedSelectorBuilder()
+ .setName(cnsName1)
+ .setContract(ImmutableList.of(contractId1))
+ .setCapability(ImmutableList.of(c2))
+ .build();
+
+ ProviderNamedSelector pns1_plus = new ProviderNamedSelectorBuilder()
+ .setName(cnsName1)
+ .setContract(ImmutableList.of(contractId2))
+ .setCapability(ImmutableList.of(c3))
+ .build();
+
+ QualityMatcher qm_q1_all = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q1_all"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q1)
+ .build()))
+ .setMatchType(MatchType.All)
+ .build();
+ QualityMatcher qm_q1_any = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q1_any"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q1)
+ .build()))
+ .setMatchType(MatchType.Any)
+ .build();
+ QualityMatcher qm_q2q3_any = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q2q3_any"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q2)
+ .build(),
+ new MatcherQualityBuilder(q3)
+ .build()))
+ .setMatchType(MatchType.Any)
+ .build();
+
+ QualityMatcher qm_q2tq2 = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q2tq2"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q2)
+ .setTargetNamespace(q2TargetName)
+ .build()))
+ .setMatchType(MatchType.Any)
+ .build();
+ QualityMatcher qm_q2q3_plus = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q2q3_any"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q3)
+ .setTargetNamespace(q2TargetName)
+ .build(),
+ new MatcherQualityBuilder(q2Exclude)
+ .build()))
+ .setMatchType(MatchType.All)
+ .build();
+ QualityMatcher qm_q1_plus = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm_q1_any"))
+ .build();
+
+ SelectorName ctsName1 = new SelectorName("cts1");
+ ConsumerTargetSelector cts1 = new ConsumerTargetSelectorBuilder()
+ .setName(ctsName1)
+ .setQualityMatcher(ImmutableList.of(qm_q1_all, qm_q1_any))
+ .setRequirement(ImmutableList.of(r2))
+ .build();
+ SelectorName ctsName2 = new SelectorName("cts2");
+ ConsumerTargetSelector cts2 = new ConsumerTargetSelectorBuilder()
+ .setName(ctsName2)
+ .setQualityMatcher(ImmutableList.of(qm_q2q3_any))
+ .setRequirement(ImmutableList.of(r1exclude, r3))
+ .build();
+ ConsumerTargetSelector cts1_plus = new ConsumerTargetSelectorBuilder()
+ .setName(ctsName1)
+ .setQualityMatcher(ImmutableList.of(qm_q1_plus,
+ qm_q2q3_any,
+ qm_q1_plus))
+ .setRequirement(ImmutableList.of(r3))
+ .build();
+ ConsumerTargetSelector cts2_plus = new ConsumerTargetSelectorBuilder()
+ .setName(ctsName2)
+ .setQualityMatcher(ImmutableList.of(qm_q2tq2,
+ qm_q2q3_plus))
+ .setRequirement(ImmutableList.of(r3))
+ .build();
+
+ SelectorName ptsName1 = new SelectorName("pts1");
+ ProviderTargetSelector pts1 = new ProviderTargetSelectorBuilder()
+ .setName(ptsName1)
+ .setQualityMatcher(ImmutableList.of(qm_q1_all, qm_q1_any))
+ .setCapability(ImmutableList.of(c2))
+ .build();
+ SelectorName ptsName2 = new SelectorName("pts2");
+ ProviderTargetSelector pts2 = new ProviderTargetSelectorBuilder()
+ .setName(ptsName2)
+ .setQualityMatcher(ImmutableList.of(qm_q2q3_any))
+ .setCapability(ImmutableList.of(c1exclude, c3))
+ .build();
+ ProviderTargetSelector pts1_plus = new ProviderTargetSelectorBuilder()
+ .setName(ptsName1)
+ .setQualityMatcher(ImmutableList.of(qm_q1_plus,
+ qm_q2q3_any,
+ qm_q1_plus))
+ .setCapability(ImmutableList.of(c3))
+ .build();
+ ProviderTargetSelector pts2_plus = new ProviderTargetSelectorBuilder()
+ .setName(ptsName2)
+ .setQualityMatcher(ImmutableList.of(qm_q2tq2,
+ qm_q2q3_plus))
+ .setCapability(ImmutableList.of(c3))
+ .build();
+
+ EndpointGroupId egId1 =
+ new EndpointGroupId("c0e5edfb-02d2-412b-8757-a77b3daeb5d4");
+ EndpointGroup eg1 = new EndpointGroupBuilder()
+ .setId(egId1)
+ .setRequirement(ImmutableList.of(r1))
+ .setCapability(ImmutableList.of(c1))
+ .setConsumerTargetSelector(ImmutableList.of(cts1, cts2))
+ .setConsumerNamedSelector(ImmutableList.of(cns1))
+ .setProviderTargetSelector(ImmutableList.of(pts1, pts2))
+ .setProviderNamedSelector(ImmutableList.of(pns1))
+ .build();
+ EndpointGroupId egId2 =
+ new EndpointGroupId("60483327-ad76-43dd-b3bf-54ffb73ef4b8");
+ EndpointGroup eg2 = new EndpointGroupBuilder()
+ .setId(egId2)
+ .setParent(egId1)
+ .setConsumerTargetSelector(ImmutableList.of(cts1_plus, cts2_plus))
+ .setConsumerNamedSelector(ImmutableList.of(cns1_plus))
+ .setProviderTargetSelector(ImmutableList.of(pts1_plus, pts2_plus))
+ .setProviderNamedSelector(ImmutableList.of(pns1_plus))
+ .build();
+
+ EndpointGroupId egloop2Id =
+ new EndpointGroupId("cb5be574-9836-4053-8ec4-4b4a43331d65");
+ EndpointGroup egloop1 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("a33fdd4d-f58b-4741-a69f-08aecab9af2e"))
+ .setParent(egloop2Id)
+ .setConsumerNamedSelector(ImmutableList.of(cns1))
+ .setProviderNamedSelector(ImmutableList.of(pns1))
+ .setConsumerTargetSelector(ImmutableList.of(cts1))
+ .setProviderTargetSelector(ImmutableList.of(pts1))
+ .build();
+ EndpointGroup egloop2 = new EndpointGroupBuilder()
+ .setId(egloop2Id)
+ .setParent(egloop1.getId())
+ .build();
+ EndpointGroupId egselfloopid =
+ new EndpointGroupId("996ad104-f852-4d77-96cf-cddde5cebb84");
+ EndpointGroup egselfloop = new EndpointGroupBuilder()
+ .setId(egselfloopid)
+ .setParent(egselfloopid)
+ .build();
+ EndpointGroup egorphan = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("feafeac9-ce1a-4b19-8455-8fcc9a4ff013"))
+ .setParent(new EndpointGroupId("aa9dfcf1-610c-42f9-8c3a-f67b43196821"))
+ .build();
+
+ // *******
+ // Tenants
+ // *******
+
+ TenantId tenantId1 = new TenantId("0ac5d219-979c-4cca-8f90-83b69bc414ad");
+ Tenant tenant1 = new TenantBuilder()
+ .setId(tenantId1)
+ .setEndpointGroup(ImmutableList.of(eg1, eg2))
+ .setContract(ImmutableList.of(contract1, contract2))
+ .build();
+
+ Tenant malformed = new TenantBuilder()
+ .setId(new TenantId("b26e6b18-8e74-4062-a7d2-e8437132030d"))
+ .setContract(ImmutableList.of(cloop1, cloop2, cselfloop, corphan))
+ .setEndpointGroup(ImmutableList.of(egloop1, egloop2, egselfloop, egorphan))
+ .build();
+
+ InstanceIdentifier<Tenant> tenantiid1 = TenantUtils.tenantIid(tenantId1);
+ InstanceIdentifier<Tenant> tenantiid2 =
+ TenantUtils.tenantIid(malformed.getId());
+
+ // ****************
+ // Other test state
+ // ****************
+
+ DataModificationTransaction transaction;
+
+ @Before
+ public void setup() throws Exception {
+ transaction = mock(DataModificationTransaction.class);
+ when(transaction.readConfigurationData(tenantiid1))
+ .thenReturn(tenant1);
+ when(transaction.readConfigurationData(tenantiid2))
+ .thenReturn(malformed);
+ }
+
+ public boolean containsQuality(List<? extends QualityBase> qualities,
+ QualityBase quality) {
+ for (QualityBase q : qualities) {
+ if (q.getName().equals(quality.getName()))
+ return true;
+ }
+ return false;
+ }
+
+ @Test
+ public void testTargetSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ Contract c1 = TenantUtils.findContract(tenant, contractId1);
+
+ // target with a quality directly in the target and one in
+ // the containing contract
+ Target result = TenantUtils.findTarget(c1, q2TargetName);
+ assertEquals(q2TargetName, result.getName());
+ List<Quality> qualities = result.getQuality();
+ assertTrue(q1.getName() + " found in q2target",
+ containsQuality(qualities, q1));
+ assertTrue(q2.getName() + " found in q2target",
+ containsQuality(qualities, q2));
+
+ // target with a quality directly in the target with explicit "include"
+ result = TenantUtils.findTarget(c1, q1IncludeTargetName);
+ qualities = result.getQuality();
+ assertTrue(q1.getName() + " found in q1IncludeTargetName",
+ containsQuality(qualities, q1));
+
+ // target with a quality from the containing contract but overridden
+ // in the target
+ result = TenantUtils.findTarget(c1, q1ExcludeTargetName);
+ qualities = result.getQuality();
+ assertFalse(q1.getName() + " found in q1ExcludeTargetName",
+ containsQuality(qualities, q1));
+ assertTrue(q2.getName() + " found in q1ExcludeTargetName",
+ containsQuality(qualities, q2));
+ }
+
+ @Test
+ public void testTargetInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ Contract c2 = TenantUtils.findContract(tenant, contractId2);
+
+ // hits the q2PlusTarget which should include everything in q2Target
+ // plus q3
+ Target result = TenantUtils.findTarget(c2, q2TargetName);
+ List<Quality> qualities = result.getQuality();
+ assertTrue(q1.getName() + " found in q2target",
+ containsQuality(qualities, q1));
+ assertTrue(q2.getName() + " found in q2target",
+ containsQuality(qualities, q2));
+ assertTrue(q3.getName() + " found in q2target",
+ containsQuality(qualities, q3));
+
+ // Simple case of inheriting the behavior from the base but not messing
+ // it up
+ result = TenantUtils.findTarget(c2, q1IncludeTargetName);
+ qualities = result.getQuality();
+ assertTrue(q1.getName() + " found in q1IncludeTargetName",
+ containsQuality(qualities, q1));
+ assertFalse(q2.getName() + " found in q1IncludeTargetName",
+ containsQuality(qualities, q2));
+ assertFalse(q3.getName() + " found in q1IncludeTargetName",
+ containsQuality(qualities, q3));
+
+ // Inherit a target from the base that isn't found in the child at all
+ result = TenantUtils.findTarget(c2, q1ExcludeTargetName);
+ qualities = result.getQuality();
+ assertFalse(q1.getName() + " found in q1ExcludeTargetName",
+ containsQuality(qualities, q1));
+ assertTrue(q2.getName() + " found in q1ExcludeTargetName",
+ containsQuality(qualities, q2));
+ assertFalse(q3.getName() + " found in q1ExcludeTargetName",
+ containsQuality(qualities, q3));
+ }
+
+ private boolean containsRequirement(List<? extends RequirementBase> requirements,
+ RequirementBase requirement) {
+ for (RequirementBase r : requirements) {
+ if (r.getName().equals(requirement.getName()))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean containsCapability(List<? extends CapabilityBase> capabilities,
+ CapabilityBase capability) {
+ for (CapabilityBase r : capabilities) {
+ if (r.getName().equals(capability.getName()))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean containsCondition(List<? extends Condition> conditions,
+ Condition condition) {
+ for (Condition r : conditions) {
+ if (r.getName().equals(condition.getName()))
+ return true;
+ }
+ return false;
+ }
+
+ @Test
+ public void testConsumerTargetSelectorSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult1 = TenantUtils.findEndpointGroup(tenant, egId1);
+
+ // should get r1 from eg1 and r2 from target selector
+ ConsumerTargetSelector result =
+ TenantUtils.findCts(egResult1, ctsName1);
+ assertEquals(ctsName1, result.getName());
+ List<Requirement> requirements = result.getRequirement();
+ assertTrue(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertTrue(r2.getName() + " found in " + requirements,
+ containsRequirement(requirements, r2));
+
+ List<QualityMatcher> matchers = result.getQualityMatcher();
+ assertEquals(2, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q1_all"))) {
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.All, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.Any, m.getMatchType());
+ }
+ }
+
+ // should get r1 from eg1 but excluded in target selector
+ // r3 comes from target selector
+ result = TenantUtils.findCts(egResult1, ctsName2);
+ assertEquals(ctsName2, result.getName());
+ requirements = result.getRequirement();
+ assertFalse(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertFalse(r2.getName() + " found in " + requirements,
+ containsRequirement(requirements, r2));
+ assertTrue(r3.getName() + " found in " + requirements,
+ containsRequirement(requirements, r3));
+
+ matchers = result.getQualityMatcher();
+ assertEquals(1, matchers.size());
+ assertTrue(containsQuality(matchers.get(0).getMatcherQuality(), q2));
+ assertTrue(containsQuality(matchers.get(0).getMatcherQuality(), q3));
+ assertEquals(MatchType.Any, matchers.get(0).getMatchType());
+ }
+
+ @Test
+ public void testConsumerTargetSelectorInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult2 = TenantUtils.findEndpointGroup(tenant, egId2);
+
+ ConsumerTargetSelector result =
+ TenantUtils.findCts(egResult2, ctsName1);
+
+ List<Requirement> requirements = result.getRequirement();
+ assertTrue(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertTrue(r3.getName() + " found in " + requirements,
+ containsRequirement(requirements, r3));
+
+ // should have three matchers,
+ // (1) qm_q1_all inherited from endpoint group 1
+ // (2) qm_q1_any inherited from endpoint group 1, but overridden in
+ // endpoint group 2 with no new semantics
+ // (3) qm_q2q3_any defined in endpoint group 2
+ List<QualityMatcher> matchers = result.getQualityMatcher();
+ assertEquals(3, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q1_all"))) {
+ assertEquals(1, m.getMatcherQuality().size());
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.All, m.getMatchType());
+ } else if (m.getName().equals(new QualityMatcherName("qm_q1_any"))) {
+ assertEquals(1, m.getMatcherQuality().size());
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.Any, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q2));
+ assertTrue(containsQuality(m.getMatcherQuality(), q3));
+ assertEquals(MatchType.Any, m.getMatchType());
+ }
+ }
+
+ result = TenantUtils.findCts(egResult2, ctsName2);
+ assertEquals(ctsName2, result.getName());
+ requirements = result.getRequirement();
+
+ // should get r1 from eg1 but excluded in target selector
+ // r3 comes from target selector
+ assertFalse(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertFalse(r2.getName() + " found in " + requirements,
+ containsRequirement(requirements, r2));
+ assertTrue(r3.getName() + " found in " + requirements,
+ containsRequirement(requirements, r3));
+
+ // Should get 2 matchers:
+ // (1) qm_q2q2_any inherited from eg1, except that q2 is excluded
+ // by qm_q2q3_plus and q3 has a target namespace added
+ // (2) qm_q2tq2_any newly-defined with a target namespace
+ matchers = result.getQualityMatcher();
+ assertEquals(2, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q2q3_any"))) {
+ assertFalse(containsQuality(m.getMatcherQuality(), q1));
+ assertFalse(containsQuality(m.getMatcherQuality(), q2));
+ assertTrue(containsQuality(m.getMatcherQuality(), q3));
+ for (MatcherQuality mq : m.getMatcherQuality()) {
+ if (mq.getName().equals(q3.getName())) {
+ assertEquals(q2TargetName, mq.getTargetNamespace());
+ } else {
+ assertNull(mq.getTargetNamespace());
+ }
+ }
+ assertEquals(MatchType.All, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q2));
+ assertEquals(MatchType.Any, m.getMatchType());
+ assertEquals(1, m.getMatcherQuality().size());
+ assertEquals(q2TargetName,
+ m.getMatcherQuality().get(0).getTargetNamespace());
+ }
+ }
+ }
+
+ @Test
+ public void testConsumerNamedSelectorSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult1 = TenantUtils.findEndpointGroup(tenant, egId1);
+
+ // should get r1 from eg1 and r2 from selector
+ ConsumerNamedSelector result =
+ TenantUtils.findCns(egResult1, cnsName1);
+ assertEquals(cnsName1, result.getName());
+ List<Requirement> requirements = result.getRequirement();
+ assertEquals(2, requirements.size());
+ assertTrue(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertTrue(r2.getName() + " found in " + requirements,
+ containsRequirement(requirements, r2));
+
+ assertEquals(1, result.getContract().size());
+ HashSet<ContractId> cids = new HashSet<>();
+ cids.addAll(result.getContract());
+ assertEquals(ImmutableSet.of(contractId1), cids);
+ }
+
+ @Test
+ public void testConsumerNamedSelectorInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult2 = TenantUtils.findEndpointGroup(tenant, egId2);
+
+ // should get r1 from eg1 and r2 from eg1 selector,
+ // and r3 from eg2 selector
+ ConsumerNamedSelector result =
+ TenantUtils.findCns(egResult2, cnsName1);
+ assertEquals(cnsName1, result.getName());
+ List<Requirement> requirements = result.getRequirement();
+ assertEquals(3, requirements.size());
+ assertTrue(r1.getName() + " found in " + requirements,
+ containsRequirement(requirements, r1));
+ assertTrue(r2.getName() + " found in " + requirements,
+ containsRequirement(requirements, r2));
+ assertTrue(r3.getName() + " found in " + requirements,
+ containsRequirement(requirements, r3));
+
+ assertEquals(2, result.getContract().size());
+ HashSet<ContractId> cids = new HashSet<>();
+ cids.addAll(result.getContract());
+ assertEquals(ImmutableSet.of(contractId1, contractId2), cids);
+ }
+
+ @Test
+ public void testProviderTargetSelectorSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult1 = TenantUtils.findEndpointGroup(tenant, egId1);
+
+ // should get c1 from eg1 and c2 from target selector
+ ProviderTargetSelector result =
+ TenantUtils.findPts(egResult1, ptsName1);
+ assertEquals(ptsName1, result.getName());
+ List<Capability> capabilities = result.getCapability();
+ assertTrue(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertTrue(c2.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c2));
+
+ List<QualityMatcher> matchers = result.getQualityMatcher();
+ assertEquals(2, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q1_all"))) {
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.All, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.Any, m.getMatchType());
+ }
+ }
+
+ // should get c1 from eg1 but excluded in target selector
+ // c3 comes from target selector
+ result = TenantUtils.findPts(egResult1, ptsName2);
+ assertEquals(ptsName2, result.getName());
+ capabilities = result.getCapability();
+ assertFalse(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertFalse(c2.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c2));
+ assertTrue(c3.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c3));
+
+ matchers = result.getQualityMatcher();
+ assertEquals(1, matchers.size());
+ assertTrue(containsQuality(matchers.get(0).getMatcherQuality(), q2));
+ assertTrue(containsQuality(matchers.get(0).getMatcherQuality(), q3));
+ assertEquals(MatchType.Any, matchers.get(0).getMatchType());
+ }
+
+ @Test
+ public void testProviderTargetSelectorInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult2 = TenantUtils.findEndpointGroup(tenant, egId2);
+
+ ProviderTargetSelector result =
+ TenantUtils.findPts(egResult2, ptsName1);
+
+ List<Capability> capabilities = result.getCapability();
+ assertTrue(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertTrue(c3.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c3));
+
+ // should have three matchers,
+ // (1) qm_q1_all inherited from endpoint group 1
+ // (2) qm_q1_any inherited from endpoint group 1, but overridden in
+ // endpoint group 2 with no new semantics
+ // (3) qm_q2q3_any defined in endpoint group 2
+ List<QualityMatcher> matchers = result.getQualityMatcher();
+ assertEquals(3, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q1_all"))) {
+ assertEquals(1, m.getMatcherQuality().size());
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.All, m.getMatchType());
+ } else if (m.getName().equals(new QualityMatcherName("qm_q1_any"))) {
+ assertEquals(1, m.getMatcherQuality().size());
+ assertTrue(containsQuality(m.getMatcherQuality(), q1));
+ assertEquals(MatchType.Any, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q2));
+ assertTrue(containsQuality(m.getMatcherQuality(), q3));
+ assertEquals(MatchType.Any, m.getMatchType());
+ }
+ }
+
+ result = TenantUtils.findPts(egResult2, ptsName2);
+ assertEquals(ptsName2, result.getName());
+ capabilities = result.getCapability();
+
+ // should get c1 from eg1 but excluded in target selector
+ // c3 comes from target selector
+ assertFalse(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertFalse(c2.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c2));
+ assertTrue(c3.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c3));
+
+ // Should get 2 matchers:
+ // (1) qm_q2q2_any inherited from eg1, except that q2 is excluded
+ // by qm_q2q3_plus and q3 has a target namespace added
+ // (2) qm_q2tq2_any newly-defined with a target namespace
+ matchers = result.getQualityMatcher();
+ assertEquals(2, matchers.size());
+ for (QualityMatcher m : matchers) {
+ if (m.getName().equals(new QualityMatcherName("qm_q2q3_any"))) {
+ assertFalse(containsQuality(m.getMatcherQuality(), q1));
+ assertFalse(containsQuality(m.getMatcherQuality(), q2));
+ assertTrue(containsQuality(m.getMatcherQuality(), q3));
+ for (MatcherQuality mq : m.getMatcherQuality()) {
+ if (mq.getName().equals(q3.getName())) {
+ assertEquals(q2TargetName, mq.getTargetNamespace());
+ } else {
+ assertNull(mq.getTargetNamespace());
+ }
+ }
+ assertEquals(MatchType.All, m.getMatchType());
+ } else {
+ assertTrue(containsQuality(m.getMatcherQuality(), q2));
+ assertEquals(MatchType.Any, m.getMatchType());
+ assertEquals(1, m.getMatcherQuality().size());
+ assertEquals(q2TargetName,
+ m.getMatcherQuality().get(0).getTargetNamespace());
+ }
+ }
+ }
+
+ @Test
+ public void testProviderNamedSelectorSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult1 = TenantUtils.findEndpointGroup(tenant, egId1);
+
+ // should get c1 from eg1 and c2 from selector
+ ProviderNamedSelector result =
+ TenantUtils.findPns(egResult1, cnsName1);
+ assertEquals(cnsName1, result.getName());
+ List<Capability> capabilities = result.getCapability();
+ assertEquals(2, capabilities.size());
+ assertTrue(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertTrue(c2.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c2));
+
+ assertEquals(1, result.getContract().size());
+ HashSet<ContractId> cids = new HashSet<>();
+ cids.addAll(result.getContract());
+ assertEquals(ImmutableSet.of(contractId1), cids);
+ }
+
+ @Test
+ public void testProviderNamedSelectorInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ EndpointGroup egResult2 = TenantUtils.findEndpointGroup(tenant, egId2);
+
+ // should get c1 from eg1 and c2 from eg1 selector,
+ // and c3 from eg2 selector
+ ProviderNamedSelector result =
+ TenantUtils.findPns(egResult2, cnsName1);
+ assertEquals(cnsName1, result.getName());
+ List<Capability> capabilities = result.getCapability();
+ assertEquals(3, capabilities.size());
+ assertTrue(c1.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c1));
+ assertTrue(c2.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c2));
+ assertTrue(c3.getName() + " found in " + capabilities,
+ containsCapability(capabilities, c3));
+
+ assertEquals(2, result.getContract().size());
+ HashSet<ContractId> cids = new HashSet<>();
+ cids.addAll(result.getContract());
+ assertEquals(ImmutableSet.of(contractId1, contractId2), cids);
+ }
+
+ @Test
+ public void testClauseSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ Contract cresult1 = TenantUtils.findContract(tenant, contractId1);
+
+ Clause result = TenantUtils.findClause(cresult1, clauseName1);
+ assertEquals(clauseName1, result.getName());
+
+ // subject refs: subject1 from clause1
+ assertEquals(1, result.getSubjectRefs().size());
+ assertEquals(ImmutableSet.of(subject1),
+ ImmutableSet.copyOf(result.getSubjectRefs()));
+
+ assertNotNull(result.getProviderMatchers());
+ List<ConditionMatcher> cm =
+ result.getProviderMatchers().getConditionMatcher();
+ assertEquals(1, cm.size());
+ assertEquals(1, cm.get(0).getCondition().size());
+ assertTrue(containsCondition(cm.get(0).getCondition(), cond1));
+
+ List<CapabilityMatcher> capm =
+ result.getProviderMatchers().getCapabilityMatcher();
+ assertEquals(1, capm.size());
+ assertEquals(1, capm.get(0).getMatcherCapability().size());
+ assertTrue(containsCapability(capm.get(0).getMatcherCapability(), c1));
+
+ assertNotNull(result.getConsumerMatchers());
+ cm = result.getConsumerMatchers().getConditionMatcher();
+ assertEquals(1, cm.size());
+ assertEquals(1, cm.get(0).getCondition().size());
+ assertTrue(containsCondition(cm.get(0).getCondition(), cond2));
+
+ List<RequirementMatcher> pm =
+ result.getConsumerMatchers().getRequirementMatcher();
+ assertEquals(1, pm.size());
+ assertEquals(1, pm.get(0).getMatcherRequirement().size());
+ assertTrue(containsRequirement(pm.get(0).getMatcherRequirement(), r1));
+
+ }
+
+ @Test
+ public void testClauseInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+ Contract cresult2 = TenantUtils.findContract(tenant, contractId2);
+
+ Clause result = TenantUtils.findClause(cresult2, clauseName1);
+ assertEquals(clauseName1, result.getName());
+
+ // subject refs: subject1 from clause1, subject2 from clause2
+ assertEquals(2, result.getSubjectRefs().size());
+ assertEquals(ImmutableSet.of(subject1, subject2),
+ ImmutableSet.copyOf(result.getSubjectRefs()));
+
+ assertNotNull(result.getProviderMatchers());
+ List<ConditionMatcher> cm =
+ result.getProviderMatchers().getConditionMatcher();
+ assertEquals(1, cm.size());
+ assertEquals(1, cm.get(0).getCondition().size());
+ assertTrue(containsCondition(cm.get(0).getCondition(), cond1));
+
+ List<CapabilityMatcher> capm =
+ result.getProviderMatchers().getCapabilityMatcher();
+ assertEquals(1, capm.size());
+ assertEquals(1, capm.get(0).getMatcherCapability().size());
+ assertTrue(containsCapability(capm.get(0).getMatcherCapability(), c1));
+
+ assertNotNull(result.getConsumerMatchers());
+ cm = result.getConsumerMatchers().getConditionMatcher();
+ assertEquals(1, cm.size());
+ assertEquals(cm_c2.getName(), cm.get(0).getName());
+ assertEquals(MatchType.All, cm.get(0).getMatchType());
+ assertEquals(0, cm.get(0).getCondition().size());
+
+ List<RequirementMatcher> pm =
+ result.getConsumerMatchers().getRequirementMatcher();
+ assertEquals(1, pm.size());
+ assertEquals(2, pm.get(0).getMatcherRequirement().size());
+ assertTrue(containsRequirement(pm.get(0).getMatcherRequirement(), r1));
+ assertTrue(containsRequirement(pm.get(0).getMatcherRequirement(), r2));
+ }
+
+ @Test
+ public void testSubjectSimple() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+
+ Contract result = TenantUtils.findContract(tenant, contractId1);
+ List<Subject> subjects = result.getSubject();
+ assertEquals(1, subjects.size());
+
+ assertEquals(s1.getName(), subjects.get(0).getName());
+ List<Rule> rules = subjects.get(0).getRule();
+ assertEquals(2, rules.size());
+ assertEquals(rule2.getName(), rules.get(0).getName());
+ assertEquals(rule1.getName(), rules.get(1).getName());
+ }
+
+ @Test
+ public void testSubjectInheritance() throws Exception {
+ Tenant tenant = InheritanceUtils.resolveTenant(tenantId1, transaction);
+
+ Contract result = TenantUtils.findContract(tenant, contractId2);
+ List<Subject> subjects = result.getSubject();
+ assertEquals(2, subjects.size());
+ for (Subject s: subjects) {
+ if (s1.getName().equals(s.getName())) {
+ assertEquals(Integer.valueOf(4), s.getOrder());
+ List<Rule> rules = s.getRule();
+ assertEquals(4, rules.size());
+ assertEquals(rule4.getName(), rules.get(0).getName());
+ assertEquals(rule3.getName(), rules.get(1).getName());
+ assertEquals(rule2.getName(), rules.get(2).getName());
+ assertEquals(rule1.getName(), rules.get(3).getName());
+ } else if (s2.getName().equals(s.getName())) {
+ assertEquals(0, s.getRule().size());
+ assertEquals(Integer.valueOf(5), s.getOrder());
+ } else {
+ fail("extra subject?");
+ }
+ }
+ }
+
+ @Test
+ public void testMalformedPolicy() throws Exception {
+ Tenant tenant =
+ InheritanceUtils.resolveTenant(malformed.getId(), transaction);
+ Contract c = TenantUtils.findContract(tenant, cloop2Id);
+ assertEquals(1, c.getClause().size());
+ Clause clause = c.getClause().get(0);
+ assertEquals(1, clause.getConsumerMatchers().getConditionMatcher().size());
+ assertEquals(1, clause.getConsumerMatchers().getRequirementMatcher().size());
+ assertEquals(1, clause.getProviderMatchers().getConditionMatcher().size());
+ assertEquals(1, clause.getProviderMatchers().getCapabilityMatcher().size());
+ assertEquals(2, c.getSubject().size());
+
+ EndpointGroup eg = TenantUtils.findEndpointGroup(tenant, egloop2Id);
+ assertEquals(1, eg.getConsumerNamedSelector().size());
+ assertEquals(1, eg.getConsumerTargetSelector().size());
+ assertEquals(1, eg.getProviderNamedSelector().size());
+ assertEquals(1, eg.getProviderTargetSelector().size());
+
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.resolver.internal;
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityName;
+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.TargetName;
+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.capabilities.Capability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.capabilities.CapabilityBuilder;
+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.qualities.QualityBuilder;
+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.has.requirements.RequirementBuilder;
+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.target.selector.quality.matcher.MatcherQualityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.TargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirement;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelectorBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+import static org.junit.Assert.*;
+
+public class MatcherUtilsTest {
+
+ @Test
+ public void testApplyQualityMatcher() throws Exception {
+ Quality q1 = new QualityBuilder().setName(new QualityName("q1")).build();
+ Quality q2 = new QualityBuilder().setName(new QualityName("q2")).build();
+ Quality q3 = new QualityBuilder().setName(new QualityName("q3")).build();
+ Quality q4 = new QualityBuilder().setName(new QualityName("q4")).build();
+
+ Target t1 = new TargetBuilder()
+ .setName(new TargetName("t1"))
+ .setQuality(ImmutableList.of(q1, q2))
+ .build();
+ Target t2 = new TargetBuilder()
+ .setName(new TargetName("t2"))
+ .setQuality(ImmutableList.of(q3, q4))
+ .build();
+
+ MatcherQuality mq1 = new MatcherQualityBuilder(q1).build();
+ MatcherQuality mq2 = new MatcherQualityBuilder(q2).build();
+ MatcherQuality mq1_ns1 = new MatcherQualityBuilder(q1)
+ .setTargetNamespace(t1.getName())
+ .build();
+ MatcherQuality mq1_ns2 = new MatcherQualityBuilder(q1)
+ .setTargetNamespace(t2.getName())
+ .build();
+ MatcherQuality mq3 = new MatcherQualityBuilder(q3).build();
+
+ QualityMatcher qm = new QualityMatcherBuilder()
+ .setMatchType(MatchType.All)
+ .setMatcherQuality(ImmutableList.of(mq1, mq1_ns1))
+ .build();
+
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t2));
+
+ qm = new QualityMatcherBuilder()
+ .setMatcherQuality(ImmutableList.of(mq1_ns2))
+ .build();
+
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t2));
+
+ qm = new QualityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherQuality(ImmutableList.of(mq1, mq3))
+ .build();
+
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t1));
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t2));
+
+ qm = new QualityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherQuality(ImmutableList.of(mq1, mq2))
+ .build();
+
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t2));
+
+ qm = new QualityMatcherBuilder()
+ .setMatchType(MatchType.None)
+ .setMatcherQuality(ImmutableList.of(mq3, mq1_ns2))
+ .build();
+
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t2));
+
+ qm = new QualityMatcherBuilder().build();
+ assertTrue(MatcherUtils.applyQualityMatcher(qm, t1));
+
+ qm = new QualityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .build();
+ assertFalse(MatcherUtils.applyQualityMatcher(qm, t1));
+ }
+
+ @Test
+ public void testApplyCapMatcher() throws Exception {
+ Capability q1 = new CapabilityBuilder().setName(new CapabilityName("q1")).build();
+ Capability q2 = new CapabilityBuilder().setName(new CapabilityName("q2")).build();
+ Capability q3 = new CapabilityBuilder().setName(new CapabilityName("q3")).build();
+ Capability q4 = new CapabilityBuilder().setName(new CapabilityName("q4")).build();
+
+ ProviderTargetSelector t1 = new ProviderTargetSelectorBuilder()
+ .setName(new SelectorName("t1"))
+ .setCapability(ImmutableList.of(q1, q2))
+ .build();
+ ProviderNamedSelector t2 = new ProviderNamedSelectorBuilder()
+ .setName(new SelectorName("t2"))
+ .setCapability(ImmutableList.of(q3, q4))
+ .build();
+
+ MatcherCapability mq1 = new MatcherCapabilityBuilder(q1).build();
+ MatcherCapability mq2 = new MatcherCapabilityBuilder(q2).build();
+ MatcherCapability mq1_ns1 = new MatcherCapabilityBuilder(q1)
+ .setSelectorNamespace(t1.getName())
+ .build();
+ MatcherCapability mq1_ns2 = new MatcherCapabilityBuilder(q1)
+ .setSelectorNamespace(t2.getName())
+ .build();
+ MatcherCapability mq3 = new MatcherCapabilityBuilder(q3).build();
+
+ CapabilityMatcher qm = new CapabilityMatcherBuilder()
+ .setMatchType(MatchType.All)
+ .setMatcherCapability(ImmutableList.of(mq1, mq1_ns1))
+ .build();
+
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t2));
+
+ qm = new CapabilityMatcherBuilder()
+ .setMatcherCapability(ImmutableList.of(mq1_ns2))
+ .build();
+
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t2));
+
+ qm = new CapabilityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherCapability(ImmutableList.of(mq1, mq3))
+ .build();
+
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t1));
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t2));
+
+ qm = new CapabilityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherCapability(ImmutableList.of(mq1, mq2))
+ .build();
+
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t2));
+
+ qm = new CapabilityMatcherBuilder()
+ .setMatchType(MatchType.None)
+ .setMatcherCapability(ImmutableList.of(mq3, mq1_ns2))
+ .build();
+
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t2));
+
+ qm = new CapabilityMatcherBuilder().build();
+ assertTrue(MatcherUtils.applyCapMatcher(qm, t1));
+
+ qm = new CapabilityMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .build();
+ assertFalse(MatcherUtils.applyCapMatcher(qm, t1));
+ }
+
+ @Test
+ public void testApplyReqMatcher() throws Exception {
+ Requirement q1 = new RequirementBuilder().setName(new RequirementName("q1")).build();
+ Requirement q2 = new RequirementBuilder().setName(new RequirementName("q2")).build();
+ Requirement q3 = new RequirementBuilder().setName(new RequirementName("q3")).build();
+ Requirement q4 = new RequirementBuilder().setName(new RequirementName("q4")).build();
+
+ ConsumerNamedSelector t1 = new ConsumerNamedSelectorBuilder()
+ .setName(new SelectorName("t1"))
+ .setRequirement(ImmutableList.of(q1, q2))
+ .build();
+ ConsumerTargetSelector t2 = new ConsumerTargetSelectorBuilder()
+ .setName(new SelectorName("t2"))
+ .setRequirement(ImmutableList.of(q3, q4))
+ .build();
+
+ MatcherRequirement mq1 = new MatcherRequirementBuilder(q1).build();
+ MatcherRequirement mq2 = new MatcherRequirementBuilder(q2).build();
+ MatcherRequirement mq1_ns1 = new MatcherRequirementBuilder(q1)
+ .setSelectorNamespace(t1.getName())
+ .build();
+ MatcherRequirement mq1_ns2 = new MatcherRequirementBuilder(q1)
+ .setSelectorNamespace(t2.getName())
+ .build();
+ MatcherRequirement mq3 = new MatcherRequirementBuilder(q3).build();
+
+ RequirementMatcher qm = new RequirementMatcherBuilder()
+ .setMatchType(MatchType.All)
+ .setMatcherRequirement(ImmutableList.of(mq1, mq1_ns1))
+ .build();
+
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t2));
+
+ qm = new RequirementMatcherBuilder()
+ .setMatcherRequirement(ImmutableList.of(mq1_ns2))
+ .build();
+
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t2));
+
+ qm = new RequirementMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherRequirement(ImmutableList.of(mq1, mq3))
+ .build();
+
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t1));
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t2));
+
+ qm = new RequirementMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .setMatcherRequirement(ImmutableList.of(mq1, mq2))
+ .build();
+
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t2));
+
+ qm = new RequirementMatcherBuilder()
+ .setMatchType(MatchType.None)
+ .setMatcherRequirement(ImmutableList.of(mq3, mq1_ns2))
+ .build();
+
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t1));
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t2));
+
+ qm = new RequirementMatcherBuilder().build();
+ assertTrue(MatcherUtils.applyReqMatcher(qm, t1));
+
+ qm = new RequirementMatcherBuilder()
+ .setMatchType(MatchType.Any)
+ .build();
+ assertFalse(MatcherUtils.applyReqMatcher(qm, t1));
+ }
+}
--- /dev/null
+/*
+ * 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.resolver.internal;
+
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyResolver;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.ConditionSet;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.Policy;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyCache.RuleGroup;
+import org.opendaylight.groupbasedpolicy.resolver.internal.PolicyResolver.ContractMatch;
+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.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.RuleName;
+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.common.rev140421.TenantId;
+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.capabilities.Capability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.capabilities.CapabilityBuilder;
+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.conditions.ConditionBuilder;
+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.qualities.QualityBuilder;
+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.has.requirements.RequirementBuilder;
+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.MatcherQualityBuilder;
+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.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.TargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.requirement.matcher.MatcherRequirementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.capability.matcher.MatcherCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelectorBuilder;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Table;
+
+import static org.junit.Assert.*;
+
+public class PolicyResolverTest {
+ Quality q1 = new QualityBuilder()
+ .setName(new QualityName("q1"))
+ .build();
+ Quality q2 = new QualityBuilder()
+ .setName(new QualityName("q2"))
+ .build();
+ Quality q3 = new QualityBuilder()
+ .setName(new QualityName("q3"))
+ .build();
+
+ Requirement r1 = new RequirementBuilder()
+ .setName(new RequirementName("r1"))
+ .build();
+ Requirement r2 = new RequirementBuilder()
+ .setName(new RequirementName("r2"))
+ .build();
+ Requirement r3 = new RequirementBuilder()
+ .setName(new RequirementName("r3"))
+ .build();
+
+ Capability cap1 = new CapabilityBuilder()
+ .setName(new CapabilityName("cap1"))
+ .build();
+ Capability cap2 = new CapabilityBuilder()
+ .setName(new CapabilityName("cap2"))
+ .build();
+ Capability cap3 = new CapabilityBuilder()
+ .setName(new CapabilityName("cap3"))
+ .build();
+
+ Condition cond1 = new ConditionBuilder()
+ .setName(new ConditionName("cond1"))
+ .build();
+ Condition cond2 = new ConditionBuilder()
+ .setName(new ConditionName("cond2"))
+ .build();
+ Condition cond3 = new ConditionBuilder()
+ .setName(new ConditionName("cond3"))
+ .build();
+
+ Target t1 = new TargetBuilder()
+ .setName(new TargetName("t1"))
+ .setQuality(ImmutableList.of(q1,q2))
+ .build();
+ Target t2 = new TargetBuilder()
+ .setName(new TargetName("t1"))
+ .setQuality(ImmutableList.of(q3))
+ .build();
+ Target t0 = new TargetBuilder()
+ .setName(new TargetName("t1"))
+ .build();
+
+ Rule rule1 = new RuleBuilder()
+ .setName(new RuleName("r1"))
+ .setOrder(Integer.valueOf(5))
+ .build();
+ Rule rule2 = new RuleBuilder()
+ .setName(new RuleName("r2"))
+ .build();
+ Rule rule3 = new RuleBuilder()
+ .setName(new RuleName("r3"))
+ .build();
+ Subject s1 = new SubjectBuilder()
+ .setName(new SubjectName("s1"))
+ .setRule(ImmutableList.of(rule1))
+ .build();
+ Subject s2 = new SubjectBuilder()
+ .setName(new SubjectName("s1"))
+ .setRule(ImmutableList.of(rule2))
+ .setOrder(Integer.valueOf(3))
+ .build();
+ Subject s3 = new SubjectBuilder()
+ .setName(new SubjectName("3"))
+ .setRule(ImmutableList.of(rule3))
+ .setOrder(Integer.valueOf(3))
+ .build();
+
+ RequirementMatcher rm1 = new RequirementMatcherBuilder()
+ .setName(new RequirementMatcherName("rm1"))
+ .setMatcherRequirement(ImmutableList.of(new MatcherRequirementBuilder(r1).build()))
+ .build();
+ RequirementMatcher rm3 = new RequirementMatcherBuilder()
+ .setName(new RequirementMatcherName("rm1"))
+ .setMatcherRequirement(ImmutableList.of(new MatcherRequirementBuilder(r3).build()))
+ .build();
+ CapabilityMatcher capm1 = new CapabilityMatcherBuilder()
+ .setName(new CapabilityMatcherName("cap1"))
+ .setMatcherCapability(ImmutableList.of(new MatcherCapabilityBuilder(cap1).build()))
+ .build();
+ CapabilityMatcher capm3 = new CapabilityMatcherBuilder()
+ .setName(new CapabilityMatcherName("cap3"))
+ .setMatcherCapability(ImmutableList.of(new MatcherCapabilityBuilder(cap3).build()))
+ .build();
+ ConditionMatcher condm1 = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("condm1"))
+ .setCondition(ImmutableList.of(cond1))
+ .setMatchType(MatchType.All)
+ .build();
+ ConditionMatcher condm2 = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("condm2"))
+ .setCondition(ImmutableList.of(cond1, cond2))
+ .setMatchType(MatchType.Any)
+ .build();
+ ConditionMatcher condm3 = new ConditionMatcherBuilder()
+ .setName(new ConditionMatcherName("condm3"))
+ .setCondition(ImmutableList.of(cond3))
+ .setMatchType(MatchType.None)
+ .build();
+
+ Clause clause1 = new ClauseBuilder()
+ .setName(new ClauseName("clause1"))
+ .setConsumerMatchers(new ConsumerMatchersBuilder()
+ .setRequirementMatcher(ImmutableList.of(rm1))
+ .setConditionMatcher(ImmutableList.of(condm1, condm2, condm3))
+ .build())
+ .setProviderMatchers(new ProviderMatchersBuilder()
+ .setCapabilityMatcher(ImmutableList.of(capm1))
+ .build())
+ .setSubjectRefs(ImmutableList.of(s1.getName()))
+ .build();
+ Clause clause2 = new ClauseBuilder()
+ .setName(new ClauseName("clause2"))
+ .setConsumerMatchers(new ConsumerMatchersBuilder()
+ .setRequirementMatcher(ImmutableList.of(rm3))
+ .build())
+ .setProviderMatchers(new ProviderMatchersBuilder()
+ .setCapabilityMatcher(ImmutableList.of(capm3))
+ .build())
+ .setSubjectRefs(ImmutableList.of(s2.getName()))
+ .build();
+ Clause clause3 = new ClauseBuilder()
+ .setName(new ClauseName("clause3"))
+ .setSubjectRefs(ImmutableList.of(s3.getName(), s2.getName()))
+ .build();
+ Clause clause0 = new ClauseBuilder()
+ .setName(new ClauseName("clause0"))
+ .build();
+ Clause clause00 = new ClauseBuilder()
+ .setName(new ClauseName("clause00"))
+ .setConsumerMatchers(new ConsumerMatchersBuilder().build())
+ .setProviderMatchers(new ProviderMatchersBuilder().build())
+ .build();
+
+ Contract contract1 = new ContractBuilder()
+ .setId(new ContractId("c9eea992-ba51-4e11-b797-986853832ad9"))
+ .setTarget(ImmutableList.of(t1))
+ .setClause(ImmutableList.of(clause1, clause0, clause00))
+ .setSubject(ImmutableList.of(s1))
+ .build();
+ Contract contract2 = new ContractBuilder()
+ .setId(new ContractId("3a3b67ff-1795-4dc0-a7b2-2c3453872e4e"))
+ .setTarget(ImmutableList.of(t1, t2))
+ .setClause(ImmutableList.of(clause3))
+ .setSubject(ImmutableList.of(s2))
+ .build();
+ Contract contract0 = new ContractBuilder()
+ .setId(new ContractId("ce467a3c-2c7b-4e9e-a575-7da1fbdf1833"))
+ .build();
+ Contract contract00 = new ContractBuilder()
+ .setId(new ContractId("79de88e8-b37f-4764-a1a3-7f3b37b15433"))
+ .setTarget(ImmutableList.of(t0))
+ .build();
+
+ ConsumerNamedSelector cns1 = new ConsumerNamedSelectorBuilder()
+ .setName(new SelectorName("cns1"))
+ .setContract(ImmutableList.of(contract1.getId()))
+ .setRequirement(ImmutableList.of(r1, r3))
+ .build();
+ ConsumerNamedSelector cns2 = new ConsumerNamedSelectorBuilder()
+ .setName(new SelectorName("cns2"))
+ .setContract(ImmutableList.of(contract2.getId()))
+ .setRequirement(ImmutableList.of(r1, r3))
+ .build();
+ ProviderNamedSelector pns1 = new ProviderNamedSelectorBuilder()
+ .setName(new SelectorName("pns1"))
+ .setContract(ImmutableList.of(contract1.getId(), contract2.getId()))
+ .setCapability(ImmutableList.of(cap1, cap3))
+ .build();
+
+ QualityMatcher qm1 = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm1"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q1).build()))
+ .build();
+ QualityMatcher qm3 = new QualityMatcherBuilder()
+ .setName(new QualityMatcherName("qm3"))
+ .setMatcherQuality(ImmutableList.of(new MatcherQualityBuilder(q3).build()))
+ .build();
+ ConsumerTargetSelector cts1 = new ConsumerTargetSelectorBuilder()
+ .setName(new SelectorName("cts1"))
+ .setQualityMatcher(ImmutableList.of(qm1))
+ .build();
+ ProviderTargetSelector pts1 = new ProviderTargetSelectorBuilder()
+ .setName(new SelectorName("pts1"))
+ .setQualityMatcher(ImmutableList.of(qm3))
+ .build();
+
+ EndpointGroup eg1 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("12802e21-8602-40ec-91d3-a75a296881ab"))
+ .setConsumerNamedSelector(ImmutableList.of(cns1))
+ .build();
+ EndpointGroup eg2 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("66bb92ff-6e4c-41f1-8c7d-baa322016ab5"))
+ .setProviderNamedSelector(ImmutableList.of(pns1))
+ .build();
+ EndpointGroup eg3 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("0ed93cb5-28ee-46bd-a5a1-41d6aa88dae5"))
+ .setConsumerNamedSelector(ImmutableList.of(cns1, cns2))
+ .build();
+ EndpointGroup eg4 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("51eaf011-94a9-4cb1-b12d-149b77c5c016"))
+ .setConsumerTargetSelector(ImmutableList.of(cts1))
+ .build();
+ EndpointGroup eg5 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("92344738-ba37-4d69-b9e5-904eebdad585"))
+ .setProviderTargetSelector(ImmutableList.of(pts1))
+ .build();
+ EndpointGroup eg0 = new EndpointGroupBuilder()
+ .setId(new EndpointGroupId("64e03313-d6d8-43cb-ae4d-5a9b0a410c91"))
+ .build();
+
+ Tenant tenant1 = new TenantBuilder()
+ .setId(new TenantId("144b9aec-ef06-44f1-a50c-2fe5be456feb"))
+ .setContract(ImmutableList.of(contract1, contract2))
+ .setEndpointGroup(ImmutableList.of(eg1, eg2))
+ .build();
+ Tenant tenant2 = new TenantBuilder()
+ .setId(new TenantId("138a2bc3-d3cb-4588-ad7a-63c9f19ce3e5"))
+ .setContract(ImmutableList.of(contract1, contract2))
+ .setEndpointGroup(ImmutableList.of(eg1, eg2, eg3))
+ .build();
+ Tenant tenant3 = new TenantBuilder()
+ .setId(new TenantId("d1feede4-c31f-4232-ace2-93fcd065af1d"))
+ .setContract(ImmutableList.of(contract1, contract2))
+ .setEndpointGroup(ImmutableList.of(eg4, eg5))
+ .build();
+ Tenant tenant0 = new TenantBuilder().build();
+ Tenant tenant00 = new TenantBuilder()
+ .setContract(ImmutableList.of(contract0, contract00))
+ .setEndpointGroup(ImmutableList.of(eg0))
+ .build();
+
+ PolicyResolver resolver;
+
+ @Before
+ public void setup() throws Exception {
+ resolver = new PolicyResolver(null);
+ }
+
+ public void verifyMatches(List<ContractId> contrids,
+ List<TenantId> contrtids,
+ List<ContractMatch> matches) {
+ HashSet<ContractMatchKey> v = new HashSet<>();
+ for (int i = 0; i < contrids.size(); i++) {
+ v.add(new ContractMatchKey(contrtids.get(i), contrids.get(i)));
+ }
+ assertEquals(contrids.size(), matches.size());
+ for (ContractMatch m : matches) {
+ ContractMatchKey k =
+ new ContractMatchKey(m.contractTenant.getId(),
+ m.contract.getId());
+ assertTrue(v.contains(k));
+ }
+ }
+
+ @Test
+ public void testContractSelection() throws Exception {
+ // named selectors
+ Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
+ resolver.selectContracts(tenant1);
+ assertEquals(1, contractMatches.size());
+ List<ContractMatch> matches =
+ contractMatches.get(new EgKey(tenant1.getId(), eg1.getId()),
+ new EgKey(tenant1.getId(), eg2.getId()));
+ verifyMatches(ImmutableList.of(contract1.getId()),
+ ImmutableList.of(tenant1.getId()),
+ matches);
+
+ contractMatches = resolver.selectContracts(tenant2);
+ assertEquals(2, contractMatches.size());
+ matches = contractMatches.get(new EgKey(tenant2.getId(), eg1.getId()),
+ new EgKey(tenant2.getId(), eg2.getId()));
+ verifyMatches(ImmutableList.of(contract1.getId()),
+ ImmutableList.of(tenant2.getId()),
+ matches);
+
+ matches = contractMatches.get(new EgKey(tenant2.getId(), eg3.getId()),
+ new EgKey(tenant2.getId(), eg2.getId()));
+ verifyMatches(ImmutableList.of(contract2.getId(), contract1.getId()),
+ ImmutableList.of(tenant2.getId(), tenant2.getId()),
+ matches);
+
+ // target selectors
+ contractMatches = resolver.selectContracts(tenant3);
+ assertEquals(1, contractMatches.size());
+ matches = contractMatches.get(new EgKey(tenant3.getId(), eg4.getId()),
+ new EgKey(tenant3.getId(), eg5.getId()));
+ verifyMatches(ImmutableList.of(contract2.getId()),
+ ImmutableList.of(tenant3.getId()),
+ matches);
+
+ // empty matches
+ contractMatches = resolver.selectContracts(tenant0);
+ assertEquals(0, contractMatches.size());
+
+ contractMatches = resolver.selectContracts(tenant00);
+ assertEquals(0, contractMatches.size());
+ }
+
+ @Test
+ public void testSubjectSelection() throws Exception {
+ ConditionSet cs =
+ new ConditionSet(ImmutableSet.of(cond1.getName()),
+ ImmutableSet.of(cond3.getName()),
+ ImmutableSet.of(ImmutableSet.of(cond1.getName(),
+ cond2.getName())));
+
+ Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
+ resolver.selectContracts(tenant1);
+ Table<EgKey, EgKey, Policy> policy =
+ resolver.selectSubjects(contractMatches);
+ assertEquals(1, policy.size());
+ Policy p = policy.get(new EgKey(tenant1.getId(), eg1.getId()),
+ new EgKey(tenant1.getId(), eg2.getId()));
+ List<RuleGroup> rules = p.ruleMap.get(cs, ConditionSet.EMPTY);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ RuleGroup rg = rules.get(0);
+ assertEquals(tenant1.getId(), rg.contractTenant.getId());
+ assertEquals(contract1.getId(), rg.relatedContract.getId());
+ assertEquals(s1.getName(), rg.relatedSubject);
+ assertEquals(1, rg.rules.size());
+ assertEquals(rule1.getName(), rg.rules.get(0).getName());
+
+ contractMatches = resolver.selectContracts(tenant2);
+ policy = resolver.selectSubjects(contractMatches);
+
+ assertEquals(2, policy.size());
+ p = policy.get(new EgKey(tenant2.getId(), eg3.getId()),
+ new EgKey(tenant2.getId(), eg2.getId()));
+ rules = p.ruleMap.get(cs, ConditionSet.EMPTY);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ rg = rules.get(0);
+ assertEquals(tenant2.getId(), rg.contractTenant.getId());
+ assertEquals(contract1.getId(), rg.relatedContract.getId());
+ assertEquals(s1.getName(), rg.relatedSubject);
+ assertEquals(1, rg.rules.size());
+ assertEquals(rule1.getName(), rg.rules.get(0).getName());
+
+ rules = p.ruleMap.get(ConditionSet.EMPTY, ConditionSet.EMPTY);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ rg = rules.get(0);
+ assertEquals(tenant2.getId(), rg.contractTenant.getId());
+ assertEquals(contract2.getId(), rg.relatedContract.getId());
+ assertEquals(s2.getName(), rg.relatedSubject);
+ assertEquals(1, rg.rules.size());
+ assertEquals(rule2.getName(), rg.rules.get(0).getName());
+
+ p = policy.get(new EgKey(tenant2.getId(), eg1.getId()),
+ new EgKey(tenant2.getId(), eg2.getId()));
+ rules = p.ruleMap.get(cs, ConditionSet.EMPTY);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ rg = rules.get(0);
+ assertEquals(tenant2.getId(), rg.contractTenant.getId());
+ assertEquals(contract1.getId(), rg.relatedContract.getId());
+ assertEquals(s1.getName(), rg.relatedSubject);
+ assertEquals(1, rg.rules.size());
+ assertEquals(rule1.getName(), rg.rules.get(0).getName());
+
+ contractMatches = resolver.selectContracts(tenant3);
+ policy = resolver.selectSubjects(contractMatches);
+
+ assertEquals(1, policy.size());
+ p = policy.get(new EgKey(tenant3.getId(), eg4.getId()),
+ new EgKey(tenant3.getId(), eg5.getId()));
+ rules = p.ruleMap.get(ConditionSet.EMPTY, ConditionSet.EMPTY);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ rg = rules.get(0);
+ assertEquals(tenant3.getId(), rg.contractTenant.getId());
+ assertEquals(contract2.getId(), rg.relatedContract.getId());
+ assertEquals(s2.getName(), rg.relatedSubject);
+ assertEquals(1, rg.rules.size());
+ assertEquals(rule2.getName(), rg.rules.get(0).getName());
+ }
+
+ @Test
+ public void testUpdates() throws Exception {
+ // test subscriptions and update notifications
+ }
+
+ private static class ContractMatchKey {
+ TenantId tenant;
+ ContractId contract;
+ public ContractMatchKey(TenantId tenant, ContractId contract) {
+ super();
+ this.tenant = tenant;
+ this.contract = contract;
+ }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result +
+ ((contract == null) ? 0 : contract.hashCode());
+ result = prime * result +
+ ((tenant == null) ? 0 : tenant.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ContractMatchKey other = (ContractMatchKey) obj;
+ if (contract == null) {
+ if (other.contract != null)
+ return false;
+ } else if (!contract.equals(other.contract))
+ return false;
+ if (tenant == null) {
+ if (other.tenant != null)
+ return false;
+ } else if (!tenant.equals(other.tenant))
+ return false;
+ return true;
+ }
+ @Override
+ public String toString() {
+ return "ContractMatchKey [tenant=" + tenant + ", contract=" +
+ contract + "]";
+ }
+ }
+
+}