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

burningwave / reflection / #68

18 Oct 2023 11:19AM UTC coverage: 74.528% (+5.4%) from 69.107%
#68

push

Roberto-Gentili
Bug fix

790 of 1060 relevant lines covered (74.53%)

0.75 hits per line

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

69.23
/src/main/java/org/burningwave/reflection/Fields.java
1
/*
2
 * This file is part of Burningwave Reflection.
3
 *
4
 * Author: Roberto Gentili
5
 *
6
 * Hosted at: https://github.com/burningwave/reflection
7
 *
8
 * --
9
 *
10
 * The MIT License (MIT)
11
 *
12
 * Copyright (c) 2022 Roberto Gentili
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
15
 * documentation files (the "Software"), to deal in the Software without restriction, including without
16
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17
 * the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
18
 * conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all copies or substantial
21
 * portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25
 * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
27
 * OR OTHER DEALINGS IN THE SOFTWARE.
28
 */
29
package org.burningwave.reflection;
30

31

32
import java.lang.reflect.Field;
33
import java.lang.reflect.Modifier;
34
import java.util.Collection;
35
import java.util.HashMap;
36
import java.util.Map;
37
import java.util.function.Supplier;
38

39
import org.burningwave.Classes;
40
import org.burningwave.Throwables;
41

42
import io.github.toolfactory.jvm.util.Strings;
43

44

