Skip to content

Commit adc2d1a

Browse files
committed
refactor Mapper interface and add semantic refinements
- moved #pre and #post methods from the SULMapper to the generic Mapper interface to allow implementing stateful (generic) mappers. - added {A,}SynchronuousMapper markup interfaces for refining the contract whether the Mapper is utilized in per-symbol transformation manner or in a per-query way.
1 parent e4a18ae commit adc2d1a

3 files changed

Lines changed: 71 additions & 34 deletions

File tree

api/src/main/java/de/learnlib/api/Mapper.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@
3838
*/
3939
public interface Mapper<AI, AO, CI, CO> {
4040

41+
/**
42+
* Method that is invoked before any translation steps on a word are performed. Usually left un-implemented for
43+
* stateless mappers.
44+
*/
45+
default void pre() {}
46+
47+
/**
48+
* Method that is invoked after all translation steps on a word are performed. Usually left un-implemented for
49+
* stateless mappers.
50+
*/
51+
default void post() {}
52+
4153
/**
4254
* Method that maps an abstract input to a corresponding concrete input.
4355
*
@@ -57,4 +69,47 @@ public interface Mapper<AI, AO, CI, CO> {
5769
* @return the abstract output
5870
*/
5971
AO mapOutput(CO concreteOutput);
72+
73+
/**
74+
* A mapper refinement to establish the contract of a synchronized, symbol-wise translation of input words for
75+
* reactive systems. This means, after each call to {@link #mapInput(Object)} the next call on {@code this} object
76+
* will be {@link #mapOutput(Object)} which is passed the immediate answer to the previously mapped input.
77+
*
78+
* @param <AI>
79+
* abstract input symbol type.
80+
* @param <AO>
81+
* abstract output symbol type.
82+
* @param <CI>
83+
* concrete input symbol type.
84+
* @param <CO>
85+
* concrete output symbol type.
86+
*
87+
* @author frohme
88+
* @see AsynchronousMapper
89+
*/
90+
interface SynchronousMapper<AI, AO, CI, CO> extends Mapper<AI, AO, CI, CO> {}
91+
92+
/**
93+
* A mapper refinement to establish the contract of a asynchronous, query-wise translation of input words. This
94+
* means, for a sequence of input symbols, {@link #mapInput(Object)} may be called multiple times before any call to
95+
* {@link #mapOutput(Object)} occurs.
96+
* <p>
97+
* Especially in the context of translating {@link de.learnlib.api.query.Query queries} for mealy machines, which
98+
* support the concept of un-answered prefixes (combined with answered suffixes) this means, the number of {@link
99+
* #mapInput(Object)} invocations may be larger than the size of the output word passed to the {@link
100+
* #mapOutput(Object)} function.
101+
*
102+
* @param <AI>
103+
* abstract input symbol type.
104+
* @param <AO>
105+
* abstract output symbol type.
106+
* @param <CI>
107+
* concrete input symbol type.
108+
* @param <CO>
109+
* concrete output symbol type.
110+
*
111+
* @author frohme
112+
* @see SynchronousMapper
113+
*/
114+
interface AsynchronousMapper<AI, AO, CI, CO> extends Mapper<AI, AO, CI, CO> {}
60115
}

drivers/mapper/src/main/java/de/learnlib/mapper/api/SULMapper.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.annotation.Nonnull;
2121

2222
import de.learnlib.api.Mapper;
23+
import de.learnlib.api.Mapper.SynchronousMapper;
2324
import de.learnlib.api.SUL;
2425
import de.learnlib.api.exception.SULException;
2526
import de.learnlib.mapper.SULMappers;
@@ -49,17 +50,7 @@
4950
*
5051
* @author Malte Isberner
5152
*/
52-
public interface SULMapper<AI, AO, CI, CO> extends Mapper<AI, AO, CI, CO> {
53-
54-
/**
55-
* Method that is invoked before any translation steps on a word are performed.
56-
*/
57-
void pre();
58-
59-
/**
60-
* Method that is invoked after all translation steps on a word are performed.
61-
*/
62-
void post();
53+
public interface SULMapper<AI, AO, CI, CO> extends SynchronousMapper<AI, AO, CI, CO> {
6354

6455
/**
6556
* Checks whether it is possible to {@link #fork() fork} this mapper.

oracles/membership-oracles/src/main/java/de/learnlib/oracle/membership/MappedOracle.java

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,10 @@
1515
*/
1616
package de.learnlib.oracle.membership;
1717

18-
import java.util.ArrayList;
19-
import java.util.Collection;
20-
import java.util.List;
21-
22-
import de.learnlib.api.Mapper;
23-
import de.learnlib.api.oracle.MembershipOracle;
24-
import de.learnlib.api.query.DefaultQuery;
25-
import de.learnlib.api.query.Query;
18+
import de.learnlib.api.Mapper.AsynchronousMapper;
19+
import de.learnlib.api.oracle.QueryAnswerer;
20+
import de.learnlib.api.oracle.SingleQueryOracle;
21+
import net.automatalib.words.Word;
2622

2723
/**
2824
* A utility class that allows to lift a membership oracle of concrete input/output symbols to a membership oracle of
@@ -39,31 +35,26 @@
3935
*
4036
* @author frohme
4137
*/
42-
public class MappedOracle<AI, AO, CI, CO> implements MembershipOracle<AI, AO> {
38+
public class MappedOracle<AI, AO, CI, CO> implements SingleQueryOracle<AI, AO> {
4339

44-
private final MembershipOracle<CI, CO> delegate;
40+
private final QueryAnswerer<CI, CO> delegate;
4541

46-
private final Mapper<AI, AO, CI, CO> mapper;
42+
private final AsynchronousMapper<AI, AO, CI, CO> mapper;
4743

48-
public MappedOracle(MembershipOracle<CI, CO> delegate, Mapper<AI, AO, CI, CO> mapper) {
44+
public MappedOracle(QueryAnswerer<CI, CO> delegate, AsynchronousMapper<AI, AO, CI, CO> mapper) {
4945
this.delegate = delegate;
5046
this.mapper = mapper;
5147
}
5248

5349
@Override
54-
public void processQueries(Collection<? extends Query<AI, AO>> queries) {
55-
final List<Query<AI, AO>> orderedQueries = new ArrayList<>(queries);
56-
final List<DefaultQuery<CI, CO>> mappedQueries = new ArrayList<>(queries.size());
50+
public AO answerQuery(Word<AI> prefix, Word<AI> suffix) {
51+
mapper.pre();
5752

58-
for (final Query<AI, AO> q : orderedQueries) {
59-
mappedQueries.add(new DefaultQuery<>(q.getPrefix().transform(mapper::mapInput),
60-
q.getSuffix().transform(mapper::mapInput)));
61-
}
53+
final CO output = delegate.answerQuery(prefix.transform(mapper::mapInput), suffix.transform(mapper::mapInput));
54+
final AO result = mapper.mapOutput(output);
6255

63-
this.delegate.processQueries(mappedQueries);
56+
mapper.post();
6457

65-
for (int i = 0; i < orderedQueries.size(); i++) {
66-
orderedQueries.get(i).answer(mapper.mapOutput(mappedQueries.get(i).getOutput()));
67-
}
58+
return result;
6859
}
6960
}

0 commit comments

Comments
 (0)