summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java
blob: e1bf501073036005a7cae060ef391ef9b2e82673 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.fd.honeycomb.translate.v3po.vppclassifier;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import io.fd.honeycomb.translate.MappingContext;
import io.fd.honeycomb.translate.read.ReaderFactory;
import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
import io.fd.honeycomb.translate.util.RWUtils;
import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
import java.util.List;
import java.util.stream.Collector;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Named;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;

/**
 * Facade on top of {@link MappingContext} that manages {@link ClassifyTableContext}.
 */
public final class VppClassifierContextManagerImpl implements VppClassifierContextManager {
    private static final Collector<ClassifyTableContext, ?, ClassifyTableContext> SINGLE_ITEM_COLLECTOR =
        RWUtils.singleItemCollector();

    @VisibleForTesting
    static final InstanceIdentifier<VppClassifierContext>
        VPP_CLASSIFIER_CONTEXT_IID = KeyedInstanceIdentifier.create(VppClassifierContext.class);
    private final String artificialNamePrefix;

    /**
     * Creates new VppClassifierContextManagerImpl.
     *
     * @param artificialNamePrefix artificial name to be used to generate names for classify tables without existing
     *                             metadata
     */
    public VppClassifierContextManagerImpl(@Nonnull final String artificialNamePrefix) {
        this.artificialNamePrefix =
            Preconditions.checkNotNull(artificialNamePrefix, "artificialNamePrefix should not be null");
    }

    private KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> getMappingIid(final String name) {
        return VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(name));
    }

    @Override
    public void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode,
                         @Nonnull final MappingContext ctx) {
        final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> mappingIid = getMappingIid(name);
        final ClassifyTableContextBuilder tableCtx = new ClassifyTableContextBuilder().setIndex(id).setName(name);
        if (classifierNode != null) {
            tableCtx.setClassifierNodeName(classifierNode.getValue());
        }
        ctx.put(mappingIid, tableCtx.build());
    }

    @Override
    public boolean containsTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
        final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
        return read.isPresent();
    }

    @Override
    public int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx) {
        final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
        checkArgument(read.isPresent(), "No mapping stored for name: %s", name);
        return read.get().getIndex();
    }

    @Override
    public String getTableName(final int id, @Nonnull final MappingContext ctx) {
        if (!containsName(id, ctx)) {
            final String artificialName = getArtificialName(id);
            addTable(id, artificialName, null, ctx);
        }

        final Optional<VppClassifierContext> read = ctx.read(VPP_CLASSIFIER_CONTEXT_IID);
        checkState(read.isPresent(), "VppClassifierContext for index: %s is not present. But should be", id);

        return read.get().getClassifyTableContext().stream()
            .filter(t -> t.getIndex().equals(id))
            .collect(SINGLE_ITEM_COLLECTOR).getName();
    }

    private boolean containsName(final int index, @Nonnull final MappingContext mappingContext) {
        final Optional<VppClassifierContext> read = mappingContext.read(VPP_CLASSIFIER_CONTEXT_IID);
        return read.isPresent()
            ? read.get().getClassifyTableContext().stream().anyMatch(t -> t.getIndex().equals(index))
            : false;
    }

    @Override
    public Optional<String> getTableBaseNode(@Nonnull final String name, @Nonnull final MappingContext ctx) {
        final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name));
        if (read.isPresent()) {
            return Optional.fromNullable(read.get().getClassifierNodeName());
        }
        return Optional.absent();
    }

    @Override
    public void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx) {
        ctx.delete(getMappingIid(name));
    }

    @Override
    public void addNodeName(@Nonnull final String tableName, final int nodeIndex,
                            @Nonnull final String nodeName,
                            @Nonnull final MappingContext ctx) {
        final KeyedInstanceIdentifier<NodeContext, NodeContextKey> iid =
            getMappingIid(tableName).child(NodeContext.class, new NodeContextKey(nodeName));
        ctx.put(iid, new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build());
    }

    @Override
    public Optional<String> getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx) {
        if (!containsName(tableIndex, ctx)) {
            return Optional.absent();
        }
        final String tableName = getTableName(tableIndex, ctx);
        final Optional<ClassifyTableContext> tableCtx = ctx.read(getMappingIid(tableName));
        final List<NodeContext> nodeContext = tableCtx.get().getNodeContext();
        if (nodeContext == null) {
            return Optional.absent();
        }
        return Optional.fromNullable(nodeContext.stream()
            .filter(n -> n.getIndex().equals(nodeIndex))
            .findFirst()
            .map(nodes -> nodes.getName())
            .orElse(null));
    }

    private String getArtificialName(final int index) {
        return artificialNamePrefix + index;
    }

    public static final class ContextsReaderFactory implements ReaderFactory {

        @Inject
        @Named("honeycomb-context")
        private DataBroker contextBindingBrokerDependency;

        @Override
        public void init(final ModifiableReaderRegistryBuilder registry) {
            registry.add(new BindingBrokerReader<>(VPP_CLASSIFIER_CONTEXT_IID,
                contextBindingBrokerDependency,
                LogicalDatastoreType.OPERATIONAL, VppClassifierContextBuilder.class));
        }
    }
}