2 * Copyright (c) 2016 Cisco and/or its affiliates.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package io.fd.honeycomb.translate.util;
19 import com.google.common.base.Function;
20 import com.google.common.base.Preconditions;
21 import com.google.common.collect.Iterables;
22 import com.google.common.collect.Maps;
23 import io.fd.honeycomb.translate.SubtreeManager;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.List;
28 import java.util.stream.Collector;
29 import java.util.stream.Collectors;
30 import java.util.stream.StreamSupport;
31 import javax.annotation.Nonnull;
32 import org.opendaylight.yangtools.yang.binding.Augmentation;
33 import org.opendaylight.yangtools.yang.binding.DataObject;
34 import org.opendaylight.yangtools.yang.binding.Identifiable;
35 import org.opendaylight.yangtools.yang.binding.Identifier;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 public final class RWUtils {
40 // TODO(HONEYCOMB-172): update the utils methods considering Java8.
41 // Make sure they still work by wiring a detailed unit test first
43 public static final Function<SubtreeManager<? extends DataObject>, Class<? extends DataObject>>
44 MANAGER_CLASS_FUNCTION = input -> input.getManagedDataObjectType().getTargetType();
46 public static final Function<SubtreeManager<? extends Augmentation<?>>, Class<? extends DataObject>>
47 MANAGER_CLASS_AUG_FUNCTION = input -> {
48 final Class<? extends Augmentation<?>> targetType = input.getManagedDataObjectType().getTargetType();
49 Preconditions.checkArgument(DataObject.class.isAssignableFrom(targetType));
50 return (Class<? extends DataObject>) targetType;
56 * Collector expecting only a single resulting item from a stream.
58 public static<T> Collector<T,?,T> singleItemCollector() {
59 return Collectors.collectingAndThen(
62 if (list.size() != 1) {
63 throw new IllegalStateException("Unexpected size of list: " + list + ". Single item expected");
71 * Find next item in ID after provided type.
74 public static InstanceIdentifier.PathArgument getNextId(@Nonnull final InstanceIdentifier<? extends DataObject> id,
75 @Nonnull final InstanceIdentifier<? extends DataObject> type) {
76 final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
77 final int i = Iterables.indexOf(pathArguments, input -> input.getType().isAssignableFrom(type.getTargetType()));
78 Preconditions.checkArgument(i >= 0, "Unable to find %s type in %s", type.getTargetType(), id);
79 return Iterables.get(pathArguments, i + 1);
83 * Replace last item in ID with a provided IdentifiableItem of the same type.
85 @SuppressWarnings("unchecked")
87 public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier<D> replaceLastInId(
88 @Nonnull final InstanceIdentifier<D> id, final InstanceIdentifier.IdentifiableItem<D, K> currentBdItem) {
90 final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
91 final Iterable<InstanceIdentifier.PathArgument> withoutCurrent =
92 Iterables.limit(pathArguments, Iterables.size(pathArguments) - 1);
93 final Iterable<InstanceIdentifier.PathArgument> concat =
94 Iterables.concat(withoutCurrent, Collections.singleton(currentBdItem));
95 return (InstanceIdentifier<D>) InstanceIdentifier.create(concat);
99 * Create IdentifiableItem from target type of provided ID with provided key.
102 public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier.IdentifiableItem<D, K> getCurrentIdItem(
103 @Nonnull final InstanceIdentifier<D> id, final K key) {
104 return InstanceIdentifier.IdentifiableItem.of(id.getTargetType(), key);
108 * Trim InstanceIdentifier at indexOf(type).
110 @SuppressWarnings("unchecked")
112 public static <D extends DataObject> InstanceIdentifier<D> cutId(@Nonnull final InstanceIdentifier<? extends DataObject> id,
113 @Nonnull final InstanceIdentifier<D> type) {
114 final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
115 final int i = Iterables.indexOf(pathArguments, input -> input.getType().equals(type.getTargetType()));
116 Preconditions.checkArgument(i >= 0, "ID %s does not contain %s", id, type);
117 return (InstanceIdentifier<D>) InstanceIdentifier.create(Iterables.limit(pathArguments, i + 1));
121 * Trim InstanceIdentifier at indexOf(type).
124 public static <D extends DataObject> InstanceIdentifier<D> cutId(@Nonnull final InstanceIdentifier<? extends DataObject> id,
125 @Nonnull final Class<D> type) {
126 return cutId(id, InstanceIdentifier.create(type));
130 * Create an ordered map from a collection, checking for duplicity in the process.
133 public static <K, V> Map<K, V> uniqueLinkedIndex(@Nonnull final Collection<V> values, @Nonnull final Function<? super V, K> keyFunction) {
134 final Map<K, V> objectObjectLinkedHashMap = Maps.newLinkedHashMap();
135 for (V value : values) {
136 final K key = keyFunction.apply(value);
137 Preconditions.checkArgument(objectObjectLinkedHashMap.put(key, value) == null,
138 "Duplicate key detected : %s", key);
140 return objectObjectLinkedHashMap;
144 * Transform a keyed instance identifier into a wildcarded one.
146 * ! This has to be called also for wildcarded List instance identifiers
147 * due to weird behavior of equals in InstanceIdentifier !
149 @SuppressWarnings("unchecked")
150 public static <D extends DataObject> InstanceIdentifier<D> makeIidWildcarded(final InstanceIdentifier<D> id) {
151 final List<InstanceIdentifier.PathArgument> transformedPathArguments =
152 StreamSupport.stream(id.getPathArguments().spliterator(), false)
153 .map(RWUtils::cleanPathArgumentFromKeys)
154 .collect(Collectors.toList());
155 return (InstanceIdentifier<D>) InstanceIdentifier.create(transformedPathArguments);
159 * Transform a keyed instance identifier into a wildcarded one, keeping keys except the last item.
161 @SuppressWarnings("unchecked")
162 public static <D extends DataObject> InstanceIdentifier<D> makeIidLastWildcarded(final InstanceIdentifier<D> id) {
163 final InstanceIdentifier.Item<D> wildcardedItem = InstanceIdentifier.Item.of(id.getTargetType());
164 final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
165 return (InstanceIdentifier<D>) InstanceIdentifier.create(
167 Iterables.limit(pathArguments, Iterables.size(pathArguments) - 1),
168 Collections.singleton(wildcardedItem)));
171 private static InstanceIdentifier.PathArgument cleanPathArgumentFromKeys(final InstanceIdentifier.PathArgument pathArgument) {
172 return pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>
173 ? InstanceIdentifier.Item.of(pathArgument.getType())