2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.sf;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
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;
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;
46 public class SupportedClassifierDefinitionListener extends DataTreeChangeHandler<SupportedClassifierDefinition> {
48 private static final Logger LOG = LoggerFactory.getLogger(SupportedClassifierDefinitionListener.class);
51 final Table<RendererName, ClassifierDefinitionId, ClassifierInstanceValidator> validatorByRendererAndCd =
52 HashBasedTable.create();
53 private final PolicyValidatorRegistry validatorRegistry;
55 public SupportedClassifierDefinitionListener(DataBroker dataProvider, PolicyValidatorRegistry validatorRegistry) {
57 this.validatorRegistry = validatorRegistry;
58 if (validatorRegistry == null) {
60 "{} service was NOT found. Automatic registration of simple classifier-instance validators is NOT available for renderers.",
61 PolicyValidatorRegistry.class.getCanonicalName());
64 "{} service was found. Automatic registration of simple classifier-instance validators is available for renderers.",
65 PolicyValidatorRegistry.class.getCanonicalName());
67 registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
68 IidFactory.supportedClassifierDefinitionIidWildcard()));
72 protected void onWrite(DataObjectModification<SupportedClassifierDefinition> rootNode,
73 InstanceIdentifier<SupportedClassifierDefinition> createdSupportedCdIid) {
74 SupportedClassifierDefinition createdSupportedCd = rootNode.getDataAfter();
75 RendererName rendererName = createdSupportedCdIid.firstKeyOf(Renderer.class).getName();
76 ClassifierInstanceValidator ciValidator = new ClassifierInstanceValidator(createdSupportedCd, rendererName);
77 setParentValidators(ciValidator, false);
78 ClassifierDefinitionId cdId = createdSupportedCd.getClassifierDefinitionId();
79 validatorByRendererAndCd.put(rendererName, cdId, ciValidator);
80 if (validatorRegistry != null) {
81 validatorRegistry.register(cdId, ciValidator);
83 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
87 protected void onDelete(DataObjectModification<SupportedClassifierDefinition> rootNode,
88 InstanceIdentifier<SupportedClassifierDefinition> removedSupportedCdIid) {
89 SupportedClassifierDefinition removedSupportedCd = rootNode.getDataBefore();
90 ClassifierDefinitionId cdId = removedSupportedCd.getClassifierDefinitionId();
91 RendererName rendererName = removedSupportedCdIid.firstKeyOf(Renderer.class).getName();
92 ClassifierInstanceValidator removedCiValidator = validatorByRendererAndCd.remove(rendererName, cdId);
93 if (validatorRegistry != null) {
94 validatorRegistry.unregister(cdId, removedCiValidator);
96 setParentValidators(removedCiValidator, true);
97 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
101 protected void onSubtreeModified(DataObjectModification<SupportedClassifierDefinition> rootNode,
102 InstanceIdentifier<SupportedClassifierDefinition> modifiedSupportedCdIid) {
103 SupportedClassifierDefinition beforeSupportedCd = rootNode.getDataBefore();
104 ClassifierDefinitionId cdId = beforeSupportedCd.getClassifierDefinitionId();
105 RendererName rendererName = modifiedSupportedCdIid.firstKeyOf(Renderer.class).getName();
106 ClassifierInstanceValidator oldCiValidator = validatorByRendererAndCd.remove(rendererName, cdId);
107 if (validatorRegistry != null) {
108 validatorRegistry.unregister(cdId, oldCiValidator);
110 SupportedClassifierDefinition afterSupportedCd = rootNode.getDataAfter();
111 ClassifierInstanceValidator newCiValidator = new ClassifierInstanceValidator(afterSupportedCd, rendererName);
112 setParentValidators(newCiValidator, false);
113 validatorByRendererAndCd.put(rendererName, cdId, newCiValidator);
114 if (validatorRegistry != null) {
115 validatorRegistry.register(cdId, newCiValidator);
117 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
121 void setParentValidators(ClassifierInstanceValidator ciValidator, boolean setParentToNull) {
122 if (ciValidator.getParentClassifierDefinitionId() != null && !setParentToNull) {
123 ClassifierInstanceValidator parentCiValidator = validatorByRendererAndCd.get(ciValidator.getRendererName(),
124 ciValidator.getParentClassifierDefinitionId());
125 if (parentCiValidator != null) {
126 ciValidator.setParentValidator(parentCiValidator);
129 for (ClassifierInstanceValidator existingCiValidator : getValidatorsWithParentCdForRenderer(
130 ciValidator.getClassifierDefinitionId(), ciValidator.getRendererName())) {
131 if (setParentToNull) {
132 existingCiValidator.setParentValidator(null);
134 existingCiValidator.setParentValidator(ciValidator);
140 Collection<ClassifierInstanceValidator> getValidatorsWithParentCdForRenderer(
141 final ClassifierDefinitionId parentCdId, RendererName renderer) {
142 return Collections2.filter(validatorByRendererAndCd.row(renderer).values(),
143 new Predicate<ClassifierInstanceValidator>() {
146 public boolean apply(ClassifierInstanceValidator ciValidator) {
147 if (parentCdId.equals(ciValidator.getParentClassifierDefinitionId())) {
156 List<ParameterName> getAllSupportedParams(final ClassifierDefinitionId cdId) {
157 return FluentIterable.from(validatorByRendererAndCd.column(cdId).values())
158 .transformAndConcat(new Function<ClassifierInstanceValidator, Set<ParameterName>>() {
161 public Set<ParameterName> apply(ClassifierInstanceValidator input) {
162 return input.getSupportedParameters();
169 void putOrRemoveClassifierDefinitionInOperDs(ClassifierDefinitionId cdId, List<ParameterName> supportedParams) {
170 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
171 Optional<ClassifierDefinition> potentialCdFromConfDs = DataStoreHelper
172 .readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierDefinitionIid(cdId), rwTx);
173 if (!potentialCdFromConfDs.isPresent()) {
174 LOG.error("Classifier-definition with ID {} does not exist in CONF datastore.", cdId);
175 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId),
177 DataStoreHelper.submitToDs(rwTx);
180 ClassifierDefinition cd =
181 createClassifierDefinitionWithUnionOfParams(potentialCdFromConfDs.get(), supportedParams);
183 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId), cd);
185 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId),
188 DataStoreHelper.submitToDs(rwTx);
192 static ClassifierDefinition createClassifierDefinitionWithUnionOfParams(ClassifierDefinition cd,
193 List<ParameterName> supportedParams) {
194 if (supportedParams == null || supportedParams.isEmpty()) {
195 LOG.debug("Classifier-definition with ID {} is not supported by any renderer.", cd.getId().getValue());
198 if (cd.getParameter() == null || cd.getParameter().isEmpty()) {
199 LOG.trace("Classifier-definition with ID {} does not contain any parameter in CONF datastore.",
200 cd.getId().getValue());
203 List<Parameter> params = new ArrayList<>();
204 for (ParameterName supportedParam : supportedParams) {
205 for (Parameter param : cd.getParameter()) {
206 if (param.getName().equals(supportedParam)) {
211 ClassifierDefinitionBuilder cdBuilder = new ClassifierDefinitionBuilder(cd);
212 return cdBuilder.setParameter(params).build();