Skip to content

Commit a721194

Browse files
committed
feat: Add StringTemplate
1 parent 0eec40e commit a721194

File tree

7 files changed

+151
-35
lines changed

7 files changed

+151
-35
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2019-present HiveMQ GmbH
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+
17+
package com.hivemq.common.i18n;
18+
19+
import freemarker.template.Configuration;
20+
import freemarker.template.Template;
21+
import org.jetbrains.annotations.NotNull;
22+
23+
import java.io.StringWriter;
24+
import java.nio.charset.StandardCharsets;
25+
import java.util.Locale;
26+
import java.util.Map;
27+
28+
public final class StringTemplate {
29+
private final static @NotNull Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);
30+
31+
static {
32+
CONFIGURATION.setDefaultEncoding(StandardCharsets.UTF_8.name());
33+
CONFIGURATION.setLocale(Locale.US);
34+
}
35+
36+
private StringTemplate() {
37+
}
38+
39+
public static @NotNull String format(
40+
final @NotNull String stringTemplate,
41+
final @NotNull Map<String, Object> arguments) {
42+
try (final StringWriter stringWriter = new StringWriter();) {
43+
final Template template = new Template(stringTemplate, stringTemplate, CONFIGURATION);
44+
template.process(arguments, stringWriter);
45+
return stringWriter.toString();
46+
} catch (final Exception e) {
47+
return e.getMessage();
48+
}
49+
}
50+
}

hivemq-edge/src/main/java/com/hivemq/protocols/fsm/I18nProtocolAdapterMessage.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323
import java.util.Map;
2424

