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

trydofor / professional-wings / #125

31 Aug 2024 04:46AM UTC coverage: 63.579% (+0.7%) from 62.919%
#125

push

web-flow
Merge pull request #290 from trydofor/develop

3.2.130

1428 of 2191 new or added lines in 106 files covered. (65.18%)

41 existing lines in 24 files now uncovered.

12923 of 20326 relevant lines covered (63.58%)

0.64 hits per line

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

80.3
/wings/slardar/src/main/java/pro/fessional/wings/slardar/jackson/EmptyValuePropertyFilter.java
1
package pro.fessional.wings.slardar.jackson;
2

3
import com.fasterxml.jackson.annotation.JsonFilter;
4
import com.fasterxml.jackson.core.JsonGenerator;
5
import com.fasterxml.jackson.databind.JavaType;
6
import com.fasterxml.jackson.databind.SerializerProvider;
7
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
8
import com.fasterxml.jackson.databind.ser.PropertyWriter;
9
import lombok.extern.slf4j.Slf4j;
10
import org.jetbrains.annotations.Nullable;
11
import pro.fessional.mirana.time.ThreadNow;
12

13
import java.lang.reflect.Array;
14
import java.time.LocalDate;
15
import java.time.LocalDateTime;
16
import java.time.OffsetDateTime;
17
import java.time.ZonedDateTime;
18
import java.util.Collection;
19
import java.util.Date;
20
import java.util.Map;
21

22
/**
23
 * <pre>
24
 * no output if LocalDate, LocalDateTime, ZonedDateTime or OffsetDateTime is `empty`.
25
 * no output if Array, Collection or Map is `empty`.
26
 * </pre>
27
 *
28
 * @author trydofor
29
 * @since 2021-10-28
30
 */
31
@Slf4j
1✔
32
public class EmptyValuePropertyFilter implements AutoRegisterPropertyFilter {
33

34
    public static final String Id = "EmptyValue";
35

36
    @JsonFilter(Id)
37
    public static class EmptyDateMixin {
×
38
    }
39

40
    private final LocalDate emptyDate;
41
    private final LocalDateTime emptyDateMin;
42
    private final LocalDateTime emptyDateMax;
43
    private final boolean emptyList;
44
    private final boolean emptyMap;
45

46
    public EmptyValuePropertyFilter(@Nullable LocalDate emptyDate, int offset, boolean list, boolean map) {
1✔
47
        this.emptyDate = emptyDate;
1✔
48
        if (emptyDate != null) {
1✔
49
            final LocalDateTime dt = emptyDate.atStartOfDay();
1✔
50
            if (offset != 0) {
1✔
51
                this.emptyDateMin = dt.minusHours(offset);
1✔
52
                this.emptyDateMax = dt.plusHours(offset);
1✔
53
            }
54
            else {
55
                this.emptyDateMin = null;
×
56
                this.emptyDateMax = null;
×
57
            }
58
        }
1✔
59
        else {
60
            this.emptyDateMin = null;
×
61
            this.emptyDateMax = null;
×
62
        }
63
        this.emptyList = list;
1✔
64
        this.emptyMap = map;
1✔
65
    }
1✔
66

67
    @Override
68
    public String getId() {
69
        return Id;
1✔
70
    }
71

72
    @Override
73
    public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer) throws Exception {
74
        final JavaType rt = writer.getType();
1✔
75
        if (writer instanceof BeanPropertyWriter) {
1✔
76
            try {
77
                BeanPropertyWriter wt = (BeanPropertyWriter) writer;
1✔
78
                if ((emptyDate != null && dealEmptyDate(pojo, gen, prov, wt, rt)) ||
1✔
79
                    (emptyList && dealEmptyList(pojo, gen, prov, wt, rt)) ||
1✔
80
                    (emptyMap && dealEmptyMap(pojo, gen, prov, wt, rt))) {
1✔
81
                    return;
1✔
82
                }
83
            }
84
            catch (Exception ex) {
×
85
                if (log.isDebugEnabled()) {
×
86
                    // noinspection StringConcatenationArgumentToLogCall
UNCOV
87
                    log.debug("Skipping '" + writer.getFullName() + "' on '" + pojo.getClass().getName()
×
88
                              + "' as an exception was thrown when retrieving its value", ex);
89
                }
90
            }
1✔
91
        }
92
        writer.serializeAsField(pojo, gen, prov);
1✔
93
    }
1✔
94

95
    private boolean dealEmptyList(Object pojo, JsonGenerator gen, SerializerProvider prov, BeanPropertyWriter writer, JavaType rt) throws Exception {
96
        final boolean isArr = rt.isArrayType();
1✔
97
        if ((isArr || rt.isTypeOrSubTypeOf(Collection.class))) {
1✔
98
            final Object v = writer.get(pojo);
1✔
99
            if ((v instanceof Collection && ((Collection<?>) v).isEmpty()) ||
1✔
100
                (isArr && v != null && Array.getLength(v) == 0)) {
1✔
101
                return skipEmpty(pojo, gen, prov, writer);
1✔
102
            }
103
        }
104

105
        return false;
1✔
106
    }
107

108
    private boolean dealEmptyMap(Object pojo, JsonGenerator gen, SerializerProvider prov, BeanPropertyWriter writer, JavaType rt) throws Exception {
109
        if (rt.isTypeOrSubTypeOf(Map.class)) {
1✔
110
            final Object v = writer.get(pojo);
1✔
111
            if (v instanceof Map && ((Map<?, ?>) v).isEmpty()) {
1✔
112
                return skipEmpty(pojo, gen, prov, writer);
1✔
113
            }
114
        }
115
        return false;
1✔
116
    }
117

118
    private boolean dealEmptyDate(Object pojo, JsonGenerator gen, SerializerProvider prov, BeanPropertyWriter writer, JavaType rt) throws Exception {
119
        if ((rt.isTypeOrSubTypeOf(LocalDate.class) ||
1✔
120
             rt.isTypeOrSubTypeOf(LocalDateTime.class) ||
1✔
121
             rt.isTypeOrSubTypeOf(ZonedDateTime.class) ||
1✔
122
             rt.isTypeOrSubTypeOf(OffsetDateTime.class) ||
1✔
123
             rt.isTypeOrSubTypeOf(Date.class))
1✔
124
        ) {
125
            final Object v = writer.get(pojo);
1✔
126
            if ((v instanceof LocalDate && emptyDate((LocalDate) v)) ||
1✔
127
                (v instanceof LocalDateTime && emptyDateTime((LocalDateTime) v)) ||
1✔
128
                (v instanceof ZonedDateTime && emptyDateTime(((ZonedDateTime) v).toLocalDateTime())) ||
1✔
129
                (v instanceof OffsetDateTime && emptyDateTime(((OffsetDateTime) v).toLocalDateTime())) ||
1✔
130
                (v instanceof Date && emptyDateTime((Date) v))
×
131
            ) {
132
                return skipEmpty(pojo, gen, prov, writer);
1✔
133
            }
134
        }
135
        return false;
1✔
136
    }
137

138
    private boolean emptyDate(LocalDate d) {
139
        return emptyDate.equals(d);
1✔
140
    }
141

142
    private boolean emptyDateTime(Date dt) {
143
        final LocalDateTime ldt = dt.toInstant().atZone(ThreadNow.sysZoneId()).toLocalDateTime();
×
144
        return emptyDateTime(ldt);
×
145
    }
146

147
    // Considering timezone, the difference is considered equal within `offset` hours.
148
    private boolean emptyDateTime(LocalDateTime dt) {
149
        if (emptyDate.equals(dt.toLocalDate())) return true;
1✔
150
        if (emptyDateMin == null || emptyDateMax == null) {
1✔
151
            return false;
×
152
        }
153
        else {
154
            return !dt.isBefore(emptyDateMin) && !dt.isAfter(emptyDateMax);
1✔
155
        }
156
    }
157

158
    private boolean skipEmpty(Object pojo, JsonGenerator gen, SerializerProvider prov, BeanPropertyWriter writer) throws Exception {
159
        if (!gen.canOmitFields()) {
1✔
160
            writer.serializeAsOmittedField(pojo, gen, prov);
×
161
        }
162
        return true;
1✔
163
    }
164
}
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

© 2025 Coveralls, Inc