13931ae479399034eae3b08e086e91fefd711346
[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.List;
32 import java.util.stream.Collector;
33 import javax.annotation.Nonnull;
34 import javax.annotation.Nullable;
35 import javax.inject.Named;
36 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
37 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNodeName;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
49
50 /**
51  * Facade on top of {@link MappingContext} that manages {@link ClassifyTableContext}.
52  */
53 public final class VppClassifierContextManagerImpl implements VppClassifierContextManager {
54     private static final Collector<ClassifyTableContext, ?, ClassifyTableContext> SINGLE_ITEM_COLLECTOR =
55         RWUtils.singleItemCollector();
56
57     @VisibleForTesting
58     static final InstanceIdentifier<VppClassifierContext>
59         VPP_CLASSIFIER_CONTEXT_IID = KeyedInstanceIdentifier.create(VppClassifierContext.class);
60     private final String artificialNamePrefix;
61
62     /**
63      * Creates new VppClassifierContextManagerImpl.
64      *
65      * @param artificialNamePrefix artificial name to be used to generate names for classify tables without existing
66      *                             metadata
67      */
68     public VppClassifierContextManagerImpl(@Nonnull final String artificialNamePrefix) {
69         this.artificialNamePrefix =
70             Preconditions.checkNotNull(artificialNamePrefix, "artificialNamePrefix should not be null");
71     }
72
73     private KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> getMappingIid(final String name) {
74         return VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(name));
75     }
76
77     @Override
78     public void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode,
79                          @Nonnull final MappingContext ctx) {
80         final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> mappingIid = getMappingIid(name);
81         final ClassifyTableContextBuilder tableCtx = new ClassifyTableContextBuilder().setIndex(id).setName(name);
82         if (classifierNode != null) {
83             tableCtx.setClassifierNodeName(classifierNode.getValue());
84         }
85         ctx.put(mappingIid, tableCtx.build());
86     }
87
88     @Override
89     public boolean containsTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
90         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
91         return read.isPresent();
92     }
93
94     @Override
95     public int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx) {
96         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
97         checkArgument(read.isPresent(), "No mapping stored for name: %s", name);
98         return read.get().getIndex();
99     }
100
101     @Override
102     public String getTableName(final int id, @Nonnull final MappingContext ctx) {
103         if (!containsName(id, ctx)) {
104             final String artificialName = getArtificialName(id);
105             addTable(id, artificialName, null, ctx);
106         }
107
108         final Optional<VppClassifierContext> read = ctx.read(VPP_CLASSIFIER_CONTEXT_IID);
109         checkState(read.isPresent(), "VppClassifierContext for index: %s is not present. But should be", id);
110
111         return read.get().getClassifyTableContext().stream()
112             .filter(t -> t.getIndex().equals(id))
113             .collect(SINGLE_ITEM_COLLECTOR).getName();
114     }
115
116     private boolean containsName(final int index, @Nonnull final MappingContext mappingContext) {
117         final Optional<VppClassifierContext> read = mappingContext.read(VPP_CLASSIFIER_CONTEXT_IID);
118         return read.isPresent()
119             ? read.get().getClassifyTableContext().stream().anyMatch(t -> t.getIndex().equals(index))
120             : false;
121     }
122
123     @Override
124     public Optional<String> getTableBaseNode(@Nonnull final String name, @Nonnull final MappingContext ctx) {
125         final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
126         if (read.isPresent()) {
127             return Optional.fromNullable(read.get().getClassifierNodeName());
128         }
129         return Optional.absent();
130     }
131
132     @Override
133     public void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
134         ctx.delete(getMappingIid(name));
135     }
136
137     @Override
138     public void addNodeName(@Nonnull final String tableName, final int nodeIndex,
139                             @Nonnull final String nodeName,
140                             @Nonnull final MappingContext ctx) {
141         final KeyedInstanceIdentifier<NodeContext, NodeContextKey> iid =
142             getMappingIid(tableName).child(NodeContext.class, new NodeContextKey(nodeName));
143         ctx.put(iid, new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build());
144     }
145
146     @Override
147     public Optional<String> getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx) {
148         if (!containsName(tableIndex, ctx)) {
149             return Optional.absent();
150         }
151         final String tableName = getTableName(tableIndex, ctx);
152         final Optional<ClassifyTableContext> tableCtx = ctx.read(getMappingIid(tableName));
153         final List<NodeContext> nodeContext = tableCtx.get().getNodeContext();
154         if (nodeContext == null) {
155             return Optional.absent();
156         }
157         return Optional.fromNullable(nodeContext.stream()
158             .filter(n -> n.getIndex().equals(nodeIndex))
159             .findFirst()
160             .map(nodes -> nodes.getName())
161             .orElse(null));
162     }
163
164     private String getArtificialName(final int index) {
165         return artificialNamePrefix + index;
166     }
167
168     public static final class ContextsReaderFactory implements ReaderFactory {
169
170         @Inject
171         @Named("honeycomb-context")
172         private DataBroker contextBindingBrokerDependency;
173
174         @Override
175         public void init(final ModifiableReaderRegistryBuilder registry) {
176             registry.add(new BindingBrokerReader<>(VPP_CLASSIFIER_CONTEXT_IID,
177                 contextBindingBrokerDependency,
178                 LogicalDatastoreType.OPERATIONAL, VppClassifierContextBuilder.class));
179         }
180     }
181 }