2525
public enum I18nProtocolAdapterMessage implements I18nError {
26-
FSM_TRANSITION_FAILURE_TRANSITIONED_FROM_STATE_TO_ERROR,
2726
FSM_TRANSITION_FAILURE_UNABLE_TO_TRANSITION_FROM_STATE_TO_STATE,
28-
FSM_TRANSITION_SUCCESS_STATE_IS_NOT_TRANSITIONED,
27+
FSM_TRANSITION_SUCCESS_STATE_IS_UNCHANGED,
2928
FSM_TRANSITION_SUCCESS_TRANSITIONED_FROM_STATE_TO_STATE,
3029
;
3130

hivemq-edge/src/main/java/com/hivemq/protocols/fsm/ProtocolAdapterInstance.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,13 @@ public ProtocolAdapterInstance() {
3737

3838
public synchronized @NotNull ProtocolAdapterTransitionResponse transitionTo(final @NotNull ProtocolAdapterState newState) {
3939
final ProtocolAdapterTransitionResponse response = state.transition(newState, this);
40-
if (response.status() == ProtocolAdapterTransitionStatus.Success) {
41-
this.state = response.state();
42-
} else {
43-
// Handle error (logging, throwing exception, etc.)
44-
switch (response.status()) {
45-
default -> {
46-
// TODO
47-
}
40+
this.state = response.toState();
41+
switch (response.status()) {
42+
case Success -> {
43+
}
44+
case Failure -> {
45+
}
46+
case NotChanged -> {
4847
}
4948
}
5049
return response;

hivemq-edge/src/main/java/com/hivemq/protocols/fsm/ProtocolAdapterState.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ public enum ProtocolAdapterState {
4141
final ProtocolAdapterState fromState = ProtocolAdapterState.Starting;
4242
return switch (toState) {
4343
case Starting -> ProtocolAdapterTransitionResponse.notChanged(fromState);
44-
case Started -> ProtocolAdapterTransitionResponse.success(fromState, toState);
45-
case Stopping, Stopped -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
46-
default -> ProtocolAdapterTransitionResponse.failure(fromState);
44+
case Started, Stopping, Error -> ProtocolAdapterTransitionResponse.success(fromState, toState);
45+
default -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
4746
};
4847
}
4948

@@ -52,10 +51,9 @@ public enum ProtocolAdapterState {
5251
final @NotNull ProtocolAdapterInstance instance) {
5352
final ProtocolAdapterState fromState = ProtocolAdapterState.Started;
5453
return switch (toState) {
55-
case Starting, Stopped -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
5654
case Started -> ProtocolAdapterTransitionResponse.notChanged(fromState);
57-
case Stopping -> ProtocolAdapterTransitionResponse.success(fromState, toState);
58-
default -> ProtocolAdapterTransitionResponse.failure(fromState);
55+
case Stopping, Error -> ProtocolAdapterTransitionResponse.success(fromState, toState);
56+
default -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
5957
};
6058
}
6159

@@ -64,10 +62,9 @@ public enum ProtocolAdapterState {
6462
final @NotNull ProtocolAdapterInstance instance) {
6563
final ProtocolAdapterState fromState = ProtocolAdapterState.Stopping;
6664
return switch (toState) {
67-
case Starting, Started -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
6865
case Stopping -> ProtocolAdapterTransitionResponse.notChanged(fromState);
69-
case Stopped -> ProtocolAdapterTransitionResponse.success(fromState, toState);
70-
default -> ProtocolAdapterTransitionResponse.failure(fromState);
66+
case Stopped, Error -> ProtocolAdapterTransitionResponse.success(fromState, toState);
67+
default -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
7168
};
7269
}
7370

@@ -77,9 +74,8 @@ public enum ProtocolAdapterState {
7774
final ProtocolAdapterState fromState = ProtocolAdapterState.Stopped;
7875
return switch (toState) {
7976
case Starting -> ProtocolAdapterTransitionResponse.success(fromState, toState);
80-
case Started, Stopping -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
8177
case Stopped -> ProtocolAdapterTransitionResponse.notChanged(fromState);
82-
case Error -> ProtocolAdapterTransitionResponse.failure(fromState);
78+
default -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
8379
};
8480
}
8581

@@ -89,8 +85,8 @@ public enum ProtocolAdapterState {
8985
final ProtocolAdapterState fromState = ProtocolAdapterState.Error;
9086
return switch (toState) {
9187
case Starting -> ProtocolAdapterTransitionResponse.success(fromState, toState);
92-
case Started, Stopping, Stopped -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
93-
default -> ProtocolAdapterTransitionResponse.notChanged(toState);
88+
case Error -> ProtocolAdapterTransitionResponse.notChanged(fromState);
89+
default -> ProtocolAdapterTransitionResponse.failure(fromState, toState);
9490
};
9591
}
9692

hivemq-edge/src/main/java/com/hivemq/protocols/fsm/ProtocolAdapterTransitionResponse.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,7 @@ public static ProtocolAdapterTransitionResponse notChanged(final @NotNull Protoc
4545
return new ProtocolAdapterTransitionResponse(state,
4646
state,
4747
ProtocolAdapterTransitionStatus.NotChanged,
48-
I18nProtocolAdapterMessage.FSM_TRANSITION_SUCCESS_STATE_IS_NOT_TRANSITIONED.get(Map.of(STATE,
49-
state.name())),
50-
null);
51-
}
52-
53-
public static ProtocolAdapterTransitionResponse failure(final @NotNull ProtocolAdapterState state) {
54-
return new ProtocolAdapterTransitionResponse(state,
55-
ProtocolAdapterState.Error,
56-
ProtocolAdapterTransitionStatus.Failure,
57-
I18nProtocolAdapterMessage.FSM_TRANSITION_FAILURE_TRANSITIONED_FROM_STATE_TO_ERROR.get(Map.of(STATE,
48+
I18nProtocolAdapterMessage.FSM_TRANSITION_SUCCESS_STATE_IS_UNCHANGED.get(Map.of(STATE,
5849
state.name())),
5950
null);
6051
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
fsm.transition.failure.unable.to.transition.from.state.to.state=Unable to transition from ${fromState} to ${toState}.
2-
fsm.transition.failure.transitioned.from.state.to.error=Transitioned from ${state} to Error.
3-
fsm.transition.success.state.is.not.transitioned=${state} is not transitioned.
2+
fsm.transition.success.state.is.unchanged=${state} is unchanged.
43
fsm.transition.success.transitioned.from.state.to.state=Transitioned from ${fromState} to ${toState}.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2019-present HiveMQ GmbH
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+
17+
package com.hivemq.protocols.fsm;
18+
19+
import com.hivemq.common.i18n.StringTemplate;
20+
import org.jetbrains.annotations.NotNull;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.ExtendWith;
23+
import org.mockito.Mock;
24+
import org.mockito.junit.jupiter.MockitoExtension;
25+
import org.mockito.junit.jupiter.MockitoSettings;
26+
import org.mockito.quality.Strictness;
27+
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.Set;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
@ExtendWith(MockitoExtension.class)
35+
@MockitoSettings(strictness = Strictness.LENIENT)
36+
public class ProtocolAdapterStateTest {
37+
private static final Map<ProtocolAdapterState, Set<ProtocolAdapterState>> PROTOCOL_ADAPTER_STATE_MAP_MAP = Map.of(
38+
ProtocolAdapterState.Starting,
39+
Set.of(ProtocolAdapterState.Started, ProtocolAdapterState.Stopping, ProtocolAdapterState.Error),
40+
ProtocolAdapterState.Started,
41+
Set.of(ProtocolAdapterState.Stopping, ProtocolAdapterState.Error),
42+
ProtocolAdapterState.Stopping,
43+
Set.of(ProtocolAdapterState.Stopped, ProtocolAdapterState.Error),
44+
ProtocolAdapterState.Stopped,
45+
Set.of(ProtocolAdapterState.Starting),
46+
ProtocolAdapterState.Error,
47+
Set.of(ProtocolAdapterState.Starting));
48+
@Mock
49+
private @NotNull ProtocolAdapterInstance protocolAdapterInstance;
50+
51+
@Test
52+
public void whenEverythingWorks_thenTransitionShouldWork() {
53+
final List<ProtocolAdapterState> states = List.of(ProtocolAdapterState.values());
54+
states.forEach(fromState -> {
55+
final Set<ProtocolAdapterState> possibleToStates = PROTOCOL_ADAPTER_STATE_MAP_MAP.get(fromState);
56+
assertThat(possibleToStates).isNotNull();
57+
states.forEach(toState -> {
58+
final ProtocolAdapterTransitionResponse response =
59+
fromState.transition(toState, protocolAdapterInstance);
60+
switch (response.status()) {
61+
case Success -> {
62+
assertThat(possibleToStates).contains(toState);
63+
assertThat(response.message()).isEqualTo(StringTemplate.format(
64+
"Transitioned from ${fromState} to ${toState}.",
65+
Map.of("fromState", fromState, "toState", toState)));
66+
}
67+
case Failure -> {
68+
assertThat(possibleToStates).doesNotContain(toState);
69+
assertThat(response.message()).isEqualTo(StringTemplate.format(
70+
"Unable to transition from ${fromState} to ${toState}.",
71+
Map.of("fromState", fromState, "toState", toState)));
72+
}
73+
case NotChanged -> {
74+
assertThat(toState).isEqualTo(fromState);
75+
assertThat(response.message()).isEqualTo(StringTemplate.format("${state} is unchanged.",
76+
Map.of("state", fromState)));
77+
}
78+
}
79+
});
80+
});
81+
}
82+
}

0 commit comments

Comments
 (0)