e093c661c2d3c92cac250f86451ba4b521d30fdd
[hc2vpp.git] /
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.hc2vpp.common.translate.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.translate.MappingContext;
24 import io.fd.honeycomb.translate.util.RWUtils;
25 import java.util.Collections;
26 import java.util.OptionalInt;
27 import java.util.stream.Collectors;
28 import javax.annotation.Nonnull;
29 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.MultiMappingCtxAugmentation;
30 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.MultiNamingContexts;
31 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.MultiNaming;
32 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.MultiNamingKey;
33 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.Mappings;
34 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.mappings.Mapping;
35 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.mappings.MappingBuilder;
36 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.mappings.MappingKey;
37 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.mappings.mapping.Value;
38 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.multi.naming.context.rev160411.multi.naming.contexts.attributes.multi.naming.contexts.multi.naming.mappings.mapping.ValueBuilder;
39 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.naming.context.rev160513.Contexts;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
42
43 /**
44  * One to many context mapping
45  */
46 public class MultiNamingContext {
47
48     private final KeyedInstanceIdentifier<MultiNaming, MultiNamingKey>
49             multiNamingContextIid;
50
51     private final int startIndex;
52
53     public MultiNamingContext(@Nonnull final String instanceName, final int startIndex) {
54         multiNamingContextIid = InstanceIdentifier.create(Contexts.class)
55                 .augmentation(MultiMappingCtxAugmentation.class)
56                 .child(MultiNamingContexts.class)
57                 .child(MultiNaming.class, new MultiNamingKey(instanceName));
58         this.startIndex = startIndex;
59     }
60
61     public synchronized void addChild(@Nonnull final String parentName, final int childIndex,
62                                       @Nonnull final String childName,
63                                       @Nonnull final MappingContext mappingContext) {
64         checkArgument(childIndex >= startIndex, "Index cannot be lower than start index %s", startIndex);
65         final KeyedInstanceIdentifier<Mapping, MappingKey> mappingIid = getMappingIid(parentName);
66
67         //uses merge to preserve previous
68         mappingContext.merge(mappingIid,
69                 new MappingBuilder().setName(parentName).setValue(Collections.singletonList(new ValueBuilder()
70                         .setIndex(childIndex)
71                         .setName(childName)
72                         .build())).build());
73     }
74
75     public synchronized void addChild(@Nonnull final String parentName,
76                                       @Nonnull final String childName,
77                                       @Nonnull final MappingContext mappingContext) {
78         addChild(parentName, getNextAvailableChildIndex(parentName, mappingContext), childName, mappingContext);
79     }
80
81     public synchronized String getChildName(@Nonnull final String parentName,
82                                             @Nonnull final int childIndex,
83                                             @Nonnull final MappingContext mappingContext) {
84         final Optional<Mapping> read = mappingContext.read(getMappingIid(parentName));
85
86         checkState(read.isPresent(), "Mapping not present");
87
88         return read.get().getValue().stream()
89                 .filter(value -> value.getIndex().equals(childIndex))
90                 .collect(RWUtils.singleItemCollector()).getName();
91     }
92
93     public synchronized int getChildIndex(@Nonnull final String parentName,
94                                           @Nonnull final String childName,
95                                           @Nonnull final MappingContext mappingContext) {
96         final Optional<Mapping> read = mappingContext.read(getMappingIid(parentName));
97
98         checkState(read.isPresent(), "Mapping not present");
99
100         return read.get().getValue().stream()
101                 .filter(value -> value.getName().equals(childName))
102                 .collect(RWUtils.singleItemCollector()).getIndex();
103     }
104
105
106     public synchronized void removeChild(@Nonnull final String parentName,
107                                          @Nonnull final String childName,
108                                          @Nonnull final MappingContext mappingContext) {
109
110         final Optional<Mapping> read = mappingContext.read(getMappingIid(parentName));
111
112         // ignore delete's for non-existing parent
113         if (read.isPresent()) {
114             final Mapping mapping = read.get();
115
116             // overrides old data with new(without removed child)
117             mappingContext.put(getMappingIid(parentName), new MappingBuilder()
118                     .setName(mapping.getName())
119                     .withKey(mapping.key())
120                     .setValue(mapping.getValue()
121                             .stream()
122                             .filter(value -> !value.getName().equals(childName))
123                             .collect(Collectors.toList()))
124                     .build());
125         }
126     }
127
128     /**
129      * Returns next available index for mapping
130      */
131     private int getNextAvailableChildIndex(final String parentName, final MappingContext mappingContext) {
132         final Optional<Mappings> read = mappingContext.read(mappingIdBase());
133
134         if (!read.isPresent()) {
135             return startIndex;
136         }
137
138         final OptionalInt max = read.get().getMapping()
139             .stream()
140             .filter(mapping -> mapping.getName().equals(parentName))
141             .flatMap(mapping -> mapping.getValue().stream())
142             .mapToInt(Value::getIndex)
143             .max();
144         if (max.isPresent()) {
145             return max.getAsInt() + 1;
146         } else {
147             return startIndex;
148         }
149     }
150
151     private KeyedInstanceIdentifier<Mapping, MappingKey> getMappingIid(final String name) {
152         return mappingIdBase().child(Mapping.class, new MappingKey(name));
153     }
154
155     private InstanceIdentifier<Mappings> mappingIdBase() {
156         return multiNamingContextIid.child(Mappings.class);
157     }
158 }