HONEYCOMB-118: extend classifer model to support node names.
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / vppclassifier / VppClassifierContextManagerImpl.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.translate.v3po.vppclassifier;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkState;
21
22 import com.google.common.annotations.VisibleForTesting;
23 import com.google.common.base.Optional;
24 import com.google.common.base.Preconditions;
25 import com.google.inject.Inject;
26 import io.fd.honeycomb.translate.MappingContext;
27 import io.fd.honeycomb.translate.read.ReaderFactory;
28 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
29 import io.fd.honeycomb.translate.util.RWUtils;
30 import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
31 import java.util.stream.Collector;
32 import javax.annotation.Nonnull;
33 import javax.annotation.Nullable;
34 import javax.inject.Named;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
48
49 /**
50  * Facade on top of {@link MappingContext} that manages {@link ClassifyTableContext}.
51  */
52 public final class VppClassifierContextManagerImpl implements VppClassifierContextManager {
53     private static final Collector<ClassifyTableContext, ?, ClassifyTableContext> SINGLE_ITEM_COLLECTOR =
54         RWUtils.singleItemCollector();
55
56     @VisibleForTesting
57     static final InstanceIdentifier<VppClassifierContext>
58         VPP_CLASSIFIER_CONTEXT_IID = KeyedInstanceIdentifier.create(VppClassifierContext.class);
59     private final String artificialNamePrefix;
60
61     /**
62      * Creates new VppClassifierContextManagerImpl.
63      *
64      * @param artificialNamePrefix artificial name to be used to generate names for classify tables without existing
65      *                             metadata
66      */
67     public VppClassifierContextManagerImpl(@Nonnull final String artificialNamePrefix) {
68         this.artificialNamePrefix =
69             Preconditions.checkNotNull(artificialNamePrefix, "artificialNamePrefix should not be null");
70     }
71
72     private KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> getMappingIid(final String name) {
73         return VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(name));
74     }
75
76     @Override
77     public void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode,
78                          @Nonnull final MappingContext ctx) {
79         final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> mappingIid = getMappingIid(name);
80         final ClassifyTableContextBuilder tableCtx = new ClassifyTableContextBuilder().setIndex(id).setName(name);
81         if (classifierNode != null) {
82             tableCtx.setClassifierNodeName(classifierNode.getValue());
83         }
84         ctx.put(mappingIid, tableCtx.build());
85     }
86
87     @Override
88     public boolean containsTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
89         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
90         return read.isPresent();
91     }
92
93     @Override
94     public int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx) {
95         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
96         checkArgument(read.isPresent(), "No mapping stored for name: %s", name);
97         return read.get().getIndex();
98     }
99
100     @Override
101     public String getTableName(final int id, @Nonnull final MappingContext ctx) {
102         if (!containsName(id, ctx)) {
103             final String artificialName = getArtificialName(id);
104             addTable(id, artificialName, null, ctx);
105         }
106
107         final Optional<VppClassifierContext> read = ctx.read(VPP_CLASSIFIER_CONTEXT_IID);
108         checkState(read.isPresent(), "VppClassifierContext for index: %s is not present. But should be", id);
109
110         return read.get().getClassifyTableContext().stream()
111             .filter(t -> t.getIndex().equals(id))
112             .collect(SINGLE_ITEM_COLLECTOR).getName();
113     }
114
115     private boolean containsName(final int index, @Nonnull final MappingContext mappingContext) {
116         final Optional<VppClassifierContext> read = mappingContext.read(VPP_CLASSIFIER_CONTEXT_IID);
117         return read.isPresent()
118             ? read.get().getClassifyTableContext().stream().anyMatch(t -> t.getIndex().equals(index))
119             : false;
120     }
121
122     @Override
123     public Optional<String> getTableBaseNode(@Nonnull final String name, @Nonnull final MappingContext ctx) {
124         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
125         if (read.isPresent()) {
126             return Optional.fromNullable(read.get().getClassifierNodeName());
127         }
128         return Optional.absent();
129     }
130
131     @Override
132     public void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
133         ctx.delete(getMappingIid(name));
134     }
135
136     @Override
137     public void addNodeName(@Nonnull final String tableName, final int nodeIndex,
138                             @Nonnull final String nodeName,
139                             @Nonnull final MappingContext ctx) {
140         final KeyedInstanceIdentifier<NodeContext, NodeContextKey> iid =
141             getMappingIid(tableName).child(NodeContext.class, new NodeContextKey(nodeName));
142         ctx.put(iid, new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build());
143     }
144
145     @Override
146     public Optional<String> getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx) {
147         if (!containsName(tableIndex, ctx)) {
148             return Optional.absent();
149         }
150         final String tableName = getTableName(tableIndex, ctx);
151         final Optional<ClassifyTableContext> tableCtx = ctx.read(getMappingIid(tableName));
152         return Optional.fromNullable(tableCtx.get().getNodeContext().stream()
153             .filter(n -> n.getIndex().equals(nodeIndex))
154             .findFirst()
155             .map(nodes -> nodes.getName())
156             .orElse(null));
157     }
158
159     private String getArtificialName(final int index) {
160         return artificialNamePrefix + index;
161     }
162
163     public static final class ContextsReaderFactory implements ReaderFactory {
164
165         @Inject
166         @Named("honeycomb-context")
167         private DataBroker contextBindingBrokerDependency;
168
169         @Override
170         public void init(final ModifiableReaderRegistryBuilder registry) {
171             registry.add(new BindingBrokerReader<>(VPP_CLASSIFIER_CONTEXT_IID,
172                 contextBindingBrokerDependency,
173                 LogicalDatastoreType.OPERATIONAL, VppClassifierContextBuilder.class));
174         }
175     }
176 }