e108549263642507141d10ee142988a76bbd0228
[policy/apex-pdp.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 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.apex.model.utilities.comparison;
23
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.TreeMap;
28 import lombok.Getter;
29
30 /**
31  * This class holds the result of a difference check between two keyed maps. Four results are returned in the class. The
32  * {@code leftOnly} result is the entries that appear only in the left map. the {@code rightOnly} result is the entries
33  * that appear only in the right map. The {@code differentValues} result are the entries that have the same key but
34  * different values in the maps being compared. The {@code identicalValues} result are the entries with identical keys
35  * and values in both maps being compared.
36  *
37  * @author Liam Fallon (liam.fallon@ericsson.com)
38  * @param <K> the generic type
39  * @param <V> the generic type
40  */
41 @Getter
42 public class KeyedMapDifference<K, V> {
43     private static final String KEY = "key=";
44     private static final String VALUE = ",value=";
45
46     // Three maps to hold the comparison result
47     private Map<K, V> leftOnly = new TreeMap<>();
48     private Map<K, V> rightOnly = new TreeMap<>();
49     private Map<K, V> identicalValues = new TreeMap<>();
50     private Map<K, List<V>> differentValues = new TreeMap<>();
51
52     /**
53      * Return a string representation of the differences.
54      *
55      * @param diffsOnly if set, then a blank string is returned if the maps are equal
56      * @param keysOnly if set, then a terse string that prints only the keys is returned, otherwise both keys and values
57      *        are printed
58      * @return the string
59      */
60     public String asString(final boolean diffsOnly, final boolean keysOnly) {
61         var builder = new StringBuilder();
62
63         if (leftOnly.isEmpty()) {
64             if (!diffsOnly) {
65                 builder.append("*** all left keys in right\n");
66             }
67         } else {
68             builder.append(getInOneSideOnlyAsString(leftOnly, "left", keysOnly));
69         }
70
71         if (rightOnly.isEmpty()) {
72             if (!diffsOnly) {
73                 builder.append("*** all right keys in left\n");
74             }
75         } else {
76             builder.append(getInOneSideOnlyAsString(rightOnly, "right", keysOnly));
77         }
78
79         if (differentValues.isEmpty()) {
80             if (!diffsOnly) {
81                 builder.append("*** all values in left and right are identical\n");
82             }
83         } else {
84             builder.append(getDifferencesAsString(keysOnly));
85         }
86
87         if (!diffsOnly) {
88             builder.append(getIdenticalsAsString(keysOnly));
89         }
90
91         return builder.toString();
92     }
93
94     /**
95      * Output the entries in a map with entries that are in one side only as a string.
96      *
97      * @param sideMap the map for the side being checked
98      * @param sideMapString the string that represents the map in output strings
99      * @param keysOnly if true, just add key information and not entries
100      * @return the entries as a string
101      */
102     private Object getInOneSideOnlyAsString(final Map<K, V> sideMap, final String sideMapString,
103                     final boolean keysOnly) {
104         var builder = new StringBuilder();
105
106         builder.append("*** list of keys on " + sideMapString + " only\n");
107         for (Entry<K, V> leftEntry : sideMap.entrySet()) {
108             builder.append(KEY);
109             builder.append(leftEntry.getKey());
110             if (!keysOnly) {
111                 builder.append(VALUE);
112                 builder.append(leftEntry.getValue());
113             }
114             builder.append('\n');
115         }
116
117         return builder.toString();
118     }
119
120     /**
121      * Output the differences between two the maps as a string.
122      *
123      * @param keysOnly if true, just add key information and not entries
124      * @return the differences as a string
125      */
126     private String getDifferencesAsString(final boolean keysOnly) {
127         var builder = new StringBuilder();
128
129         builder.append("*** list of differing entries between left and right\n");
130         for (Entry<K, List<V>> differentEntry : differentValues.entrySet()) {
131             builder.append(KEY);
132             builder.append(differentEntry.getKey());
133             if (!keysOnly) {
134                 builder.append(",values={");
135                 var first = true;
136                 for (V differentEntryValue : differentEntry.getValue()) {
137                     builder.append(differentEntryValue);
138                     if (first) {
139                         first = false;
140                     } else {
141                         builder.append(',');
142                     }
143                 }
144                 builder.append("}");
145             }
146             builder.append('\n');
147         }
148
149         return builder.toString();
150     }
151
152     /**
153      * Output the identical entries in the maps as a string.
154      *
155      * @param keysOnly if true, just add key information and not entries
156      * @return the identical entries as a string
157      */
158     private String getIdenticalsAsString(final boolean keysOnly) {
159         var builder = new StringBuilder();
160
161         builder.append("*** list of identical entries in left and right\n");
162         for (Entry<K, V> identicalEntry : identicalValues.entrySet()) {
163             builder.append(KEY);
164             builder.append(identicalEntry.getKey());
165             if (!keysOnly) {
166                 builder.append(VALUE);
167                 builder.append(identicalEntry.getValue());
168             }
169             builder.append('\n');
170         }
171
172         return builder.toString();
173     }
174 }