Implement SFC integration
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / resolver / PolicyResolver.java
index 6371f10a30f2d5150fff309c6257ee2d87680642..94d51d5672c52e7ac0743134f98ac316fadec698 100644 (file)
@@ -8,9 +8,7 @@
 
 package org.opendaylight.groupbasedpolicy.resolver;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -31,36 +29,14 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-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.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 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.HasDirection.Direction;
-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.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.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.has.action.refs.ActionRef;
 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.GroupIdentificationConstraints;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.group.identification.constraints.GroupRequirementConstraintCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.RequirementMatcher;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.group.identification.constraints.GroupCapabilityConstraintCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.CapabilityMatcher;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.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.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.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -69,9 +45,6 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Ordering;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Table;
 import com.google.common.collect.Table.Cell;
@@ -110,6 +83,7 @@ public class PolicyResolver implements AutoCloseable {
 
     protected ConcurrentMap<TenantId, TenantContext> resolvedTenants;
 
+
     /**
      * 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
@@ -117,6 +91,13 @@ public class PolicyResolver implements AutoCloseable {
      */
     AtomicReference<PolicyInfo> policy = new AtomicReference<>();
 
+    /*
+     * Store validators for ActionDefinitions from Renderers
+     *
+     */
+
+    protected ConcurrentMap<ActionDefinitionId, ActionInstanceValidator> registeredActions = new ConcurrentHashMap<>();
+
     public PolicyResolver(DataBroker dataProvider,
             ScheduledExecutorService executor) {
         super();
@@ -167,6 +148,9 @@ public class PolicyResolver implements AutoCloseable {
         return tc.tenant.get();
     }
 
+    public void registerActionDefinitions(ActionDefinitionId actionDefinitionId, ActionInstanceValidator validator) {
+        registeredActions.putIfAbsent(actionDefinitionId, validator);
+    }
     /**
      * Register a listener to receive update events.
      *
@@ -326,19 +310,25 @@ public class PolicyResolver implements AutoCloseable {
                 }
 
                 Tenant t = InheritanceUtils.resolveTenant(result.get());
-                IndexedTenant it = new IndexedTenant(t);
-                if (!tenantRef.compareAndSet(ot, it)) {
-                    // concurrent update of tenant policy. Retry
-                    updateTenant(tenantId);
-                } else {
-                    // Update the policy cache and notify listeners
-                    WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
-                    wt.put(LogicalDatastoreType.OPERATIONAL, tiid, t, true);
-                    wt.submit();
-                    updatePolicy();
+                if (isValidTenant(t)) {
+                    IndexedTenant it = new IndexedTenant(t);
+                    if (!tenantRef.compareAndSet(ot, it)) {
+                        // concurrent update of tenant policy. Retry
+                        updateTenant(tenantId);
+                    } else {
+                        // Update the policy cache and notify listeners
+                        WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
+                        wt.put(LogicalDatastoreType.OPERATIONAL, tiid, t, true);
+                        wt.submit();
+                        updatePolicy();
+                    }
                 }
             }
 
+
+
+
+
             @Override
             public void onFailure(Throwable t) {
                 LOG.error("Count not get tenant {}", tenantId, t);
@@ -349,13 +339,9 @@ public class PolicyResolver implements AutoCloseable {
     protected void updatePolicy() {
         try {
             Map<EgKey, Set<ConditionSet>> egConditions = new HashMap<>();
-            Table<EgKey, EgKey, Policy> policyMap =
-                    resolvePolicy(resolvedTenants.values(),
-                            egConditions);
-            Set<EgKey> updatedGroups =
-                    updatePolicy(policyMap,
-                            egConditions,
-                            policyListenerScopes);
+            Set<IndexedTenant> indexedTenants = getIndexedTenants(resolvedTenants.values());
+            Table<EgKey, EgKey, Policy> policyMap = PolicyResolverUtils.resolvePolicy(indexedTenants, egConditions);
+            Set<EgKey> updatedGroups = updatePolicy(policyMap, egConditions, policyListenerScopes);
 
             notifyListeners(updatedGroups);
         } catch (Exception e) {
@@ -363,605 +349,78 @@ public class PolicyResolver implements AutoCloseable {
         }
     }
 
-    /**
-     * 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(Collection<TenantContext> tenants,
-                    Map<EgKey, Set<ConditionSet>> egConditions) {
-        // select contracts that apply for the given tenant
-        Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
-                selectContracts(tenants);
-
-        // 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, egConditions);
-    }
-
-    /**
-     * 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(Collection<TenantContext> tenants) {
-        Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches =
-                HashBasedTable.create();
-        Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
-                HashBasedTable.create();
-
-        for (TenantContext tenant : tenants) {
+    private Set<IndexedTenant> getIndexedTenants(Collection<TenantContext> tenantCtxs) {
+        Set<IndexedTenant> result = new HashSet<>();
+        for (TenantContext tenant : tenantCtxs) {
             IndexedTenant t = tenant.tenant.get();
-            if (t == null)
-                continue;
-            selectContracts(consumerMatches,
-                    contractMatches,
-                    t.getTenant());
+            if (t != null)
+                result.add(t);
         }
-        return contractMatches;
+        return result;
     }
 
-    protected void selectContracts(Table<TenantId,
-            ContractId,
-            List<ConsumerContractMatch>> consumerMatches,
-            Table<EgKey, EgKey,
-            List<ContractMatch>> contractMatches,
-            Tenant tenant) {
-        // For each endpoint group, match consumer selectors
-        // against contracts to get a set of matching consumer selectors
-        if (tenant.getEndpointGroup() == null)
-            return;
-        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.
-        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);
-            }
-        }
-    }
+    protected static class TenantContext {
+        ListenerRegistration<DataChangeListener> registration;
 
-    private boolean clauseMatches(Clause clause, ContractMatch match) {
-        if (clause.getConsumerMatchers() != null) {
-            GroupIdentificationConstraints groupIdentificationConstraintsConsumer = clause.getConsumerMatchers()
-                    .getGroupIdentificationConstraints();
-            if (groupIdentificationConstraintsConsumer instanceof GroupRequirementConstraintCase) {
-                List<RequirementMatcher> reqMatchers = ((GroupRequirementConstraintCase) groupIdentificationConstraintsConsumer)
-                        .getRequirementMatcher();
-                if (reqMatchers != null) {
-                    for (RequirementMatcher reqMatcher : reqMatchers) {
-                        if (!MatcherUtils.applyReqMatcher(reqMatcher,
-                                match.consumerRelator)) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-        if (clause.getProviderMatchers() != null) {
-            org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.GroupIdentificationConstraints groupIdentificationConstraintsProvider = clause
-                    .getProviderMatchers().getGroupIdentificationConstraints();
-            if (groupIdentificationConstraintsProvider instanceof GroupCapabilityConstraintCase) {
-                List<CapabilityMatcher> capMatchers = ((GroupCapabilityConstraintCase) groupIdentificationConstraintsProvider)
-                        .getCapabilityMatcher();
-
-                if (capMatchers != null) {
-                    for (CapabilityMatcher capMatcher : capMatchers) {
-                        if (!MatcherUtils.applyCapMatcher(capMatcher,
-                                match.providerRelator)) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-        return true;
-    }
+        AtomicReference<IndexedTenant> tenant = new AtomicReference<>();
 
-    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;
-                    }
-                }
-            }
+        public TenantContext(ListenerRegistration<DataChangeListener> registration) {
+            super();
+            this.registration = registration;
         }
-        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;
-    }
+    @Immutable
+    private class PolicyChangeListener implements DataChangeListener {
+        final TenantId tenantId;
 
-    private ConditionSet buildProvConditionSet(Clause clause) {
-        if (clause.getProviderMatchers() != null) {
-            List<ConditionMatcher> condMatchers =
-                    clause.getProviderMatchers().getConditionMatcher();
-            return buildConditionSet(condMatchers);
+        public PolicyChangeListener(TenantId tenantId) {
+            super();
+            this.tenantId = tenantId;
         }
-        return ConditionSet.EMPTY;
-    }
 
-    private Policy resolvePolicy(Tenant contractTenant,
-            Contract contract,
-            boolean reverse,
-            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<>();
-            ConditionSet rowKey = entry.getRowKey();
-            ConditionSet columnKey = entry.getColumnKey();
-            if (reverse) {
-                rowKey = columnKey;
-                columnKey = entry.getRowKey();
-            }
-            List<RuleGroup> oldrules =
-                    ruleMap.get(rowKey, columnKey);
-            if (oldrules != null) {
-                rules.addAll(oldrules);
-            }
-            for (Subject s : entry.getValue()) {
-                if (s.getRule() == null)
-                    continue;
-                List<Rule> srules;
-                if (reverse)
-                    srules = reverseRules(s.getRule());
-                else
-                    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(rowKey, columnKey,
-                    Collections.unmodifiableList(rules));
+        @Override
+        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> arg0) {
+            updateTenant(tenantId);
         }
-        return new Policy(ruleMap);
-    }
-
-    private List<Rule> reverseRules(List<Rule> rules) {
-        ArrayList<Rule> nrules = new ArrayList<>();
-        for (Rule input : rules) {
-            if (input.getClassifierRef() == null ||
-                    input.getClassifierRef().size() == 0) {
-                nrules.add(input);
-                continue;
-            }
 
-            List<ClassifierRef> classifiers = new ArrayList<>();
-            for (ClassifierRef clr : input.getClassifierRef()) {
-                Direction nd = Direction.Bidirectional;
-                if (clr.getDirection() != null) {
-                    switch (clr.getDirection()) {
-                    case In:
-                        nd = Direction.Out;
-                        break;
-                    case Out:
-                        nd = Direction.In;
-                        break;
-                    case Bidirectional:
-                    default:
-                        nd = Direction.Bidirectional;
-                    }
-                }
-                classifiers.add(new ClassifierRefBuilder(clr)
-                        .setDirection(nd).build());
-            }
-            nrules.add(new RuleBuilder(input)
-                    .setClassifierRef(Collections.unmodifiableList(classifiers))
-                    .build());
-        }
-        Collections.sort(nrules, TenantUtils.RULE_COMPARATOR);
-        return Collections.unmodifiableList(nrules);
     }
 
-    /**
-     * Get the "natural" direction for the policy for the given pair of endpoint
-     * groups.
-     *
-     * @param one
-     *            The first endpoint group
-     * @param two
-     *            The second endpoint group
-     * @return true if the order should be reversed in the index
-     */
-    protected static boolean shouldReverse(EgKey one, EgKey two) {
-        if (one.compareTo(two) < 0) {
+    private boolean isValidTenant(Tenant t) {
+        if(validActionInstances(t.getSubjectFeatureInstances().getActionInstance())) {
             return true;
         }
         return false;
     }
 
-    private void addConditionSet(EgKey eg, ConditionSet cs,
-            Map<EgKey, Set<ConditionSet>> egConditions) {
-        if (egConditions == null)
-            return;
-        Set<ConditionSet> cset = egConditions.get(eg);
-        if (cset == null) {
-            egConditions.put(eg, cset = new HashSet<>());
+    private boolean validActionInstances(List<ActionInstance> actionInstances) {
+        for(ActionInstance actionInstance : actionInstances) {
+            if(!(registeredActions.get(actionInstance.getActionDefinitionId()).isValid(actionInstance))) {
+                return false;
+            };
         }
-        cset.add(cs);
-    }
-
-    /**
-     * 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,
-                    Map<EgKey, Set<ConditionSet>> egConditions) {
-        // TODO: Note that it's possible to further simplify the resulting
-        // policy
-        // in the case of things like repeated rules, condition sets that
-        // cover other condition sets, etc. This would be a good thing to do
-        // at some point
-        Table<EgKey, EgKey, Policy> policy = HashBasedTable.create();
-
-        for (List<ContractMatch> matches : contractMatches.values()) {
-            for (ContractMatch match : matches) {
-                List<Clause> clauses = match.contract.getClause();
-                if (clauses == null)
-                    continue;
-
-                List<Subject> subjectList = match.contract.getSubject();
-                if (subjectList == null)
-                    continue;
-
-                EgKey ckey = new EgKey(match.consumerTenant.getId(),
-                        match.consumer.getId());
-                EgKey pkey = new EgKey(match.providerTenant.getId(),
-                        match.provider.getId());
-                EgKey one = ckey;
-                EgKey two = pkey;
-                boolean reverse = shouldReverse(ckey, pkey);
-                if (reverse) {
-                    one = pkey;
-                    two = ckey;
-                }
-                Policy existing = policy.get(one, two);
-
-                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);
-                        addConditionSet(ckey, consCSet, egConditions);
-                        ConditionSet provCSet = buildProvConditionSet(clause);
-                        addConditionSet(pkey, provCSet, egConditions);
-                        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(one, two,
-                        resolvePolicy(match.contractTenant,
-                                match.contract,
-                                reverse,
-                                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;
+        return true;
     }
 
-    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 boolean validContracts(List<Contract> contracts) {
+        for (Contract contract: contracts) {
+            validateSubjects(contract.getSubject());
         }
+        return false;
     }
 
-    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);
-
-                        }
-                    }
-                }
-            }
+    private void validateSubjects(List<Subject> subjects) {
+        for(Subject subject: subjects) {
+            validateRules(subject.getRule());
         }
-        return matches;
-    }
-
-    protected static class TenantContext {
-        ListenerRegistration<DataChangeListener> registration;
-
-        AtomicReference<IndexedTenant> tenant = new AtomicReference<>();
 
-        public TenantContext(ListenerRegistration<DataChangeListener> registration) {
-            super();
-            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;
-        }
-    }
+    private void validateRules(List<Rule> rules) {
 
-    @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(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> arg0) {
-            updateTenant(tenantId);
-        }
+    private void validateActionRefs(List<ActionRef> actionRefs) {
 
     }
 }