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

LearnLib / automatalib / 13138848026

04 Feb 2025 02:53PM UTC coverage: 92.108% (+2.2%) from 89.877%
13138848026

push

github

mtf90
[maven-release-plugin] prepare release automatalib-0.12.0

16609 of 18032 relevant lines covered (92.11%)

1.7 hits per line

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

97.18
/serialization/taf/src/main/java/net/automatalib/serialization/taf/parser/AbstractTAFBuilder.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.taf.parser;
17

18
import java.util.ArrayList;
19
import java.util.Collection;
20
import java.util.HashMap;
21
import java.util.HashSet;
22
import java.util.List;
23
import java.util.Map;
24
import java.util.Objects;
25
import java.util.Set;
26
import java.util.regex.Pattern;
27

28
import net.automatalib.alphabet.Alphabet;
29
import net.automatalib.automaton.MutableDeterministic;
30
import net.automatalib.common.util.string.StringUtil;
31

32
@SuppressWarnings("nullness")
33
abstract class AbstractTAFBuilder<S, T, SP, TP, M extends MutableDeterministic<S, String, T, SP, TP>>
34
        implements TAFBuilder {
35

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

38
    private final InternalTAFParser parser;
39
    private final Map<String, S> stateMap = new HashMap<>();
2✔
40
    private final Set<String> declaredStates = new HashSet<>();
2✔
41
    protected M automaton;
42
    private Alphabet<String> alphabet;
43

44
    AbstractTAFBuilder(InternalTAFParser parser) {
2✔
45
        this.parser = parser;
2✔
46
    }
2✔
47

48
    @Override
49
    public void init(Alphabet<String> alphabet) {
50
        if (automaton != null) {
2✔
51
            throw new IllegalStateException();
×
52
        }
53
        automaton = createAutomaton(alphabet);
2✔
54
        this.alphabet = alphabet;
2✔
55
    }
2✔
56

57
    @Override
58
    public void declareState(String identifier, Set<String> options) {
59
        if (!declaredStates.add(identifier)) {
2✔
60
            error("State {0} declared twice, ignoring properties ...", identifier);
2✔
61
            return;
2✔
62
        }
63

64
        boolean init = options.remove("initial") | options.remove("init");
2✔
65
        if (init && automaton.getInitialState() != null) {
2✔
66
            error("Duplicate initial state {0}, ignoring property ...", identifier);
2✔
67
            init = false;
2✔
68
        }
69

70
        S state = stateMap.get(identifier);
2✔
71
        SP property = getStateProperty(options);
2✔
72
        if (state == null) {
2✔
73
            state = init ? automaton.addInitialState(property) : automaton.addState(property);
2✔
74
            stateMap.put(identifier, state);
2✔
75
        } else {
76
            automaton.setStateProperty(state, property);
2✔
77
            if (init) {
2✔
78
                automaton.setInitialState(state);
2✔
79
            }
80
        }
81

82
        if (!options.isEmpty()) {
2✔
83
            warning("Unrecognized options for state {0}: {1}", identifier, options);
2✔
84
        }
85
    }
2✔
86

87
    @Override
88
    public M finish() {
89
        if (automaton == null) {
2✔
90
            throw new IllegalStateException("Must call one of the parse methods first");
×
91
        }
92

93
        stateMap.clear();
2✔
94
        declaredStates.clear();
2✔
95
        M result = automaton;
2✔
96
        automaton = null;
2✔
97
        alphabet = null;
2✔
98
        return result;
2✔
99
    }
100

101
    protected void error(String msgFmt, Object... args) {
102
        parser.error(msgFmt, args);
2✔
103
    }
2✔
104

105
    protected abstract M createAutomaton(Alphabet<String> stringAlphabet);
106

107
    protected abstract SP getStateProperty(Set<String> options);
108

109
    protected void warning(String msgFmt, Object... args) {
110
        parser.warning(msgFmt, args);
2✔
111
    }
2✔
112

113
    protected void doAddTransitions(String source, Collection<String> symbols, String target, TP transProperty) {
114
        S src = lookupState(source);
2✔
115
        S tgt = lookupState(target);
2✔
116
        List<String> invalidSymbols = new ArrayList<>();
2✔
117
        for (String input : symbols) {
2✔
118
            if (!alphabet.containsSymbol(input)) {
2✔
119
                invalidSymbols.add(StringUtil.enquoteIfNecessary(input, ID_PATTERN));
2✔
120
                continue;
2✔
121
            }
122
            T exTrans = automaton.getTransition(src, input);
2✔
123
            if (exTrans != null) {
2✔
124
                if (!Objects.equals(tgt, automaton.getSuccessor(exTrans))) {
2✔
125
                    error("Duplicate transition from {0} on input {1} to differing target {2} would introduce non-determinism",
2✔
126
                          source,
127
                          StringUtil.enquoteIfNecessary(input, ID_PATTERN),
2✔
128
                          tgt);
129
                } else if (!Objects.equals(transProperty, automaton.getTransitionProperty(exTrans))) {
2✔
130
                    error("Duplicate transition from {0} on input {1} to {2} with differing property '{3}' would introduce non-determinism",
2✔
131
                          source,
132
                          StringUtil.enquoteIfNecessary(input, ID_PATTERN),
2✔
133
                          tgt,
134
                          transProperty);
135
                }
136
            } else {
137
                automaton.addTransition(src, input, tgt, transProperty);
2✔
138
            }
139
        }
2✔
140
        if (!invalidSymbols.isEmpty()) {
2✔
141
            error("Invalid symbols for transition from {0} to {1}: {2}", source, target, invalidSymbols);
2✔
142
        }
143
    }
2✔
144

145
    protected S lookupState(String identifier) {
146
        return stateMap.computeIfAbsent(identifier, k -> automaton.addState());
2✔
147
    }
148

149
    protected void doAddWildcardTransitions(String source, String target, TP transProperty) {
150
        S src = lookupState(source);
2✔
151
        S tgt = lookupState(target);
2✔
152
        for (String input : alphabet) {
2✔
153
            T exTrans = automaton.getTransition(src, input);
2✔
154
            if (exTrans == null) {
2✔
155
                automaton.addTransition(src, input, tgt, transProperty);
2✔
156
            }
157
        }
2✔
158
    }
2✔
159

160
    protected Alphabet<String> getAlphabet() {
161
        return alphabet;
2✔
162
    }
163
}
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