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) {
56 super(dataProvider, new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
57 IidFactory.supportedClassifierDefinitionIidWildcard()));
58 this.validatorRegistry = validatorRegistry;
59 if (validatorRegistry == null) {
61 "{} service was NOT found. Automatic registration of simple classifier-instance validators is NOT available for renderers.",
62 PolicyValidatorRegistry.class.getCanonicalName());
65 "{} service was found. Automatic registration of simple classifier-instance validators is available for renderers.",
66 PolicyValidatorRegistry.class.getCanonicalName());
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);
82 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
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);
95 setParentValidators(removedCiValidator, true);
96 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
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);
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);
116 putOrRemoveClassifierDefinitionInOperDs(cdId, getAllSupportedParams(cdId));
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);
128 for (ClassifierInstanceValidator existingCiValidator : getValidatorsWithParentCdForRenderer(
129 ciValidator.getClassifierDefinitionId(), ciValidator.getRendererName())) {
130 if (setParentToNull) {
131 existingCiValidator.setParentValidator(null);
133 existingCiValidator.setParentValidator(ciValidator);
139 Collection<ClassifierInstanceValidator> getValidatorsWithParentCdForRenderer(
140 final ClassifierDefinitionId parentCdId, RendererName renderer) {
141 return Collections2.filter(validatorByRendererAndCd.row(renderer).values(),
142 new Predicate<ClassifierInstanceValidator>() {
145 public boolean apply(ClassifierInstanceValidator ciValidator) {
146 if (parentCdId.equals(ciValidator.getParentClassifierDefinitionId())) {
155 List<ParameterName> getAllSupportedParams(final ClassifierDefinitionId cdId) {
156 return FluentIterable.from(validatorByRendererAndCd.column(cdId).values())
157 .transformAndConcat(new Function<ClassifierInstanceValidator, Set<ParameterName>>() {
160 public Set<ParameterName> apply(ClassifierInstanceValidator input) {
161 return input.getSupportedParameters();
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),
176 DataStoreHelper.submitToDs(rwTx);
179 ClassifierDefinition cd =
180 createClassifierDefinitionWithUnionOfParams(potentialCdFromConfDs.get(), supportedParams);
182 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId), cd);
184 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(cdId),
187 DataStoreHelper.submitToDs(rwTx);
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());
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());
202 List<Parameter> params = new ArrayList<>();
203 for (ParameterName supportedParam : supportedParams) {
204 for (Parameter param : cd.getParameter()) {
205 if (param.getName().equals(supportedParam)) {
210 ClassifierDefinitionBuilder cdBuilder = new ClassifierDefinitionBuilder(cd);
211 return cdBuilder.setParameter(params).build();