HONEYCOMB-106 - Support for generic cache management
[honeycomb.git] / vpp-common / vpp-translate-utils / src / main / java / io / fd / honeycomb / v3po / translate / v3po / util / NamingContext.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.v3po.translate.v3po.util;
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.base.Optional;
23 import io.fd.honeycomb.v3po.translate.MappingContext;
24 import io.fd.honeycomb.v3po.translate.util.RWUtils;
25 import java.util.stream.Collector;
26 import javax.annotation.Nonnull;
27 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts;
28 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContextKey;
29 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
30 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
31 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingBuilder;
32 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Utility adapter on top of {@link MappingContext} storing integer to string mappings according to naming-context yang
40  * model
41  */
42 public final class NamingContext implements AutoCloseable {
43
44     private static final Logger LOG = LoggerFactory.getLogger(NamingContext.class);
45
46     private final String artificialNamePrefix;
47     private final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContext, NamingContextKey>
48         namingContextIid;
49
50     private static final Collector<Mapping, ?, Mapping> SINGLE_ITEM_COLLECTOR = RWUtils.singleItemCollector();
51
52     /**
53      * Create new naming context
54      *
55      * @param artificialNamePrefix artificial name to be used for items without a name in VPP (or not provided)
56      * @param instanceName name of this context instance. Will be used as list item identifier within context data tree
57      */
58     public NamingContext(@Nonnull final String artificialNamePrefix, @Nonnull final String instanceName) {
59         this.artificialNamePrefix = artificialNamePrefix;
60         namingContextIid = InstanceIdentifier.create(Contexts.class).child(
61             org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContext.class,
62             new NamingContextKey(instanceName));
63     }
64
65     /**
66      * Retrieve name for mapping stored provided mappingContext instance. If not present, artificial name will be
67      * generated.
68      *
69      * @param index index of a mapped item
70      * @param mappingContext mapping context providing context data for current transaction
71      *
72      * @return name mapped to provided index
73      */
74     @Nonnull
75     public synchronized String getName(final int index, @Nonnull final MappingContext mappingContext) {
76         if (!containsName(index, mappingContext)) {
77             final String artificialName = getArtificialName(index);
78             addName(index, artificialName, mappingContext);
79         }
80
81         final Optional<Mappings> read = mappingContext.read(namingContextIid.child(Mappings.class));
82         checkState(read.isPresent(), "Mapping for index: %s is not present. But should be", index);
83
84         return read.get().getMapping().stream()
85             .filter(mapping -> mapping.getIndex().equals(index))
86             .collect(SINGLE_ITEM_COLLECTOR).getName();
87     }
88
89     /**
90      * Retrieve name for mapping stored provided mappingContext instance. if present
91      *
92      * @param index index of a mapped item
93      * @param mappingContext mapping context providing context data for current transaction
94      *
95      * @return name mapped to provided index
96      */
97     @Nonnull
98     public synchronized Optional<String> getNameIfPresent(final int index,
99                                                           @Nonnull final MappingContext mappingContext) {
100         final Optional<Mappings> read = mappingContext.read(namingContextIid.child(Mappings.class));
101
102         return read.isPresent()
103                 ? Optional.of(read.get().getMapping().stream()
104                     .filter(mapping -> mapping.getIndex().equals(index))
105                     .collect(SINGLE_ITEM_COLLECTOR)
106                     .getName())
107                 : Optional.absent();
108     }
109
110     /**
111      * Check whether mapping is present for index.
112      *
113      * @param index index of a mapped item
114      * @param mappingContext mapping context providing context data for current transaction
115      *
116      * @return true if present, false otherwise
117      */
118     public synchronized boolean containsName(final int index, @Nonnull final MappingContext mappingContext) {
119         final Optional<Mappings> read = mappingContext.read(namingContextIid.child(Mappings.class));
120         return read.isPresent()
121             ? read.get().getMapping().stream().anyMatch(mapping -> mapping.getIndex().equals(index))
122             : false;
123     }
124
125
126     /**
127      * Add mapping to current context
128      *
129      * @param index index of a mapped item
130      * @param name name of a mapped item
131      * @param mappingContext mapping context providing context data for current transaction
132      */
133     public synchronized void addName(final int index, final String name, final MappingContext mappingContext) {
134         final KeyedInstanceIdentifier<Mapping, MappingKey> mappingIid = getMappingIid(name);
135         mappingContext.put(mappingIid, new MappingBuilder().setIndex(index).setName(name).build());
136     }
137
138     private KeyedInstanceIdentifier<Mapping, MappingKey> getMappingIid(final String name) {
139         return namingContextIid.child(Mappings.class).child(Mapping.class, new MappingKey(name));
140     }
141
142     /**
143      * Remove mapping from current context
144      *
145      * @param name name of a mapped item
146      * @param mappingContext mapping context providing context data for current transaction
147      */
148     public synchronized void removeName(final String name, final MappingContext mappingContext) {
149         mappingContext.delete(getMappingIid(name));
150     }
151
152     /**
153      * Returns index value associated with the given name.
154      *
155      * @param name the name whose associated index value is to be returned
156      * @param mappingContext mapping context providing context data for current transaction
157      *
158      * @return integer index value matching supplied name
159      * @throws IllegalArgumentException if name was not found
160      */
161     public synchronized int getIndex(final String name, final MappingContext mappingContext) {
162         final Optional<Mapping> read = mappingContext.read(getMappingIid(name));
163         checkArgument(read.isPresent(), "No mapping stored for name: %s", name);
164         return read.get().getIndex();
165
166     }
167
168     /**
169      * Check whether mapping is present for name.
170      *
171      * @param name name of a mapped item
172      * @param mappingContext mapping context providing context data for current transaction
173      *
174      * @return true if present, false otherwise
175      */
176     public synchronized boolean containsIndex(final String name, final MappingContext mappingContext) {
177         return mappingContext.read(getMappingIid(name)).isPresent();
178     }
179
180     private String getArtificialName(final int index) {
181         return artificialNamePrefix + index;
182     }
183
184     @Override
185     public void close() throws Exception {
186         /// Not removing the mapping from backing storage
187     }
188 }