Java 17 Upgrade
[policy/models.git] / models-base / src / main / java / org / onap / policy / models / base / PfUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019-2021, 2023 Nordix Foundation.
4  *  Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.models.base;
23
24 import jakarta.ws.rs.core.Response;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.Collection;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.function.Function;
32 import java.util.stream.Collectors;
33 import lombok.AccessLevel;
34 import lombok.NoArgsConstructor;
35 import org.apache.commons.collections4.CollectionUtils;
36 import org.apache.commons.collections4.MapUtils;
37
38 /**
39  * Utility class for Policy Framework concept utilities.
40  *
41  * @author Liam Fallon (liam.fallon@est.tech)
42  */
43 @NoArgsConstructor(access = AccessLevel.PRIVATE)
44 public final class PfUtils {
45
46     /**
47      * Compare two objects using their equals methods, nulls are allowed.
48      *
49      * @param leftObject  the first object
50      * @param rightObject the second object
51      * @return a measure of the comparison
52      */
53     public static int compareObjects(final Object leftObject, final Object rightObject) {
54         if (leftObject == null && rightObject == null) {
55             return 0;
56         }
57
58         if (leftObject == null) {
59             return 1;
60         }
61
62         if (rightObject == null) {
63             return -1;
64         }
65
66         if (!leftObject.equals(rightObject)) {
67             return leftObject.hashCode() - rightObject.hashCode();
68         }
69
70         return 0;
71     }
72
73     /**
74      * Compare two collections of the same type, nulls are allowed.
75      *
76      * @param leftCollection  the first collection
77      * @param rightCollection the second collection
78      * @return a measure of the comparison
79      */
80     public static <T> int compareCollections(final Collection<T> leftCollection, final Collection<T> rightCollection) {
81         if (CollectionUtils.isEmpty(leftCollection) && CollectionUtils.isEmpty(rightCollection)) {
82             return 0;
83         }
84
85         return compareObjects(leftCollection, rightCollection);
86     }
87
88
89     /**
90      * Compare two maps of the same type, nulls are allowed.
91      *
92      * @param leftMap  the first map
93      * @param rightMap the second map
94      * @return a measure of the comparison
95      */
96     public static <K, V> int compareMaps(final Map<K, V> leftMap, final Map<K, V> rightMap) {
97         if (MapUtils.isEmpty(leftMap) && MapUtils.isEmpty(rightMap)) {
98             return 0;
99         }
100
101         return compareObjects(leftMap, rightMap);
102     }
103
104     /**
105      * Convenience method to apply a mapping function to all the elements of a list, generating a new list.
106      *
107      * @param source       list whose elements are to be mapped, or {@code null}
108      * @param mapFunc      mapping function
109      * @param defaultValue value to be returned if source is {@code null}
110      * @return a new list, containing mappings of all the items in the original list
111      */
112     public static <T, R> List<R> mapList(List<T> source, Function<T, R> mapFunc, List<R> defaultValue) {
113         if (source == null) {
114             return defaultValue;
115         }
116
117         return source.stream().map(mapFunc).collect(Collectors.toList());
118     }
119
120     /**
121      * Convenience method to apply a mapping function to all the elements of a list, generating a new list.
122      *
123      * @param source  list whose elements are to be mapped, or {@code null}
124      * @param mapFunc mapping function
125      * @return a new list, containing mappings of all the items in the original list, or {@code null} if the source
126      *      is {@code null}
127      */
128     public static <T, R> List<R> mapList(List<T> source, Function<T, R> mapFunc) {
129         return mapList(source, mapFunc, null);
130     }
131
132     /**
133      * Convenience method to apply a mapping function to all the values of a map, generating a new map.
134      *
135      * @param source       map whose values are to be mapped, or {@code null}
136      * @param mapFunc      mapping function
137      * @param defaultValue value to be returned if source is {@code null}
138      * @return a new map, containing mappings of all the items in the original map
139      */
140     public static <K, T, R> Map<K, R> mapMap(Map<K, T> source, Function<T, R> mapFunc, Map<K, R> defaultValue) {
141         if (source == null) {
142             return defaultValue;
143         }
144
145         Map<K, R> map = new LinkedHashMap<>();
146         for (Entry<K, T> ent : source.entrySet()) {
147             map.put(ent.getKey(), mapFunc.apply(ent.getValue()));
148         }
149
150         return map;
151     }
152
153     /**
154      * Convenience method to apply a mapping function to all the values of a map, generating a new map.
155      *
156      * @param source  map whose values are to be mapped, or {@code null}
157      * @param mapFunc mapping function
158      * @return a new map, containing mappings of all the items in the original map, or {@code null} if the source is
159      *      {@code null}
160      */
161     public static <K, T, R> Map<K, R> mapMap(Map<K, T> source, Function<T, R> mapFunc) {
162         return mapMap(source, mapFunc, null);
163     }
164
165     /**
166      * Makes a copy of an object using the copy constructor from the object's class.
167      *
168      * @param source object to be copied
169      * @return a copy of the source, or {@code null} if the source is {@code null}
170      * @throws PfModelRuntimeException if the object cannot be copied
171      */
172     public static <T> T makeCopy(T source) {
173         if (source == null) {
174             return null;
175         }
176
177         try {
178             @SuppressWarnings("unchecked") Class<? extends T> clazz = (Class<? extends T>) source.getClass();
179
180             return clazz.getConstructor(clazz).newInstance(source);
181
182         } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
183                  | RuntimeException e) {
184             throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
185                 "error copying concept key class: " + source.getClass().getName(), e);
186         }
187     }
188 }