• 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

70.59
/serialization/fsm/src/main/java/net/automatalib/serialization/fsm/parser/FSM2MealyParserIO.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.serialization.fsm.parser;
17

18
import java.io.IOException;
19
import java.io.StreamTokenizer;
20
import java.util.Collection;
21
import java.util.function.Function;
22

23
import net.automatalib.automaton.AutomatonCreator;
24
import net.automatalib.automaton.transducer.MealyMachine;
25
import net.automatalib.automaton.transducer.MutableMealyMachine;
26
import net.automatalib.automaton.transducer.impl.CompactMealy;
27
import net.automatalib.common.util.Pair;
28
import net.automatalib.exception.FormatException;
29
import net.automatalib.serialization.ModelDeserializer;
30
import org.checkerframework.checker.nullness.qual.Nullable;
31

32
/**
33
 * Parse a Mealy machine from an FSM source with straightforward edge semantics (as compared to
34
 * {@link FSM2MealyParserAlternating}).
35
 *
36
 * @param <I>
37
 *         the input type
38
 * @param <O>
39
 *         the output type
40
 * @param <A>
41
 *         the parsed automaton type
42
 */
43
public final class FSM2MealyParserIO<I, O, A extends MutableMealyMachine<Integer, I, ?, O>> extends AbstractFSM2MealyParser<I, O, A> {
44

45
    /**
46
     * Constructs a new FSM2MealyParserIO. Use one of the static parse() methods to actually parse an FSM source.
47
     *
48
     * @param targetInputs
49
     *         A collection containing the inputs which should constitute the input alphabet of the parsed automaton.
50
     *         If {@code null}, the inputs will be automatically gathered from the read FSM file.
51
     * @param inputParser
52
     *         the input parser.
53
     * @param outputParser
54
     *         the output parser (similar to {@code inputParser}).
55
     */
56
    private FSM2MealyParserIO(@Nullable Collection<? extends I> targetInputs,
57
                              Function<String, I> inputParser,
58
                              Function<String, O> outputParser,
59
                              AutomatonCreator<A, I> creator) {
60
        super(targetInputs, inputParser, outputParser, creator);
2✔
61
    }
2✔
62

63
    /**
64
     * Parse a transition.
65
     *
66
     * @throws FSMFormatException
67
     *         when the transition is illegal.
68
     * @throws IOException
69
     *         see {@link StreamTokenizer#nextToken()}.
70
     */
71
    @Override
72
    protected void parseTransition(StreamTokenizer streamTokenizer) throws IOException, FormatException {
73
        try {
74

75
            // check we will read a state index
76
            if (streamTokenizer.nextToken() != StreamTokenizer.TT_WORD) {
2✔
77
                throw new FSMFormatException(EXPECT_NUMBER, streamTokenizer);
×
78
            }
79

80
            // read the source state index
81
            int from = Integer.parseInt(streamTokenizer.sval);
2✔
82

83
            // check if such a state exists
84
            if (!getStates().isEmpty() && !getStates().contains(from)) {
2✔
85
                throw new FSMFormatException(String.format(NO_SUCH_STATE, from), streamTokenizer);
×
86
            }
87

88
            // check we will read a state index
89
            if (streamTokenizer.nextToken() != StreamTokenizer.TT_WORD) {
2✔
90
                throw new FSMFormatException(EXPECT_NUMBER, streamTokenizer);
×
91
            }
92

93
            // read the target state index
94
            int to = Integer.parseInt(streamTokenizer.sval);
2✔
95

96
            // check if such a state exists
97
            if (!getStates().isEmpty() && !getStates().contains(to)) {
2✔
98
                throw new FSMFormatException(String.format(NO_SUCH_STATE, to), streamTokenizer);
×
99
            }
100

101
            // check we will read an input edge label
102
            if (streamTokenizer.nextToken() != '"') {
2✔
103
                throw new FSMFormatException(EXPECT_STRING, streamTokenizer);
×
104
            }
105

106
            // read the input, and convert the input string to actual input
107
            final I input = getInputParser().apply(streamTokenizer.sval);
2✔
108

109
            // add it to the set of inputs
110
            getInputs().add(input);
2✔
111

112
            // check we will read an output edge label
113
            if (streamTokenizer.nextToken() != '"') {
2✔
114
                throw new FSMFormatException(EXPECT_STRING, streamTokenizer);
×
115
            }
116

117
            // read the output, and convert the output string to actual output
118
            final O output = getOutputParser().apply(streamTokenizer.sval);
2✔
119

120
            // create the Mealy machine transition
121
            final Pair<O, Integer> prev = getTransitions().put(Pair.of(from, input), Pair.of(output, to));
2✔
122

123
            // check for non-determinism
124
            if (prev != null) {
2✔
125
                throw new FSMFormatException(String.format(NON_DETERMINISM_DETECTED, prev), streamTokenizer);
×
126
            }
127
        } catch (NumberFormatException nfe) {
×
128
            throw new FSMFormatException(nfe, streamTokenizer);
×
129
        }
2✔
130
    }
2✔
131

132
    @Override
133
    protected void checkTransitions(StreamTokenizer streamTokenizer) {
134
        // Only if no states are defined we add all from the transitions we found.
135
        // This is necessary because states are not necessarily defined in FSMs.
136
        if (getStates().isEmpty()) {
2✔
NEW
137
            getStates().addAll(getTransitions().keySet().stream().map(Pair::getFirst).toList());
×
138
        }
139
    }
2✔
140

141
    /**
142
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
143
     * {@link CompactMealy}.
144
     *
145
     * @param edgeParser
146
     *         the transformer of String representatives to (same-typed) input/output symbols
147
     * @param <E>
148
     *         symbol type
149
     *
150
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
151
     */
152
    public static <E> ModelDeserializer<CompactMealy<E, E>> getParser(Function<String, E> edgeParser) {
153
        return getParser(edgeParser, edgeParser);
2✔
154
    }
155

156
    /**
157
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
158
     * {@link CompactMealy}.
159
     *
160
     * @param inputParser
161
     *         the transformer of String representatives to input alphabet symbols
162
     * @param outputParser
163
     *         the transformer of String representatives to output alphabet symbols
164
     * @param <I>
165
     *         input symbol type
166
     * @param <O>
167
     *         output symbol type
168
     *
169
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
170
     */
171
    public static <I, O> ModelDeserializer<CompactMealy<I, O>> getParser(Function<String, I> inputParser,
172
                                                                         Function<String, O> outputParser) {
173
        return getParser(null, inputParser, outputParser);
2✔
174
    }
175

176
    /**
177
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
178
     * {@link CompactMealy}.
179
     *
180
     * @param targetInputs
181
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
182
     * @param edgeParser
183
     *         the transformer of String representatives to (same-typed) input/output symbols
184
     * @param <E>
185
     *         symbol type
186
     *
187
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
188
     */
189
    public static <E> ModelDeserializer<CompactMealy<E, E>> getParser(@Nullable Collection<? extends E> targetInputs,
190
                                                                      Function<String, E> edgeParser) {
191
        return getParser(targetInputs, edgeParser, edgeParser);
2✔
192
    }
193

194
    /**
195
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
196
     * {@link CompactMealy}.
197
     *
198
     * @param targetInputs
199
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
200
     * @param inputParser
201
     *         the transformer of String representatives to input alphabet symbols
202
     * @param outputParser
203
     *         the transformer of String representatives to output alphabet symbols
204
     * @param <I>
205
     *         input symbol type
206
     * @param <O>
207
     *         output symbol type
208
     *
209
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
210
     */
211
    public static <I, O> ModelDeserializer<CompactMealy<I, O>> getParser(@Nullable Collection<? extends I> targetInputs,
212
                                                                         Function<String, I> inputParser,
213
                                                                         Function<String, O> outputParser) {
214
        return getParser(targetInputs, inputParser, outputParser, new CompactMealy.Creator<>());
2✔
215
    }
216

217
    /**
218
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a given
219
     * {@link MutableMealyMachine}.
220
     *
221
     * @param targetInputs
222
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
223
     * @param inputParser
224
     *         the transformer of String representatives to input alphabet symbols
225
     * @param outputParser
226
     *         the transformer of String representatives to output alphabet symbols
227
     * @param creator
228
     *         the creator to construct the concrete automaton instance
229
     * @param <I>
230
     *         input symbol type
231
     * @param <O>
232
     *         output symbol type
233
     * @param <A>
234
     *         (concrete) automaton type
235
     *
236
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
237
     */
238
    public static <I, O, A extends MutableMealyMachine<Integer, I, ?, O>> ModelDeserializer<A> getParser(@Nullable Collection<? extends I> targetInputs,
239
                                                                                                         Function<String, I> inputParser,
240
                                                                                                         Function<String, O> outputParser,
241
                                                                                                         AutomatonCreator<A, I> creator) {
242
        return new FSM2MealyParserIO<>(targetInputs, inputParser, outputParser, creator);
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