Skip to content

Commit

Permalink
feat: static jps and other replies (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
mghilardelli authored Jul 19, 2024
1 parent b2d2f36 commit 92aa3d9
Show file tree
Hide file tree
Showing 17 changed files with 7,803 additions and 173 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
if: github.ref == 'refs/heads/main'
env:
IMAGE_ID: ghcr.io/${{ github.repository }}/playground-backend
VERSION: SNAPSHOT
VERSION: main
run: |
# Convert to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
public class MessageListener {

@Bean
public Function<Message<String>, Message<String>> boardToGround() {
public Function<Message<String>, Message<String>> boardToGround(SferaHandler sferaHandler) {
return message -> {
SferaHandler sferaHandler = new SferaHandler(message.getHeaders());
String respone = sferaHandler.boardToGround(message.getPayload());
return MessageBuilder.withPayload(respone).setHeader(BinderHeaders.TARGET_DESTINATION, sferaHandler.replyTopic()).build();
String respone = sferaHandler.boardToGround(message);
if (respone == null) {
return null;
}
return MessageBuilder.withPayload(respone).setHeader(BinderHeaders.TARGET_DESTINATION, sferaHandler.replyTopic).build();
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,41 @@
import static ch.sbb.playgroundbackend.helper.XmlHelper.xmlToObject;

import com.solace.spring.cloud.stream.binder.messaging.SolaceHeaders;
import generated.G2BError;
import generated.G2BMessageResponse;
import generated.G2BReplyPayload;
import generated.MessageHeader;
import generated.Recipient;
import generated.SFERAB2GRequestMessage;
import generated.SFERAG2BReplyMessage;
import generated.Sender;
import jakarta.xml.bind.JAXBException;
import java.io.IOException;
import java.time.Instant;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
public class SferaHandler {

private static final Logger log = LoggerFactory.getLogger(SferaHandler.class);
private static final String SFERA_VERSION = "2.01";
private static final String SOURCE_DEVICE = "TMS";
private static final String SENDER = "0085";

private final String companyCode;
private final String trainIdentifier;
private final String clientId;
private final StaticSferaService staticSferaService;

public SferaHandler(MessageHeaders messageHeaders) {
String topic = messageHeaders.get(SolaceHeaders.DESTINATION).toString();
String[] topicParts = topic.split("/");
if (topicParts.length != 6) {
log.error("wrong topic format topic={}", topic);
}
this.companyCode = topicParts[3];
this.trainIdentifier = topicParts[4];
this.clientId = topicParts[5];
}
public String replyTopic;

public MessageHeader header(String correlationId) {
MessageHeader responseHeader = new MessageHeader();
responseHeader.setSFERAVersion(SFERA_VERSION);
responseHeader.setMessageID(UUID.randomUUID().toString());
responseHeader.setTimestamp(Instant.now());
responseHeader.setSourceDevice(SOURCE_DEVICE);
responseHeader.setCorrelationID(correlationId);

Recipient recipient = new Recipient();
recipient.setValue(companyCode);
responseHeader.setRecipient(recipient);
Sender sender = new Sender();
sender.setValue(SENDER);
responseHeader.setSender(sender);
return responseHeader;
public SferaHandler(StaticSferaService staticSferaService) {
this.staticSferaService = staticSferaService;
}

public String boardToGround(String xmlPayload) {
SFERAB2GRequestMessage sferab2GRequestMessage;
public String boardToGround(Message<String> message) {
String inputTopic = message.getHeaders().get(SolaceHeaders.DESTINATION).toString();
SFERAG2BReplyMessage replyMessage;

this.replyTopic = replyTopic(inputTopic);

SFERAB2GRequestMessage sferab2GRequestMessage;
try {
sferab2GRequestMessage = xmlToObject(xmlPayload, SFERAB2GRequestMessage.class);
SferaSession session = new SferaSession();
log.info("B2G request received companyCode={} trainIdentifier={} clientId={}", companyCode, trainIdentifier, clientId);
replyMessage = session.request(sferab2GRequestMessage);
replyMessage.setMessageHeader(header(sferab2GRequestMessage.getMessageHeader().getMessageID()));
} catch (JAXBException | IOException e) {
sferab2GRequestMessage = xmlToObject(message.getPayload(), SFERAB2GRequestMessage.class);
log.info("B2G request received");
replyMessage = request(sferab2GRequestMessage);
} catch (JAXBException e) {
log.error("Could not map xml to object", e);
replyMessage = invalidXmlError();
replyMessage = staticSferaService.invalidXmlError();
}
try {
return objectToXml(replyMessage);
Expand All @@ -80,32 +48,62 @@ public String boardToGround(String xmlPayload) {
}
}

private SFERAG2BReplyMessage invalidXmlError() {
G2BError error = new G2BError();
error.setErrorCode("13");
error.setAdditionalInfo("XML Schema Violation");
return errorReply(error);
}
private SFERAG2BReplyMessage request(SFERAB2GRequestMessage requestMessage) {

private SFERAG2BReplyMessage notImplementedError() {
G2BError error = new G2BError();
error.setErrorCode("99");
error.setAdditionalInfo("Not implemented yet!");
return errorReply(error);
if (requestMessage.getHandshakeRequest() != null) {
log.info("Send handshakeAck");
return staticSferaService.handshake();
// or HandshakeReject
// or Error
} else if (requestMessage.getB2GRequest() != null) {
return b2gRequest(requestMessage);
}
log.info("Send insufficient data");
return staticSferaService.insufficientData();
}

private SFERAG2BReplyMessage errorReply(G2BError error) {
SFERAG2BReplyMessage replyMessage = new SFERAG2BReplyMessage();
G2BReplyPayload replyPayload = new G2BReplyPayload();
G2BMessageResponse messageResponse = new G2BMessageResponse();
messageResponse.setResult("ERROR");
messageResponse.getG2BError().add(error);
replyPayload.setG2BMessageResponse(messageResponse);
replyMessage.setG2BReplyPayload(replyPayload);
return replyMessage;
private SFERAG2BReplyMessage b2gRequest(SFERAB2GRequestMessage requestMessage) {
if (requestMessage.getB2GRequest().getJPRequest() != null && !requestMessage.getB2GRequest().getJPRequest().isEmpty()) {
// assuming only one jp request
var jpRequest = requestMessage.getB2GRequest().getJPRequest().getFirst();
var requestedTrainNumber = jpRequest.getTrainIdentification().getOTNID().getOperationalTrainNumber();
var jpResult = staticSferaService.journeyProfile(requestedTrainNumber);
if (jpResult != null) {
log.info("Send JP for trainId={}", requestedTrainNumber);
return jpResult;
} else {
log.info("JP with trainId={} not available", requestedTrainNumber);
return staticSferaService.notAvailableError();
}
// G2B_MessageResponse / result = “OK” no more recent JP
// or result = “ERROR” / dataFirstAvailable
// or result = “ERROR” / errorCode

}
if (requestMessage.getB2GRequest().getSPRequest() != null && !requestMessage.getB2GRequest().getSPRequest().isEmpty()) {
log.info("Send static SP");
return staticSferaService.segmentProfile();
}
if (requestMessage.getB2GRequest().getTCRequest() != null && !requestMessage.getB2GRequest().getTCRequest().isEmpty()) {
log.info("Send static TC");
return staticSferaService.trainCharcteristics();
}
// combination of SP/TC/JP
// or C_DAS_C_AdviceRequest
// or PlaintextMessageRequest
// or ForceDrivingModeChangeRequest
// or PositionSpeedRequest

log.info("b2g request not implemented");
return staticSferaService.notImplementedError();
}

public String replyTopic() {
private String replyTopic(String topic) {
log.info("new message on topic={}", topic);
String[] topicParts = topic.split("/");
String companyCode = topicParts[3];
String trainIdentifier = topicParts[4];
String clientId = topicParts[5];
return "90940/2/G2B/" + companyCode + "/" + trainIdentifier + "/" + clientId;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ch.sbb.playgroundbackend.service;

import ch.sbb.playgroundbackend.helper.XmlHelper;
import generated.SFERAG2BReplyMessage;
import jakarta.xml.bind.JAXBException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

@Service
public class StaticSferaService implements ApplicationRunner {

private static final Logger log = LoggerFactory.getLogger(StaticSferaService.class);

private static final String XML_RESOURCES_CLASSPATH = "classpath:sfera_example_messages/";
private static final Map<Object, String> files = new HashMap<>();

static {
files.put(ResponseType.HANDSHAKE, "SFERA_G2B_ReplyMessage_handshake.xml");
files.put(ResponseType.SP, "SFERA_G2B_Reply_SP_request.xml");
files.put(ResponseType.TC, "SFERA_G2B_Reply_TC_request.xml");
files.put(ResponseType.NOT_IMPLEMENTED, "SFERA_G2B_ReplyMessage_error_notImplemented.xml");
files.put(ResponseType.XML_ERROR, "SFERA_G2B_ReplyMessage_error_xmlSchema.xml");
files.put(ResponseType.NOT_AVAILABLE, "SFERA_G2B_ReplyMessage_error_notAvailable.xml");
files.put(ResponseType.INSUFFICIENT_DATA, "SFERA_G2B_ReplyMessage_error_insufficientData.xml");
files.put("9358", "SFERA_G2B_Reply_JP_request_9358.xml");
files.put("9232", "SFERA_G2B_Reply_JP_request_9232.xml");
files.put("9310", "SFERA_G2B_Reply_JP_request_9310.xml");
files.put("9315", "SFERA_G2B_Reply_JP_request_9315.xml");
}

private final Map<Object, SFERAG2BReplyMessage> b2gReplies = new HashMap<>();

@Override
public void run(ApplicationArguments args) {
files.forEach((trainId, fileName) -> {
String filePath = XML_RESOURCES_CLASSPATH + fileName;
try {
this.b2gReplies.put(trainId, XmlHelper.xmlFileToObject(filePath, SFERAG2BReplyMessage.class));
} catch (IOException | JAXBException e) {
log.error("failed to import static xml replies", e);
}
});
log.info("imported {} static replies", this.b2gReplies.size());
}

public SFERAG2BReplyMessage journeyProfile(String trainId) {
return b2gReplies.get(trainId);
}

public SFERAG2BReplyMessage handshake() {
return b2gReplies.get(ResponseType.HANDSHAKE);
}

public SFERAG2BReplyMessage segmentProfile() {
return b2gReplies.get(ResponseType.SP);
}

public SFERAG2BReplyMessage trainCharcteristics() {
return b2gReplies.get(ResponseType.TC);
}

public SFERAG2BReplyMessage invalidXmlError() {
return b2gReplies.get(ResponseType.XML_ERROR);
}

public SFERAG2BReplyMessage notImplementedError() {
return b2gReplies.get(ResponseType.NOT_IMPLEMENTED);
}

public SFERAG2BReplyMessage notAvailableError() {
return b2gReplies.get(ResponseType.NOT_AVAILABLE);
}

public SFERAG2BReplyMessage insufficientData() {
return b2gReplies.get(ResponseType.INSUFFICIENT_DATA);
}

protected enum ResponseType {
HANDSHAKE,
SP,
TC,
NOT_IMPLEMENTED,
XML_ERROR,
NOT_AVAILABLE,
INSUFFICIENT_DATA,
}
}

This file was deleted.

Loading

0 comments on commit 92aa3d9

Please sign in to comment.