Simplifying validators
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / resolver / PolicyResolver.java
index 723645fc2eb2fe6c21221defb280d2050711dddf..0123fba6e3fad7cc82642aeda315617eaf2fec49 100755 (executable)
@@ -24,17 +24,22 @@ import javax.annotation.concurrent.Immutable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 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.groupbasedpolicy.resolver.validator.ValidationResult;
+import org.opendaylight.groupbasedpolicy.resolver.validator.Validator;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 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.resolved.policy.rev150828.ResolvedPolicies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPoliciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -43,6 +48,9 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Table;
 import com.google.common.collect.Table.Cell;
@@ -50,8 +58,6 @@ import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
-import org.opendaylight.groupbasedpolicy.resolver.validator.PolicyValidator;
-import org.opendaylight.groupbasedpolicy.resolver.validator.ValidationResult;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 
 /**
@@ -97,7 +103,8 @@ public class PolicyResolver implements AutoCloseable {
      * Store validators for ActionDefinitions from Renderers
      *
      */
-    protected ConcurrentMap<ActionDefinitionId, ActionInstanceValidator> registeredActions = new ConcurrentHashMap<>();
+    protected SetMultimap<ActionDefinitionId, Validator<ActionInstance>> actionInstanceValidatorsByDefinition = Multimaps.synchronizedSetMultimap(HashMultimap.<ActionDefinitionId, Validator<ActionInstance>>create());
+    protected SetMultimap<ClassifierDefinitionId, Validator<ClassifierInstance>> classifierInstanceValidatorsByDefinition = Multimaps.synchronizedSetMultimap(HashMultimap.<ClassifierDefinitionId, Validator<ClassifierInstance>>create());
 
     public PolicyResolver(DataBroker dataProvider,
             ScheduledExecutorService executor) {
@@ -148,8 +155,24 @@ public class PolicyResolver implements AutoCloseable {
         return tc.tenant.get();
     }
 
-    public void registerActionDefinitions(ActionDefinitionId actionDefinitionId, ActionInstanceValidator validator) {
-        registeredActions.putIfAbsent(actionDefinitionId, validator);
+    public void registerActionInstanceValidators(ActionDefinitionId actionDefinitionId,
+            Validator<ActionInstance> validator) {
+        actionInstanceValidatorsByDefinition.put(actionDefinitionId, validator);
+    }
+
+    public void unregisterActionInstanceValidators(ActionDefinitionId actionDefinitionId,
+            Validator<ActionInstance> validator) {
+        actionInstanceValidatorsByDefinition.remove(actionDefinitionId, validator);
+    }
+
+    public void registerClassifierInstanceValidators(ClassifierDefinitionId classifierDefinitionId,
+            Validator<ClassifierInstance> validator) {
+        classifierInstanceValidatorsByDefinition.put(classifierDefinitionId, validator);
+    }
+
+    public void unregisterClassifierInstanceValidators(ClassifierDefinitionId classifierDefinitionId,
+            Validator<ClassifierInstance> validator) {
+        classifierInstanceValidatorsByDefinition.remove(classifierDefinitionId, validator);
     }
 
     /**
@@ -310,7 +333,11 @@ public class PolicyResolver implements AutoCloseable {
                 }
 
                 Tenant t = InheritanceUtils.resolveTenant(result.get());
-                if (isValidTenant(t)) {
+                SubjectFeatureInstances subjectFeatureInstances = t.getSubjectFeatureInstances();
+                if (subjectFeatureInstances != null) {
+                    // TODO log and remove invalid action instances
+                    if (actionInstancesAreValid(subjectFeatureInstances.getActionInstance())
+                            && classifierInstancesAreValid(subjectFeatureInstances.getClassifierInstance())) {
                     IndexedTenant it = new IndexedTenant(t);
                     if (!tenantRef.compareAndSet(ot, it)) {
                         // concurrent update of tenant policy. Retry
@@ -324,6 +351,7 @@ public class PolicyResolver implements AutoCloseable {
                     }
                 }
             }
+        }
 
             @Override
             public void onFailure(Throwable t) {
@@ -399,6 +427,56 @@ public class PolicyResolver implements AutoCloseable {
         return result;
     }
 
+    /**
+     * Validation of action instances.
+     *
+     * @param actionInstances list of instances to validate
+     * @return true if instances are valid or if <code>actionInstances</code>
+     * is <code>null</code>, Otherwise returns false.
+     *
+     */
+    private boolean actionInstancesAreValid(List<ActionInstance> actionInstances) {
+        if (actionInstances == null) {
+            return true;
+        }
+        for (ActionInstance actionInstance : actionInstances) {
+            Set<Validator<ActionInstance>> actionInstanceValidators = actionInstanceValidatorsByDefinition.get(actionInstance.getActionDefinitionId());
+            for (Validator<ActionInstance> actionInstanceValidator : actionInstanceValidators) {
+                ValidationResult validationResult = actionInstanceValidator.validate(actionInstance);
+                if (!validationResult.isValid()) {
+                    LOG.error("ActionInstance {} is not valid!", actionInstance.getName());
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Validation of classifier instances.
+     *
+     * @param classifierInstances list of instances to validate
+     * @return true if instances are valid or if <code>classifierInstances</code>
+     * is <code>null</code>, Otherwise returns false.
+     *
+     */
+    private boolean classifierInstancesAreValid(List<ClassifierInstance> classifierInstances) {
+        if (classifierInstances == null) {
+            return true;
+        }
+        for (ClassifierInstance classifierInstance : classifierInstances) {
+            Set<Validator<ClassifierInstance>> classifierInstanceValidators = classifierInstanceValidatorsByDefinition.get(classifierInstance.getClassifierDefinitionId());
+            for (Validator<ClassifierInstance> classifierInstanceValidator : classifierInstanceValidators) {
+                ValidationResult validationResult = classifierInstanceValidator.validate(classifierInstance);
+                if (!validationResult.isValid()) {
+                    LOG.error("ClassifierInstance {} is not valid!", classifierInstance.getName());
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     protected static class TenantContext {
 
         ListenerRegistration<DataChangeListener> registration;
@@ -428,20 +506,4 @@ public class PolicyResolver implements AutoCloseable {
 
     }
 
-    private boolean isValidTenant(Tenant t) {
-        ValidationResult validationResult = PolicyValidator.validate(t, this);
-        if (validationResult == null) {
-            return true;
-        }
-        return validationResult.getResult().getValue();
-    }
-
-    public ActionInstanceValidator getActionInstanceValidator(ActionDefinitionId actionDefinitionId) {
-        if (registeredActions == null) {
-            return null;
-        }
-        return registeredActions.get(actionDefinitionId);
-
-    }
-
 }