45
public class Fields extends Members.Handler<Field, FieldCriteria> {
46

47
        public static final Fields INSTANCE;
48

49
        static {
50
                INSTANCE = new Fields();
1✔
51
        }
1✔
52

53
        private Fields() {}
1✔
54

55
        public Collection<Field> findAllAndMakeThemAccessible(
56
                Class<?> targetClass
57
        ) {
58
                String cacheKey = getCacheKey(targetClass, Members.ALL_FOR_CLASS, (Class<?>[])null);
1✔
59
                return Cache.INSTANCE.uniqueKeyForAllFields.getOrUploadIfAbsent(
1✔
60
                        cacheKey,
61
                        () ->
62
                                findAllAndMakeThemAccessible(
1✔
63
                                        FieldCriteria.forEntireClassHierarchy(), targetClass
1✔
64
                                )
65
                );
66
        }
67

68
        public Collection<Field> findAllByExactNameAndMakeThemAccessible(
69
                Class<?> targetClass,
70
                String fieldName
71
        ) {
72
                return findAllByExactNameAndMakeThemAccessible(targetClass, fieldName, null);
×
73
        }
74

75
        public Collection<Field> findAllByExactNameAndMakeThemAccessible(
76
                Class<?> targetClass,
77
                String fieldName,
78
                Class<?> valueType
79
        ) {
80
                String cacheKey = getCacheKey(targetClass, "equals " + fieldName, valueType);
1✔
81
                return Cache.INSTANCE.uniqueKeyForAllFields.getOrUploadIfAbsent(
1✔
82
                        cacheKey,
83
                        () ->
84
                                findAllAndMakeThemAccessible(
1✔
85
                                        FieldCriteria.forEntireClassHierarchy().allThoseThatMatch(field -> {
1✔
86
                                                if (valueType == null) {
1✔
87
                                                        return field.getName().equals(fieldName);
1✔
88
                                                } else {
89
                                                        return field.getName().equals(fieldName) && Classes.INSTANCE.isAssignableFrom(field.getType(), valueType);
1✔
90
                                                }
91
                                        }), targetClass
92
                                )
93
                );
94
        }
95

96
        public Field findFirstAndMakeItAccessible(Class<?> targetClass, String fieldName) {
97
                return findFirstAndMakeItAccessible(targetClass, fieldName, null);
×
98
        }
99

100
        public Field findFirstAndMakeItAccessible(Class<?> targetClass, String fieldName, Class<?> fieldTypeOrSubType) {
101
                Collection<Field> members = findAllByExactNameAndMakeThemAccessible(targetClass, fieldName, fieldTypeOrSubType);
1✔
102
                if (members.size() < 1) {
1✔
103
                        Throwables.INSTANCE.throwException(
×
104
                                new NoSuchFieldException(
105
                                        Strings.compile("Field {} not found in {} hierarchy", fieldName, targetClass.getName())
×
106
                                )
107
                        );
108
                }
109
                return members.stream().findFirst().get();
1✔
110
        }
111

112
        public Field findOneAndMakeItAccessible(Class<?> targetClass, String memberName) {
113
                Collection<Field> members = findAllByExactNameAndMakeThemAccessible(targetClass, memberName, null);
1✔
114
                if (members.size() != 1) {
1✔
115
                        Throwables.INSTANCE.throwException(
×
116
                                new NoSuchFieldException(
117
                                        Strings.compile("Field {} not found or found more than one field in {} hierarchy", memberName, targetClass.getName())
×
118
                                )
119
                        );
120
                }
121
                return members.stream().findFirst().get();
1✔
122
        }
123

124
        public <T> T get(Object target, Field field) {
125
                return Facade.INSTANCE.getFieldValue(target, field);
1✔
126
        }
127

128
        public <T> T get(Object target, String fieldName) {
129
                return get(target, findFirstAndMakeItAccessible(Classes.INSTANCE.retrieveFrom(target), fieldName, null));
1✔
130
        }
131

132
        public Map<Field, ?> getAll(FieldCriteria criteria, Object target) {
133
                return getAll(() -> findAllAndMakeThemAccessible(criteria, Classes.INSTANCE.retrieveFrom(target)), target);
1✔
134
        }
135

136
        public Map<Field, ?> getAll(Object target) {
137
                return getAll(() -> findAllAndMakeThemAccessible(Classes.INSTANCE.retrieveFrom(target)), target);
1✔
138
        }
139

140
        public Map<Field, ?> getAllDirect(FieldCriteria criteria, Object target) {
141
                return getAllDirect(() -> findAllAndMakeThemAccessible(criteria, Classes.INSTANCE.retrieveFrom(target)), target);
×
142
        }
143

144

145
        public Map<Field, ?> getAllDirect(Object target) {
146
                return getAllDirect(() -> findAllAndMakeThemAccessible(Classes.INSTANCE.retrieveFrom(target)), target);
1✔
147
        }
148

149
        public Map<Field, ?> getAllStatic(Class<?> targetClass) {
150
                return getAll(() -> findAllAndMakeThemAccessible(targetClass), null);
×
151
        }
152

153
        public Map<Field, ?> getAllStaticDirect(Class<?> targetClass) {
154
                return getAllDirect(() -> findAllAndMakeThemAccessible(targetClass), null);
×
155
        }
156

157
        public <T> T getStatic(Class<?> targetClass, String fieldName) {
158
                return getStatic(findFirstAndMakeItAccessible(targetClass, fieldName, null));
×
159
        }
160

161
        public <T> T getStatic(Field field) {
162
                return get(null, field);
×
163
        }
164

165
        public void set(Object target, Field field, Object value) {
166
                Facade.INSTANCE.setFieldValue(target, field, value);
1✔
167
        }
1✔
168

169
        public void set(Object target, String fieldName, Object value) {
170
                set(Classes.INSTANCE.retrieveFrom(target), target, fieldName, value);
1✔
171
        }
1✔
172

173
        public void setStatic(Class<?> targetClass, String fieldName, Object value) {
174
                set(targetClass, null, fieldName, value);
×
175
        }
×
176

177
        public void setStatic(Field field, Object value) {
178
                set(null, field, value);
×
179
        }
×
180

181
        private Map<Field, Object> getAll(Supplier<Collection<Field>> fieldsSupplier, Object target) {
182
                Map<Field, Object> fieldValues = new HashMap<>();
1✔
183
                for (Field field : fieldsSupplier.get()) {
1✔
184
                        if (target != null) {
1✔
185
                                fieldValues.put(
1✔
186
                                        field,
187
                                        get(
1✔
188
                                                Modifier.isStatic(field.getModifiers()) ? null : target, field
1✔
189
                                        )
190
                                );
191
                        } else if (Modifier.isStatic(field.getModifiers())) {
×
192
                                fieldValues.put(
×
193
                                        field,
194
                                        get(null, field)
×
195
                                );
196
                        }
197
                }
1✔
198
                return fieldValues;
1✔
199
        }
200

201
        private Map<Field, ?> getAllDirect(Supplier<Collection<Field>> fieldsSupplier, Object target) {
202
                Map<Field, ?> fieldValues = new HashMap<>();
1✔
203
                for (Field field : fieldsSupplier.get()) {
1✔
204
                        fieldValues.put(
1✔
205
                                field,
206
                                Facade.INSTANCE.getFieldValue(target, field)
1✔
207
                        );
208
                }
1✔
209
                return fieldValues;
1✔
210
        }
211

212
        private void set(Class<?> targetClass, Object target, String fieldName, Object value) {
213
                set(target, findFirstAndMakeItAccessible(targetClass, fieldName, Classes.INSTANCE.retrieveFrom(value)), value);
1✔
214
        }
1✔
215

216
        public static class NoSuchFieldException extends RuntimeException {
217

218
                private static final long serialVersionUID = 3656790511956737635L;
219

220
                public NoSuchFieldException(String message) {
221
                        super(message);
×
222
                }
×
223

224
        }
225

226
}
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