Reformat catalog-model
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / utils / TypeCompareUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.model.utils;
21
22 import static org.springframework.util.CollectionUtils.isEmpty;
23
24 import com.google.common.base.Strings;
25 import fj.data.Either;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29 import java.util.stream.Collectors;
30 import org.apache.commons.collections.SetUtils;
31 import org.openecomp.sdc.be.dao.utils.MapUtil;
32 import org.openecomp.sdc.be.model.CapabilityDefinition;
33 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
34 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
35 import org.openecomp.sdc.be.model.GroupTypeDefinition;
36 import org.openecomp.sdc.be.model.PropertyDefinition;
37 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
38 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
39 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
40
41 /**
42  * Types comparison utils The class is required since origin class "equals" methods take in account fields that should be ignored during update of
43  * that types.
44  *
45  * @author dr2032
46  */
47 public class TypeCompareUtils {
48
49     private TypeCompareUtils() {
50     }
51
52     public static <R> Either<R, StorageOperationStatus> typeAlreadyExists() {
53         return Either.right(StorageOperationStatus.OK);
54     }
55
56     public static boolean isGroupTypesEquals(GroupTypeDefinition gt1, GroupTypeDefinition gt2) {
57         if (gt1 == gt2) {
58             return true;
59         }
60         if (gt1 == null || gt2 == null) {
61             return false;
62         }
63         /*
64          * We compare here attributes, capabilities and not inherited properties of group types.
65          * So even if properties of group type parent were changed it will not effect on comparison of these group types.
66          */
67         return Objects.equals(gt1.getType(), gt2.getType()) && Objects.equals(gt1.getName(), gt2.getName()) && Objects
68             .equals(gt1.getIcon(), gt2.getIcon()) && Objects.equals(gt1.getVersion(), gt2.getVersion()) && Objects
69             .equals(gt1.getDerivedFrom(), gt2.getDerivedFrom()) && Objects.equals(gt1.getMembers(), gt2.getMembers()) && Objects
70             .equals(gt1.getMetadata(), gt2.getMetadata()) && capabilitiesEqual(gt1.getCapabilities(), gt2.getCapabilities()) && propertiesEquals(
71             collectNotInheritedProperties(gt1.getProperties(), gt1.getUniqueId()),
72             collectNotInheritedProperties(gt2.getProperties(), gt2.getUniqueId()));
73     }
74
75     public static boolean isCapabilityTypesEquals(CapabilityTypeDefinition ct1, CapabilityTypeDefinition ct2) {
76         if (ct1 == ct2) {
77             return true;
78         }
79         if (ct1 == null || ct2 == null) {
80             return false;
81         }
82         return Objects.equals(ct1.getType(), ct2.getType()) && Objects.equals(ct1.getDerivedFrom(), ct2.getDerivedFrom()) && Objects
83             .equals(ct1.getDescription(), ct2.getDescription()) && SetUtils.isEqualSet(ct1.getValidSourceTypes(), ct2.getValidSourceTypes())
84             && propertiesEquals(ct1.getProperties(), ct2.getProperties());
85     }
86
87     public static boolean isRelationshipTypesEquals(RelationshipTypeDefinition rs1, RelationshipTypeDefinition rs2) {
88         if (rs1 == rs2) {
89             return true;
90         }
91         if (rs1 == null || rs2 == null) {
92             return false;
93         }
94         return Objects.equals(rs1.getType(), rs2.getType()) && Objects.equals(rs1.getDerivedFrom(), rs2.getDerivedFrom()) && Objects
95             .equals(rs1.getDescription(), rs2.getDescription()) && SetUtils.isEqualSet(rs1.getValidSourceTypes(), rs2.getValidSourceTypes())
96             && propertiesEquals(rs1.getProperties(), rs2.getProperties());
97     }
98
99     private static boolean propertiesEquals(Map<String, PropertyDefinition> props1, Map<String, PropertyDefinition> props2) {
100         if (props1 == props2) {
101             return true;
102         }
103         if (isEmpty(props1) && isEmpty(props2)) {
104             return true;
105         } else if (props1 == null || props2 == null) {
106             return false;
107         } else if (props1.size() != props2.size()) {
108             return false;
109         }
110         return props2.entrySet().stream().allMatch(entry -> propertyEquals(props1.get(entry.getKey()), entry.getValue()));
111     }
112
113     public static boolean propertiesEquals(List<PropertyDefinition> props1, List<PropertyDefinition> props2) {
114         if (props1 == props2) {
115             return true;
116         }
117         if (isEmpty(props1) && isEmpty(props2)) {
118             return true;
119         } else if (props1 == null || props2 == null) {
120             return false;
121         } else if (props1.size() != props2.size()) {
122             return false;
123         }
124         Map<String, PropertyDefinition> pt1PropsByName = MapUtil.toMap(props1, PropertyDefinition::getName);
125         return props2.stream().allMatch(pt2Prop -> propertyEquals(pt1PropsByName.get(pt2Prop.getName()), pt2Prop));
126     }
127
128     private static boolean propertyEquals(PropertyDefinition prop1, PropertyDefinition prop2) {
129         if (prop1 == prop2) {
130             return true;
131         }
132         if (prop1 == null || prop2 == null) {
133             return false;
134         }
135         return Objects.equals(prop1.getDefaultValue(), prop2.getDefaultValue()) && prop1.isDefinition() == prop2.isDefinition() && Objects
136             .equals(prop1.getDescription(), prop2.getDescription()) && prop1.isPassword() == prop2.isPassword() && prop1.isRequired() == prop2
137             .isRequired() && Objects.equals(prop1.getSchemaType(), prop2.getSchemaType()) && Objects.equals(prop1.getType(), prop2.getType());
138     }
139
140     private static boolean capabilitiesEqual(Map<String, CapabilityDefinition> caps1, Map<String, CapabilityDefinition> caps2) {
141         if (caps1 == caps2) {
142             return true;
143         }
144         if (caps1 == null || caps2 == null) {
145             return false;
146         }
147         if (caps1.size() != caps2.size()) {
148             return false;
149         }
150         return caps2.entrySet().stream().allMatch(capEntry2 -> capabilityEquals(caps1.get(capEntry2.getKey()), capEntry2.getValue()));
151     }
152
153     public static boolean capabilityEquals(CapabilityDefinition capDef1, CapabilityDefinition capDef2) {
154         return Objects.equals(capDef1.getName(), capDef2.getName()) && Objects.equals(capDef1.getType(), capDef2.getType()) && Objects
155             .equals(capDef1.getDescription(), capDef2.getDescription()) && propValuesEqual(capDef1.getProperties(), capDef2.getProperties());
156     }
157
158     private static boolean propValuesEqual(final List<ComponentInstanceProperty> props1, final List<ComponentInstanceProperty> props2) {
159         Map<String, String> propValues1 = toValueMap(props1);
160         Map<String, String> propValues2 = toValueMap(props2);
161         return propValues1.equals(propValues2);
162     }
163
164     /**
165      * @param props
166      * @return
167      */
168     private static Map<String, String> toValueMap(final List<ComponentInstanceProperty> props) {
169         return props.stream().filter(TypeCompareUtils::isCapabilityPropValue)
170             .collect(Collectors.toMap(ComponentInstanceProperty::getName, p -> p.getValue() != null ? p.getValue() : ""));
171     }
172
173     /**
174      * Returns true if the property object was created from property value or false otherwise
175      * <p>
176      * We try to segregate original properties values from dummy ones created from relevant properties. Such dummy property value doesn't have their
177      * valueUniqueId but it has uniqueId taken from property.
178      *
179      * @param property
180      * @return
181      */
182     private static boolean isCapabilityPropValue(ComponentInstanceProperty property) {
183         return property.getValueUniqueUid() != null || property.getUniqueId() == null;
184     }
185
186     /**
187      * Collect properties of resource that belongs to it without taking in account properties inherited from resource parents.
188      */
189     private static List<PropertyDefinition> collectNotInheritedProperties(List<PropertyDefinition> properties, String resourceId) {
190         if (Strings.isNullOrEmpty(resourceId)) {
191             return properties;
192         }
193         return properties.stream().filter(prop -> !isInherited(prop, resourceId)).collect(Collectors.toList());
194     }
195
196     private static boolean isInherited(PropertyDefinition prop, String resourceId) {
197         return prop.getUniqueId() != null && !prop.getUniqueId().equals(UniqueIdBuilder.buildPropertyUniqueId(resourceId, prop.getName()));
198     }
199 }