88a83db7e2958232c697e9f7d64ac8ada17cd581
[so.git] / common / src / main / java / org / onap / so / openpojo / rules / EqualsAndHashCodeTester.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.openpojo.rules;
24
25 import static org.hamcrest.CoreMatchers.anyOf;
26 import static org.hamcrest.CoreMatchers.anything;
27
28 import java.lang.reflect.Method;
29 import java.util.ArrayList;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import javax.persistence.GeneratedValue;
35 import javax.persistence.Id;
36
37 import org.hamcrest.Matcher;
38
39 import com.openpojo.business.annotation.BusinessKey;
40 import com.openpojo.random.RandomFactory;
41 import com.openpojo.reflection.PojoClass;
42 import com.openpojo.reflection.PojoField;
43 import com.openpojo.validation.affirm.Affirm;
44 import com.openpojo.validation.test.Tester;
45 import com.openpojo.validation.utils.ValidationHelper;
46
47 public class EqualsAndHashCodeTester implements Tester {
48
49         
50         private final Matcher m;
51         private boolean onlyDeclaredMethods = false;
52         public EqualsAndHashCodeTester() {
53                 m = anything();
54         }
55         
56         public EqualsAndHashCodeTester(Matcher m) {
57                 this.m = m;
58         }
59         
60         public EqualsAndHashCodeTester onlyDeclaredMethods() {
61                 this.onlyDeclaredMethods = true;
62                 return this;
63         }
64
65         // Marks sonar warnings about object being compared to itself as false positive
66         // https://sonar.onap.org/coding_rules#rule_key=squid%3AS1764
67         @SuppressWarnings("squid:S1764")
68         @Override
69         public void run(PojoClass pojoClass) {
70                 Class<?> clazz = pojoClass.getClazz();
71                 if (anyOf(m).matches(clazz)) {
72                         final Object classInstanceOne = ValidationHelper.getBasicInstance(pojoClass);
73                         final Object classInstanceTwo = ValidationHelper.getBasicInstance(pojoClass);
74                         if (onlyDeclaredMethods) {
75                                 Method[] methods = classInstanceOne.getClass().getDeclaredMethods();
76                                 boolean hasEquals = false;
77                                 boolean hasHashcode = false;
78                                 for (Method method : methods) {
79                                         if (method.getName().equals("equals")) {
80                                                 hasEquals = true;
81                                         } else if (method.getName().equals("hashCode")) {
82                                                 hasHashcode = true;
83                                         }
84                                 }
85                                 
86                                 if (!(hasEquals && hasHashcode)) {
87                                         return;
88                                 }
89                         }
90                         Set<PojoField> identityFields = hasIdOrBusinessKey(pojoClass);
91                         List<PojoField> otherFields = new ArrayList<>(pojoClass.getPojoFields());
92                         otherFields.removeAll(identityFields);
93                         
94                         for (PojoField field : identityFields) {
95                                 final Object value  = RandomFactory.getRandomValue(field);
96         
97                                 field.invokeSetter(classInstanceOne, value);
98                                 field.invokeSetter(classInstanceTwo, value);
99                         }
100                         
101                         for (PojoField field : otherFields) {
102                                 if (field.hasSetter()) {
103                                         final Object valueOne  = RandomFactory.getRandomValue(field);
104                                         final Object valueTwo  = RandomFactory.getRandomValue(field);
105                                         
106                                         field.invokeSetter(classInstanceOne, valueOne);
107                                         field.invokeSetter(classInstanceTwo, valueTwo);
108                                 }
109                         }
110                         
111                         Affirm.affirmTrue("Equals test failed for [" + classInstanceOne.getClass().getName() + "]", classInstanceOne.equals(classInstanceTwo));
112                         
113                         Affirm.affirmTrue("Expected true for comparison of the same references [" + classInstanceOne.getClass().getName() + "]",
114                                 classInstanceOne.equals(classInstanceOne));
115
116                         Affirm.affirmTrue("HashCode test failed for [" + classInstanceOne.getClass().getName() + "]", classInstanceOne.hashCode() == classInstanceTwo.hashCode());
117                         
118                         Affirm.affirmFalse("Expected false for comparison of two unlike objects", classInstanceOne.equals("test"));
119                 }
120         }
121         
122         
123         private Set<PojoField> hasIdOrBusinessKey(PojoClass pojoClass) {
124                 final Set<PojoField> fields = new HashSet<>();
125                 
126                 fields.addAll(pojoClass.getPojoFieldsAnnotatedWith(BusinessKey.class));
127                 fields.addAll(pojoClass.getPojoFieldsAnnotatedWith(Id.class));
128                 fields.removeAll(pojoClass.getPojoFieldsAnnotatedWith(GeneratedValue.class));
129                 
130                 return fields;
131                 
132         }
133
134 }