e152fd6674e4c03152ed989bf1673d01cb7196ee
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / sf / SupportedClassifierDefinitionListener.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.groupbasedpolicy.sf;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.Set;
15
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
22 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
23 import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
24 import org.opendaylight.groupbasedpolicy.util.IidFactory;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.common.annotations.VisibleForTesting;
38 import com.google.common.base.Function;
39 import com.google.common.base.Optional;
40 import com.google.common.base.Predicate;
41 import com.google.common.collect.Collections2;
42 import com.google.common.collect.FluentIterable;
43 import com.google.common.collect.HashBasedTable;
44 import com.google.common.collect.Table;
45
46 public class SupportedClassifierDefinitionListener extends DataTreeChangeHandler<SupportedClassifierDefinition> {
47
48     private static final Logger LOG = LoggerFactory.getLogger(SupportedClassifierDefinitionListener.class);
49
50     @VisibleForTesting
51     final Table<RendererName, ClassifierDefinitionId, ClassifierInstanceValidator> validatorByRendererAndCd =
52             HashBasedTable.create();
53     private final PolicyValidatorRegistry validatorRegistry;
54
55     public SupportedClassifierDefinitionListener(DataBroker dataProvider, PolicyValidatorRegistry validatorRegistry) {
56         super(dataProvider, new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
57                 IidFactory.supportedClassifierDefinitionIidWildcard()));
58         this.validatorRegistry = validatorRegistry;
59         if (validatorRegistry == null) {
60             LOG.info(
61                     "{} service was NOT found. Automatic registration of simple classifier-instance validators is NOT available for renderers.",
62                     PolicyValidatorRegistry.class.getCanonicalName());
63         } else {
64             LOG.info(
65                     "{} service was found. Automatic registration of simple classifier-instance validators is available for renderers.",
66                     PolicyValidatorRegistry.class.getCanonicalName());
67         }
68     }
69
70     @Override
71     protected void onWrite(DataObjectModification<SupportedClassifierDefinition> rootNode,
72             InstanceIdentifier<SupportedClassifierDefinition> createdSupportedCdIid) {
73         SupportedClassifierDefinition createdSupportedCd = rootNode.getDataAfter();
74         RendererName rendererName = createdSupportedCdIid.firstKeyOf(Renderer.class).getName();
75         ClassifierInstanceValidator ciValidator = new ClassifierInstanceValidator(createdSupportedCd, rendererName);
76         setParentValidators(ciValidator, false);
77         ClassifierDefinitionId cdId = createdSupportedCd.getClassifierDefinitionId();
78         validatorByRendererAndCd.put(rendererName, cdId, ciValidator);
79         if (validatorRegistry != null) {
80             validatorRegistry.register(cdId, ciValidator);
81         }
82         putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
83     }
84
85     @Override
86     protected void onDelete(DataObjectModification<SupportedClassifierDefinition> rootNode,
87             InstanceIdentifier<SupportedClassifierDefinition> removedSupportedCdIid) {
88         SupportedClassifierDefinition removedSupportedCd = rootNode.getDataBefore();
89         ClassifierDefinitionId cdId = removedSupportedCd.getClassifierDefinitionId();
90         RendererName rendererName = removedSupportedCdIid.firstKeyOf(Renderer.class).getName();
91         ClassifierInstanceValidator removedCiValidator = validatorByRendererAndCd.remove(rendererName, cdId);
92         if (validatorRegistry != null) {
93             validatorRegistry.unregister(cdId, removedCiValidator);
94         }
95         setParentValidators(removedCiValidator, true);
96         putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
97     }
98
99     @Override
100     protected void onSubtreeModified(DataObjectModification<SupportedClassifierDefinition> rootNode,
101             InstanceIdentifier<SupportedClassifierDefinition> modifiedSupportedCdIid) {
102         SupportedClassifierDefinition beforeSupportedCd = rootNode.getDataBefore();
103         ClassifierDefinitionId cdId = beforeSupportedCd.getClassifierDefinitionId();
104         RendererName rendererName = modifiedSupportedCdIid.firstKeyOf(Renderer.class).getName();
105         ClassifierInstanceValidator oldCiValidator = validatorByRendererAndCd.remove(rendererName, cdId);
106         if (validatorRegistry != null) {
107             validatorRegistry.unregister(cdId, oldCiValidator);
108         }
109         SupportedClassifierDefinition afterSupportedCd = rootNode.getDataAfter();
110         ClassifierInstanceValidator newCiValidator = new ClassifierInstanceValidator(afterSupportedCd, rendererName);
111         setParentValidators(newCiValidator, false);
112         validatorByRendererAndCd.put(rendererName, cdId, newCiValidator);
113         if (validatorRegistry != null) {
114             validatorRegistry.register(cdId, newCiValidator);
115         }
116         putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
117     }
118
119     @VisibleForTesting
120     void setParentValidators(ClassifierInstanceValidator ciValidator, boolean setParentToNull) {
121         if (ciValidator.getParentClassifierDefinitionId() != null && !setParentToNull) {
122             ClassifierInstanceValidator parentCiValidator = validatorByRendererAndCd.get(ciValidator.getRendererName(),
123                     ciValidator.getParentClassifierDefinitionId());
124             if (parentCiValidator != null) {
125                 ciValidator.setParentValidator(parentCiValidator);
126             }
127         }
128         for (ClassifierInstanceValidator existingCiValidator : getValidatorsWithParentCdForRenderer(
129                 ciValidator.getClassifierDefinitionId(), ciValidator.getRendererName())) {
130             if (setParentToNull) {
131                 existingCiValidator.setParentValidator(null);
132             } else {
133                 existingCiValidator.setParentValidator(ciValidator);
134             }
135         }
136     }
137
138     @VisibleForTesting
139     Collection<ClassifierInstanceValidator> getValidatorsWithParentCdForRenderer(
140             final ClassifierDefinitionId parentCdId, RendererName renderer) {
141         return Collections2.filter(validatorByRendererAndCd.row(renderer).values(),
142                 new Predicate<ClassifierInstanceValidator>() {
143
144                     @Override
145                     public boolean apply(ClassifierInstanceValidator ciValidator) {
146                         if (parentCdId.equals(ciValidator.getParentClassifierDefinitionId())) {
147                             return true;
148                         }
149                         return false;
150                     }
151                 });
152     }
153
154     @VisibleForTesting
155     List<ParameterName> getAllSupportedParams(final ClassifierDefinitionId cdId) {
156         return FluentIterable.from(validatorByRendererAndCd.column(cdId).values())
157             .transformAndConcat(new Function<ClassifierInstanceValidator, Set<ParameterName>>() {
158
159                 @Override
160                 public Set<ParameterName> apply(ClassifierInstanceValidator input) {
161                     return input.getSupportedParameters();
162                 }
163             })
164             .toList();
165     }
166
167     @VisibleForTesting
168     void putOrRemoveClassifierDefinitionInOperDs(ClassifierDefinitionId cdId, List<ParameterName> supportedParams) {
169         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
170         Optional<ClassifierDefinition> potentialCdFromConfDs = DataStoreHelper
171             .readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierDefinitionIid(cdId), rwTx);
172         if (!potentialCdFromConfDs.isPresent()) {
173             LOG.error("Classifier-definition with ID {} does not exist in CONF datastore.", cdId);
174             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId),
175                     rwTx);
176             DataStoreHelper.submitToDs(rwTx);
177             return;
178         }
179         ClassifierDefinition cd =
180                 createClassifierDefinitionWithUnionOfParams(potentialCdFromConfDs.get(), supportedParams);
181         if (cd != null) {
182             rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId), cd);
183         } else {
184             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId),
185                     rwTx);
186         }
187         DataStoreHelper.submitToDs(rwTx);
188     }
189
190     @VisibleForTesting
191     static ClassifierDefinition createClassifierDefinitionWithUnionOfParams(ClassifierDefinition cd,
192             List<ParameterName> supportedParams) {
193         if (supportedParams == null || supportedParams.isEmpty()) {
194             LOG.debug("Classifier-definition with ID {} is not supported by any renderer.", cd.getId().getValue());
195             return null;
196         }
197         if (cd.getParameter() == null || cd.getParameter().isEmpty()) {
198             LOG.trace("Classifier-definition with ID {} does not contain any parameter in CONF datastore.",
199                     cd.getId().getValue());
200             return cd;
201         }
202         List<Parameter> params = new ArrayList<>();
203         for (ParameterName supportedParam : supportedParams) {
204             for (Parameter param : cd.getParameter()) {
205                 if (param.getName().equals(supportedParam)) {
206                     params.add(param);
207                 }
208             }
209         }
210         ClassifierDefinitionBuilder cdBuilder = new ClassifierDefinitionBuilder(cd);
211         return cdBuilder.setParameter(params).build();
212     }
213
214 }