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

LearnLib / automatalib / 19566384231

21 Nov 2025 09:41AM UTC coverage: 92.565% (+0.4%) from 92.206%
19566384231

push

github

web-flow
Bump Java Version to 17/25 (#97)

* initial refactorings for Java 25 compatibility

spotbugs + pmd-plugin still need new releases that work on Java 25

* update CI config

* JDK builds pass

updates to the analysis plugins required some adjustments

* utilize Java 17 features

* fix documentation

* cleanups

* fix visibility issues

* potential fix for breaking GUI tests

* example: fix GUI tests

* cleanups

* jung: do not run GUI tests for now

* Revert "jung: do not run GUI tests for now"

This reverts commit 6a6645488.

* jung: found workaround for crashing JVM

* jacoco: correctly track coverage in GUI tests

* Revert "jung: found workaround for crashing JVM"

This reverts commit d99704042.

* Reapply "jung: do not run GUI tests for now"

This reverts commit 176cece7f.

* jung: add note

145 of 153 new or added lines in 51 files covered. (94.77%)

1 existing line in 1 file now uncovered.

16496 of 17821 relevant lines covered (92.56%)

1.72 hits per line

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

82.18
/commons/util/src/main/java/net/automatalib/common/util/string/StringUtil.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of AutomataLib <https://automatalib.net>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.common.util.string;
17

18
import java.io.IOException;
19
import java.util.Arrays;
20
import java.util.regex.Pattern;
21

22
import org.checkerframework.checker.nullness.qual.Nullable;
23
import org.slf4j.Logger;
24
import org.slf4j.LoggerFactory;
25

26
/**
27
 * Miscellaneous utility functions for {@link String}s.
28
 */
29
public final class StringUtil {
30

31
    private static final Logger LOGGER = LoggerFactory.getLogger(StringUtil.class);
2✔
32

33
    private StringUtil() {
34
        // prevent instantiation
35
    }
36

37
    public static String enquote(String s) {
38
        StringBuilder sb = new StringBuilder(s.length() + 2);
2✔
39
        try {
40
            enquote(s, sb);
2✔
41
        } catch (IOException e) {
×
42
            LOGGER.error("Could not enquote String", e);
×
43
        }
2✔
44
        return sb.toString();
2✔
45
    }
46

47
    public static void enquote(String s, Appendable a) throws IOException {
48
        a.append('"');
2✔
49
        escapeQuotes(s, a);
2✔
50
        a.append('"');
2✔
51
    }
2✔
52

53
    public static Pattern getIdentifierPattern() {
54
        return LazyPatternHolder.INSTANCE;
2✔
55
    }
56

57
    public static String enquoteIfNecessary(String s) {
58
        StringBuilder sb = new StringBuilder();
2✔
59
        try {
60
            enquoteIfNecessary(s, sb);
2✔
61
            return sb.toString();
2✔
62
        } catch (IOException ex) {
×
63
            throw new AssertionError("StringBuilder should not throw", ex);
×
64
        }
65
    }
66

67
    public static void enquoteIfNecessary(String s, Appendable a) throws IOException {
68
        enquoteIfNecessary(s, a, getIdentifierPattern());
2✔
69
    }
2✔
70

71
    public static String enquoteIfNecessary(String s, Pattern p) {
72
        StringBuilder sb = new StringBuilder();
1✔
73
        try {
74
            enquoteIfNecessary(s, sb, p);
1✔
75
            return sb.toString();
1✔
76
        } catch (IOException ex) {
×
77
            throw new AssertionError("StringBuilder should not throw", ex);
×
78
        }
79
    }
80

81
    public static void enquoteIfNecessary(String s, Appendable a, Pattern valid) throws IOException {
82
        if (valid.matcher(s).matches()) {
2✔
83
            a.append(s);
2✔
84
        } else {
85
            enquote(s, a);
2✔
86
        }
87
    }
2✔
88

89
    public static void enquoteIfNecessary(String s, Appendable a, Pattern valid, Pattern exception) throws IOException {
90
        if (!valid.matcher(s).matches() || exception.matcher(s).matches()) {
×
91
            enquote(s, a);
×
92
        } else {
93
            a.append(s);
×
94
        }
95
    }
×
96

97
    public static String unquote(String s) {
98
        if (s.length() < 2) {
2✔
99
            throw new IllegalArgumentException(
2✔
100
                    "Argument to StringUtil.unquote() must begin and end with a double quote ('\"').");
101
        }
102

103
        StringBuilder sb = new StringBuilder(s.length() - 2);
2✔
104
        try {
105
            unquote(s, sb);
2✔
106
        } catch (IOException e) {
×
107
            LOGGER.error("Could not unquote String", e);
×
108
        }
2✔
109
        return sb.toString();
2✔
110
    }
111

112
    public static void unquote(String s, Appendable a) throws IOException {
113
        if (s.charAt(0) != '"' || s.charAt(s.length() - 1) != '"') {
2✔
114
            throw new IllegalArgumentException(
2✔
115
                    "Argument to StringUtil.unquote() must begin and end with a double quote ('\"').");
116
        }
117
        unescapeQuotes(s.substring(1, s.length() - 1), a);
2✔
118
    }
2✔
119

120
    /**
121
     * Unescapes escaped double quotes in a string, i.e. replaces {@code \"} by {@code "} and {@code \\} by {@code \}.
122
     *
123
     * @param s
124
     *         the string in which to unescape double quotes.
125
     *
126
     * @return the unescaped string.
127
     */
128
    public static String unescapeQuotes(String s) {
129
        StringBuilder sb = new StringBuilder(s.length());
2✔
130
        try {
131
            unescapeQuotes(s, sb);
2✔
132
        } catch (IOException e) {
×
133
            LOGGER.error("Could not unescape quotes", e);
×
134
        }
2✔
135
        return sb.toString();
2✔
136
    }
137

138
    public static void unescapeQuotes(String s, Appendable a) throws IOException {
139
        if (s.isEmpty()) {
2✔
140
            return;
2✔
141
        }
142

143
        int idx = 0;
2✔
144
        final int eos = s.length() - 1;
2✔
145

146
        for (; idx < eos; idx++) {
2✔
147
            char c = s.charAt(idx);
2✔
148
            if (c == '\\') {
2✔
149
                c = s.charAt(++idx);
2✔
150
                if (c != '"' && c != '\\') {
2✔
151
                    a.append('\\');
×
152
                }
153
            }
154
            a.append(c);
2✔
155
        }
156

157
        // only append last symbol, if it wasn't forwarded in the loop
158
        if (idx < s.length()) {
2✔
159
            a.append(s.charAt(eos));
2✔
160
        }
161
    }
2✔
162

163
    /**
164
     * Escapes double quotes in a string. Effectively, {@code "} is replaced by {@code \"} and {@code \} is replaced by
165
     * {@code \\}.
166
     *
167
     * @param s
168
     *         the string to escape.
169
     *
170
     * @return the escaped string.
171
     */
172
    public static String escapeQuotes(String s) {
173
        StringBuilder sb = new StringBuilder(s.length());
2✔
174
        try {
175
            escapeQuotes(s, sb);
2✔
176
        } catch (IOException e) {
×
177
            LOGGER.error("Could not escape quotes", e);
×
178
        }
2✔
179
        return sb.toString();
2✔
180
    }
181

182
    public static void escapeQuotes(String s, Appendable a) throws IOException {
183
        for (int i = 0; i < s.length(); i++) {
2✔
184
            char c = s.charAt(i);
2✔
185

186
            if (c == '\\' || c == '"') {
2✔
187
                a.append('\\');
2✔
188
            }
189
            a.append(c);
2✔
190
        }
191
    }
2✔
192

193
    public static void appendArray(Appendable a, Object[] array, String sepString) throws IOException {
194
        appendIterable(a, Arrays.asList(array), sepString);
2✔
195
    }
2✔
196

197
    public static void appendArrayEnquoted(Appendable a, Object[] array, String sepString) throws IOException {
198
        appendIterableEnquoted(a, Arrays.asList(array), sepString);
2✔
199
    }
2✔
200

201
    public static void appendIterable(Appendable a, Iterable<?> it, String sepString) throws IOException {
202
        boolean first = true;
2✔
203

204
        for (Object o : it) {
2✔
205
            if (first) {
2✔
206
                first = false;
2✔
207
            } else {
208
                a.append(sepString);
2✔
209
            }
210
            appendObject(a, o);
2✔
211
        }
2✔
212
    }
2✔
213

214
    public static void appendIterableEnquoted(Appendable a, Iterable<?> it, String sepString) throws IOException {
215
        boolean first = true;
2✔
216

217
        for (Object o : it) {
2✔
218
            if (first) {
2✔
219
                first = false;
2✔
220
            } else {
221
                a.append(sepString);
2✔
222
            }
223
            enquote(String.valueOf(o), a);
2✔
224
        }
2✔
225
    }
2✔
226

227
    public static void appendObject(Appendable a, @Nullable Object obj) throws IOException {
228
        if (obj instanceof Printable p) {
2✔
NEW
229
            p.print(a);
×
230
        } else {
231
            a.append(String.valueOf(obj));
2✔
232
        }
233
    }
2✔
234

235
    /**
236
     * Lazy holder for identifier pattern. See
237
     * <a href="https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom">
238
     * Initialization-on-demand holder idiom</a>
239
     */
240
    private static final class LazyPatternHolder {
241

242
        private static final Pattern INSTANCE = Pattern.compile("[a-zA-Z_]*\\w*");
2✔
243
    }
244
}
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