• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmrs / openmrs-core / 20275610617

16 Dec 2025 04:41PM UTC coverage: 64.893% (-0.009%) from 64.902%
20275610617

push

github

web-flow
Support ParameterizedType in Reflect#isSuperClass (#5592) (#5605)

1 of 5 new or added lines in 1 file covered. (20.0%)

5 existing lines in 2 files now uncovered.

23449 of 36135 relevant lines covered (64.89%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.31
/api/src/main/java/org/openmrs/util/Reflect.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.util;
11

12

13
import java.lang.annotation.Annotation;
14
import java.lang.reflect.Field;
15
import java.lang.reflect.ParameterizedType;
16
import java.lang.reflect.Type;
17
import java.lang.reflect.TypeVariable;
18
import java.util.ArrayList;
19
import java.util.Collection;
20
import java.util.List;
21

22

23
/**
24
 * This class has convenience methods to find the fields on a class and superclass as well as
25
 * methods to check the class type of members in a collection
26
 */
27
public class Reflect {
28
        
29
        
30
        private Class parametrizedClass;
31
        
32
        /**
33
         * @param parametrizedClass Class
34
         * <strong>Should</strong> throw exception when null is passed
35
         */
36
        public Reflect(Class parametrizedClass) {
1✔
37
                
38
                if (parametrizedClass == null) {
1✔
39
                        throw new NullPointerException("Parametrized class cannot be null");
1✔
40
                }
41
                this.parametrizedClass = parametrizedClass;
1✔
42
        }
1✔
43
        
44
        /**
45
         * @param fieldClass
46
         * @return true if, given fieldClass is Collection otherwise returns false
47
         * <strong>Should</strong> return true if given fieldClass is Collection class
48
         * <strong>Should</strong> return false if given fieldClass is not a Collection class
49
         */
50
        public static boolean isCollection(Class<?> fieldClass) {
51
                return Collection.class.isAssignableFrom(fieldClass);
1✔
52
        }
53
        
54
        /**
55
         * @param object Object
56
         * @return true if, given object is Collection otherwise returns false
57
         * <strong>Should</strong> return true if given object is Collection class
58
         * <strong>Should</strong> return false if given object is not a Collection
59
         */
60
        public static boolean isCollection(Object object) {
61
                return isCollection(object.getClass());
1✔
62
        }
63
        
64
        /**
65
         * This method return all the fields (including private) from the given class and its super
66
         * classes.
67
         * 
68
         * @param fieldClass Class
69
         * @return List&lt;Field&gt;
70
         * <strong>Should</strong> return all fields include private and super classes
71
         */
72
        public static List<Field> getAllFields(Class<?> fieldClass) {
73
                List<Field> fields = new ArrayList<>();
1✔
74
                while (fieldClass != null) {
1✔
75
                        Field[] declaredFields = fieldClass.getDeclaredFields();
1✔
76
                        for (Field field : declaredFields) {
1✔
77
                                field.setAccessible(true);
1✔
78
                                fields.add(field);
1✔
79
                        }
80
                        fieldClass = fieldClass.getSuperclass();
1✔
81
                }
1✔
82
                return fields;
1✔
83
        }
84
        
85
        /**
86
         * This method returns true if the given annotation is present on the given field.
87
         * 
88
         * @param fieldClass
89
         * @param fieldName
90
         * @param annotation
91
         * @return true if the given annotation is present
92
         */
93
        public static boolean isAnnotationPresent(Class<?> fieldClass, String fieldName, Class<? extends Annotation> annotation) {
94
                try {
95
                        Field field = fieldClass.getDeclaredField(fieldName);
1✔
96
                        return field.isAnnotationPresent(annotation);
1✔
97
                } catch (NoSuchFieldException e) {
1✔
98
                        return false; 
1✔
99
                }
100
        }
101
        
102
        /**
103
         * @param subClass Class
104
         * @return true if, given subClass is accessible from the parameterized class
105
         * <strong>Should</strong> return true if given subClass is accessible from given parameterized class
106
         * <strong>Should</strong> return false if given subClass is not accessible from given parameterized class
107
         */
108
        @SuppressWarnings("unchecked")
109
        public boolean isSuperClass(Class subClass) {
110
                return parametrizedClass.isAssignableFrom(subClass);
1✔
111
        }
112
        
113
        /**
114
         * @param t
115
         * @return true if given type is a subclass, or a generic type bounded by a subclass of the
116
         *         parameterized class
117
         * <strong>Should</strong> return true for a generic whose bound is a subclass
118
         * <strong>Should</strong> return false for a generic whose bound is not a subclass
119
         */
120
        public boolean isSuperClass(Type t) {
121
                if (t instanceof TypeVariable<?>) {
1✔
122
                        TypeVariable<?> typeVar = (TypeVariable<?>) t;
1✔
123
                        if (typeVar.getBounds() == null || typeVar.getBounds().length == 0) {
1✔
124
                                return parametrizedClass.equals(Object.class);
×
125
                        }
126
                        for (Type typeBound : typeVar.getBounds()) {
1✔
127
                                if (isSuperClass(typeBound)) {
1✔
128
                                        return true;
1✔
129
                                }
130
                        }
131
                        return false;
×
132
                }
133
                else if (t instanceof ParameterizedType) {
1✔
NEW
134
                        Type rawType = ((ParameterizedType) t).getRawType();
×
NEW
135
                        if (rawType instanceof Class<?>) {
×
NEW
136
                                return isSuperClass((Class<?>) rawType);
×
137
                        } else {
NEW
138
                                throw new IllegalArgumentException("Raw type is not a Class<?>: " + rawType.getClass());
×
139
                        }
140
                } else if (t instanceof Class<?>) {
1✔
141
                        return isSuperClass((Class<?>) t);
1✔
142
                } else {
143
                        throw new IllegalArgumentException("Don't know how to handle: " + t.getClass());
×
144
                }
145
        }
146
        
147
        /**
148
         * @param object Object
149
         * @return true if, given object is accessible from the parameterized class
150
         * <strong>Should</strong> return true if given object is accessible from given parameterized class
151
         * <strong>Should</strong> return false if given object is not accessible from given parameterized class
152
         */
153
        public boolean isSuperClass(Object object) {
154
                return isSuperClass(object.getClass());
1✔
155
        }
156
        
157
        /**
158
         * This method validate the given field is Collection and the elements should be of
159
         * parameterized type
160
         * 
161
         * @param field Field
162
         * @return boolean
163
         * <strong>Should</strong> return true if given field is Collection and its element type is given parameterized
164
         *         class type
165
         * <strong>Should</strong> return false if given field is not a Collection
166
         * <strong>Should</strong> return false if given field is Collection and element type is other than given
167
         *         parameterized class type
168
         */
169
        @SuppressWarnings("unchecked")
170
        public boolean isCollectionField(Field field) {
171
                if (isCollection(field.getType())) {
1✔
172
                        try {
173
                                ParameterizedType type = (ParameterizedType) field.getGenericType();
1✔
174
                                if (type.getActualTypeArguments()[0] instanceof Class) {
1✔
175
                                        return (parametrizedClass.isAssignableFrom((Class) type.getActualTypeArguments()[0]));
1✔
176
                                } else if (type.getActualTypeArguments()[0] instanceof TypeVariable) {
1✔
177
                                        return isSuperClass(type.getActualTypeArguments()[0]);
1✔
178
                                }
179
                        }
180
                        catch (ClassCastException e) {
1✔
181
                                // Do nothing.  If this exception is thrown, then field is not a Collection of OpenmrsObjects
182
                        }
×
183
                }
184
                return false;
1✔
185
        }
186
        
187
        /**
188
         * This method return all the fields (including private) until the given parameterized class
189
         * 
190
         * @param subClass Class
191
         * @return List&lt;Field&gt;
192
         * <strong>Should</strong> return only the sub class fields of given parameterized class
193
         */
194
        public List<Field> getInheritedFields(Class<?> subClass) {
195
                
196
                List<Field> allFields = getAllFields(subClass);
1✔
197
                allFields.removeIf(field -> !hasField(field));
1✔
198
                
199
                return allFields;
1✔
200
        }
201
        
202
        /**
203
         * @param field
204
         * @return true if, given field is declared in parameterized class or its sub classes
205
         */
206
        public boolean hasField(Field field) {
207
                return isSuperClass(field.getDeclaringClass());
1✔
208
        }
209
        
210
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc