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

oracle / opengrok / #3691

09 Nov 2023 04:15PM UTC coverage: 74.721% (+8.6%) from 66.08%
#3691

push

web-flow
avoid annotations for binary files (#4476)

fixes #4473

6 of 13 new or added lines in 4 files covered. (46.15%)

258 existing lines in 28 files now uncovered.

43797 of 58614 relevant lines covered (74.72%)

0.75 hits per line

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

62.64
/opengrok-indexer/src/main/java/org/opengrok/indexer/web/messages/Message.java
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * See LICENSE.txt included in this distribution for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing Covered Code, include this CDDL HEADER in each
12
 * file and include the License file at LICENSE.txt.
13
 * If applicable, add the following below this CDDL HEADER, with the
14
 * fields enclosed by brackets "[]" replaced with your own identifying
15
 * information: Portions Copyright [yyyy] [name of copyright owner]
16
 *
17
 * CDDL HEADER END
18
 */
19

20
/*
21
 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
 */
23
package org.opengrok.indexer.web.messages;
24

25
import com.fasterxml.jackson.core.JsonGenerator;
26
import com.fasterxml.jackson.core.JsonParser;
27
import com.fasterxml.jackson.databind.DeserializationContext;
28
import com.fasterxml.jackson.databind.SerializerProvider;
29
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
30
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
31
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
32
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
33
import jakarta.validation.constraints.NotBlank;
34
import jakarta.validation.constraints.NotEmpty;
35
import org.opengrok.indexer.web.Util;
36
import org.opengrok.indexer.web.api.constraints.PositiveDuration;
37

38
import java.io.IOException;
39
import java.time.Duration;
40
import java.time.format.DateTimeParseException;
41
import java.util.Collections;
42
import java.util.Comparator;
43
import java.util.Locale;
44
import java.util.Objects;
45
import java.util.Set;
46
import java.util.TreeSet;
47

48
import static org.opengrok.indexer.web.messages.MessagesContainer.MESSAGES_MAIN_PAGE_TAG;
49

50
public class Message implements Comparable<Message>, JSONable {
51

52
    @NotEmpty(message = "tags cannot be empty")
1✔
53
    private Set<String> tags = Collections.singleton(MESSAGES_MAIN_PAGE_TAG);
1✔
54

55
    public enum MessageLevel {
1✔
56
        /**
57
         * Known values: {@code SUCCESS}, {@code INFO}, {@code WARNING}, {@code ERROR}.
58
         * The values are sorted according to their level. Higher numeric value of the level (i.e. the enum ordinal)
59
         * means higher priority.
60
         */
61
        SUCCESS("success"), INFO("info"), WARNING("warning"), ERROR("error");
1✔
62

63
        private final String messageLevelString;
64

65
        MessageLevel(String str) {
1✔
66
            messageLevelString = str;
1✔
67
        }
1✔
68

69
        public static MessageLevel fromString(String val) throws IllegalArgumentException {
70
            for (MessageLevel v : MessageLevel.values()) {
×
71
                if (v.toString().equals(val.toLowerCase(Locale.ROOT))) {
×
72
                    return v;
×
73
                }
74
            }
75
            throw new IllegalArgumentException("class type does not match any known value");
×
76
        }
77

78
        @Override
79
        public String toString() {
80
            return messageLevelString;
1✔
81
        }
82

83
        public static final Comparator<MessageLevel> VALUE_COMPARATOR = Comparator.comparingInt(Enum::ordinal);
1✔
84
    }
85

86
    @JsonDeserialize(using = MessageLevelDeserializer.class)
1✔
87
    @JsonSerialize(using = MessageLevelSerializer.class)
88
    private MessageLevel messageLevel = MessageLevel.INFO;
89

90
    @NotBlank(message = "text cannot be empty")
91
    @JsonSerialize(using = HTMLSerializer.class)
92
    private String text;
93

94
    @PositiveDuration(message = "duration must be positive")
1✔
95
    @JsonSerialize(using = DurationSerializer.class)
96
    @JsonDeserialize(using = DurationDeserializer.class)
97
    private Duration duration = Duration.ofMinutes(10);
1✔
98

99
    private Message() { // needed for deserialization
×
100
    }
×
101

102
    public Message(
103
            final String text,
104
            final Set<String> tags,
105
            final MessageLevel messageLevel,
106
            final Duration duration
107
    ) {
1✔
108
        if (text == null || text.isEmpty()) {
1✔
109
            throw new IllegalArgumentException("text cannot be null or empty");
1✔
110
        }
111
        if (tags == null || tags.isEmpty()) {
1✔
112
            throw new IllegalArgumentException("tags cannot be null or empty");
1✔
113
        }
114
        if (duration == null || duration.isNegative()) {
1✔
115
            throw new IllegalArgumentException("duration cannot be null or negative");
1✔
116
        }
117

118
        this.text = text;
1✔
119
        this.tags = tags;
1✔
120
        this.messageLevel = messageLevel;
1✔
121
        this.duration = duration;
1✔
122
    }
1✔
123

124
    public Set<String> getTags() {
125
        return tags;
1✔
126
    }
127

128
    public MessageLevel getMessageLevel() {
129
        return messageLevel;
1✔
130
    }
131

132
    public String getText() {
133
        return text;
1✔
134
    }
135

136
    public Duration getDuration() {
137
        return duration;
1✔
138
    }
139

140
    /**
141
     * @param t set of tags
142
     * @return true if message has at least one of the tags
143
     */
144
    public boolean hasAny(Set<String> t) {
145
        Set<String> tmp = new TreeSet<>(t);
1✔
146
        tmp.retainAll(tags);
1✔
147
        return !tmp.isEmpty();
1✔
148
    }
149

150
    /**
151
     * @param tags set of tags to check
152
     * @param text message text
153
     * @return true if a mesage has at least one of the tags and text
154
     */
155
    public boolean hasTagsAndText(Set<String> tags, String text) {
156
        if (text == null || text.isEmpty()) {
×
157
            return hasAny(tags);
×
158
        }
159

160
        return hasAny(tags) && getText().equals(text);
×
161
    }
162

163
    @Override
164
    public boolean equals(Object o) {
165
        if (this == o) {
1✔
166
            return true;
1✔
167
        }
168
        if (o == null || getClass() != o.getClass()) {
×
169
            return false;
×
170
        }
171
        Message message = (Message) o;
×
172
        return Objects.equals(tags, message.tags) &&
×
173
                Objects.equals(messageLevel, message.messageLevel) &&
×
174
                Objects.equals(text, message.text) &&
×
175
                Objects.equals(duration, message.duration);
×
176
    }
177

178
    @Override
179
    public int hashCode() {
180
        return Objects.hash(tags, messageLevel, text, duration);
1✔
181
    }
182

183
    @Override
184
    public int compareTo(final Message o) {
185
        int i;
186
        if (text != null && (i = text.compareTo(o.text)) != 0) {
1✔
UNCOV
187
            return i;
×
188
        }
189
        if (duration != null && (i = duration.compareTo(o.duration)) != 0) {
1✔
190
            return i;
×
191
        }
192
        return tags.size() - o.tags.size();
1✔
193
    }
194

195
    static class MessageLevelSerializer extends StdSerializer<MessageLevel> {
196
        private static final long serialVersionUID = 928540953227342817L;
197

198
        MessageLevelSerializer() {
199
            this(null);
1✔
200
        }
1✔
201

202
        MessageLevelSerializer(Class<MessageLevel> vc) {
203
            super(vc);
1✔
204
        }
1✔
205

206
        @Override
207
        public void serialize(final MessageLevel messageLevel,
208
                                final JsonGenerator jsonGenerator,
209
                                final SerializerProvider serializerProvider) throws IOException {
210
            jsonGenerator.writeString(messageLevel.toString().toLowerCase(Locale.ROOT));
1✔
211
        }
1✔
212
    }
213

214
    private static class MessageLevelDeserializer extends StdDeserializer<MessageLevel> {
215
        private static final long serialVersionUID = 928540953227342817L;
216

217
        MessageLevelDeserializer() {
218
            this(null);
×
219
        }
×
220

221
        MessageLevelDeserializer(Class<?> vc) {
222
            super(vc);
×
223
        }
×
224

225
        @Override
226
        public MessageLevel deserialize(final JsonParser parser, final DeserializationContext context)
227
                throws IOException {
228
            try {
229
                return MessageLevel.fromString(context.readValue(parser, String.class));
×
230
            } catch (DateTimeParseException e) {
×
231
                throw new IOException(e);
×
232
            }
233
        }
234
    }
235

236
    private static class DurationSerializer extends StdSerializer<Duration> {
237

238
        private static final long serialVersionUID = 5275434375701446542L;
239

240
        DurationSerializer() {
241
            this(null);
1✔
242
        }
1✔
243

244
        DurationSerializer(final Class<Duration> cl) {
245
            super(cl);
1✔
246
        }
1✔
247

248
        @Override
249
        public void serialize(
250
                final Duration duration,
251
                final JsonGenerator jsonGenerator,
252
                final SerializerProvider serializerProvider
253
        ) throws IOException {
254
            if (duration != null) {
1✔
255
                jsonGenerator.writeString(duration.toString());
1✔
256
            } else {
257
                jsonGenerator.writeNull();
×
258
            }
259
        }
1✔
260
    }
261

262
    private static class DurationDeserializer extends StdDeserializer<Duration> {
263
        private static final long serialVersionUID = 5513386447457242809L;
264

265
        DurationDeserializer() {
266
            this(null);
×
267
        }
×
268

269
        DurationDeserializer(Class<?> vc) {
270
            super(vc);
×
271
        }
×
272

273
        @Override
274
        public Duration deserialize(final JsonParser parser, final DeserializationContext context)
275
                throws IOException {
276
            try {
277
                return Duration.parse(context.readValue(parser, String.class));
×
278
            } catch (DateTimeParseException e) {
×
279
                throw new IOException(e);
×
280
            }
281
        }
282
    }
283

284
    protected static class HTMLSerializer extends StdSerializer<String> {
285

286
        private static final long serialVersionUID = -2843900664165513923L;
287

288
        HTMLSerializer() {
289
            this(null);
1✔
290
        }
1✔
291

292
        HTMLSerializer(final Class<String> cl) {
293
            super(cl);
1✔
294
        }
1✔
295

296
        @Override
297
        public void serialize(
298
                final String string,
299
                final JsonGenerator jsonGenerator,
300
                final SerializerProvider serializerProvider
301
        ) throws IOException {
302
            if (string != null) {
1✔
303
                jsonGenerator.writeString(Util.encode(string));
1✔
304
            } else {
305
                jsonGenerator.writeNull();
×
306
            }
307
        }
1✔
308
    }
309
}
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