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

LearnLib / automatalib / 10220057657

02 Aug 2024 06:06PM UTC coverage: 90.366% (+0.3%) from 90.072%
10220057657

push

github

mtf90
overhaul serizalition code

* unify access to Input(De)Serializers behind facades to leverage the default methods for various input/output channels
* drop implicit buffering/decompressing as this should be decided where the stream are constructed (user-land)
* remove/cleanup the (now) unused code

300 of 349 new or added lines in 33 files covered. (85.96%)

9 existing lines in 3 files now uncovered.

15927 of 17625 relevant lines covered (90.37%)

1.67 hits per line

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

98.78
/serialization/taf/src/main/java/net/automatalib/serialization/taf/writer/TAFConcreteWriter.java
1
/* Copyright (C) 2013-2024 TU Dortmund University
2
 * This file is part of AutomataLib, http://www.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.taf.writer;
17

18
import java.io.IOException;
19
import java.io.OutputStream;
20
import java.io.Writer;
21
import java.util.ArrayList;
22
import java.util.Collection;
23
import java.util.HashMap;
24
import java.util.HashSet;
25
import java.util.List;
26
import java.util.Map;
27
import java.util.Objects;
28
import java.util.Set;
29
import java.util.function.BiFunction;
30
import java.util.regex.Pattern;
31

32
import net.automatalib.alphabet.Alphabet;
33
import net.automatalib.automaton.UniversalDeterministicAutomaton;
34
import net.automatalib.automaton.concept.StateIDs;
35
import net.automatalib.common.util.HashUtil;
36
import net.automatalib.common.util.IOUtil;
37
import net.automatalib.common.util.Pair;
38
import net.automatalib.common.util.string.StringUtil;
39
import net.automatalib.serialization.InputModelSerializer;
40
import org.checkerframework.checker.nullness.qual.Nullable;
41

42
class TAFConcreteWriter<S, I, T, TP, A extends UniversalDeterministicAutomaton<S, I, T, ?, TP>>
43
        implements InputModelSerializer<I, A> {
44

45
    private static final Pattern ID_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*");
2✔
46

47
    private final String type;
48
    private final BiFunction<A, S, ? extends Collection<? extends String>> spExtractor;
49

50
    private int indent;
51

52
    TAFConcreteWriter(String type, BiFunction<A, S, Collection<String>> spExtractor) {
2✔
53
        this.type = type;
2✔
54
        this.spExtractor = spExtractor;
2✔
55
    }
2✔
56

57
    @Override
58
    public void writeModel(OutputStream os, A automaton, Alphabet<I> inputs) throws IOException {
59

60
        try (Writer out = IOUtil.asNonClosingUTF8Writer(os)) {
2✔
61
            begin(out, type, inputs);
2✔
62

63
            S init = automaton.getInitialState();
2✔
64
            StateIDs<S> ids = automaton.stateIDs();
2✔
65
            for (S state : automaton) {
2✔
66
                Set<String> options = new HashSet<>(spExtractor.apply(automaton, state));
2✔
67
                if (Objects.equals(init, state)) {
2✔
68
                    options.add("initial");
2✔
69
                }
70
                int id = ids.getStateId(state);
2✔
71
                String name = "s" + id;
2✔
72

73
                beginState(out, name, options);
2✔
74

75
                final Map<Pair<S, TP>, List<I>> groupedTransitions = new HashMap<>(HashUtil.capacity(inputs.size()));
2✔
76
                for (I i : inputs) {
2✔
77
                    final T t = automaton.getTransition(state, i);
2✔
78

79
                    if (t != null) {
2✔
80
                        final S succ = automaton.getSuccessor(t);
2✔
81
                        final TP tp = automaton.getTransitionProperty(t);
2✔
82
                        final Pair<S, TP> key = Pair.of(succ, tp);
2✔
83

84
                        groupedTransitions.computeIfAbsent(key, k -> new ArrayList<>()).add(i);
2✔
85
                    }
86
                }
2✔
87

88
                for (Map.Entry<Pair<S, TP>, List<I>> group : groupedTransitions.entrySet()) {
2✔
89
                    S tgt = group.getKey().getFirst();
2✔
90
                    int tgtId = ids.getStateId(tgt);
2✔
91
                    String tgtName = "s" + tgtId;
2✔
92
                    TP transProp = group.getKey().getSecond();
2✔
93
                    writeTransition(out, group.getValue(), tgtName, transProp);
2✔
94
                }
2✔
95

96
                endState(out);
2✔
97
            }
2✔
98

99
            end(out);
2✔
100
        }
101
    }
2✔
102

103
    private void begin(Writer out, String type, Collection<?> inputs) throws IOException {
104
        writeIndent(out);
2✔
105
        out.append(type).append(' ');
2✔
106
        writeStringCollection(out, inputs);
2✔
107
        out.append(" {").append(System.lineSeparator());
2✔
108
        indent++;
2✔
109
    }
2✔
110

111
    private void beginState(Writer out, String name, Set<String> options) throws IOException {
112
        writeIndent(out);
2✔
113
        out.append(name).append(' ');
2✔
114
        if (!options.isEmpty()) {
2✔
115
            out.append(options.toString()).append(' ');
2✔
116
        }
117
        out.append('{').append(System.lineSeparator());
2✔
118
        indent++;
2✔
119
    }
2✔
120

121
    private void writeTransition(Writer out, Collection<?> symbols, String target, @Nullable Object output)
122
            throws IOException {
123
        writeIndent(out);
2✔
124
        writeStringCollection(out, symbols);
2✔
125
        if (output != null) {
2✔
126
            out.append(" / ").append(StringUtil.enquoteIfNecessary(output.toString()));
2✔
127
        }
128
        out.append(" -> ").append(target).append(System.lineSeparator());
2✔
129
    }
2✔
130

131
    private void endState(Writer out) throws IOException {
132
        --indent;
2✔
133
        writeIndent(out);
2✔
134
        out.append('}').append(System.lineSeparator());
2✔
135
    }
2✔
136

137
    private void end(Writer out) throws IOException {
138
        --indent;
2✔
139
        writeIndent(out);
2✔
140
        out.append('}').append(System.lineSeparator());
2✔
141
    }
2✔
142

143
    private void writeIndent(Writer out) throws IOException {
144
        for (int i = 0; i < indent; i++) {
2✔
145
            out.append('\t');
2✔
146
        }
147
    }
2✔
148

149
    private void writeStringCollection(Writer out, Collection<?> symbols) throws IOException {
150
        if (symbols.isEmpty()) {
2✔
NEW
151
            out.append("{}");
×
152
        } else if (symbols.size() == 1) {
2✔
153
            Object sym = symbols.iterator().next();
2✔
154
            StringUtil.enquoteIfNecessary(String.valueOf(sym), out, ID_PATTERN);
2✔
155
        } else {
2✔
156
            out.append('{');
2✔
157
            boolean first = true;
2✔
158
            for (Object sym : symbols) {
2✔
159
                if (first) {
2✔
160
                    first = false;
2✔
161
                } else {
162
                    out.append(',');
2✔
163
                }
164
                StringUtil.enquoteIfNecessary(String.valueOf(sym), out, ID_PATTERN);
2✔
165
            }
2✔
166
            out.append('}');
2✔
167
        }
168
    }
2✔
169
}
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