diff --git a/AlgebraicDataflowArchitectureModel/models/RestTest.model b/AlgebraicDataflowArchitectureModel/models/RestTest.model new file mode 100644 index 0000000..d37ca5c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/RestTest.model @@ -0,0 +1,40 @@ +native channel setResponse(num: Int) { + out restClients.{num}.response(prev: Str, setResponse(response)) = response +} + +native channel changeState(num: Int) { + in restClients.{num}.state(state: Int, changeState(newState: Int)) = newState +} + + +channel creatClient{ + out restClients(clients: List, create(url:Str, method:Str)) = append(clients, { + "url": url, + "method": method, + "body": nil, + "response": "", + "header": nil, + "state": 0 + }) +} + +channel onResponse(num: Int) { + in restClients.{num}.response(res: Str, changeRes(newRes)) = newRes + out restClients.{num}.state(state: Int, changeRes(newRes)) = 0 +} + +channel setUrl(num: Int) { + out restClients.{num}.url(curUrl: Str, setUrl(newUrl: Str)) = newUrl +} + +channel addBody(num: Int) { + out restClients.{num}.body(body: Map, addBody(key: Str, value: Str)) = insert(body, key, value) +} + +channel addHeader(num: Int) { + out restClients.{num}.header(header: Map, addHeader(key: Str, value: Str)) = insert(header, key, value) +} + +channel setState(num: Int) { + out restClients.{num}.state(nowState: Int, setState(newState)) = newState +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java index 1c246b9..d3d03a6 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java @@ -4,6 +4,7 @@ import javax.swing.JPanel; import simulator.Simulator; +import simulator.interfaces.rest.RestPresenter; import simulator.interfaces.swing.SwingPresenter; import simulator.interfaces.timers.TimerService; @@ -15,11 +16,15 @@ private JPanel mainPanel; private TimerService timerService; + private RestPresenter rest; + public UISimulatorWindow(Simulator simulator) { setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.simulator = simulator; mainPanel = new JPanel(); presenter = new SwingPresenter(mainPanel, simulator); + rest = new RestPresenter(simulator); + this.add(mainPanel); timerService = new TimerService(simulator); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/ResponseSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/ResponseSender.java new file mode 100644 index 0000000..240a598 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/ResponseSender.java @@ -0,0 +1,74 @@ +package simulator.interfaces.rest; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.util.concurrent.CompletableFuture; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.MapTerm; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Resource; +import simulator.Simulator; +import simulator.interfaces.NativeSender; + +public class ResponseSender extends NativeSender{ + + private HttpClient client; + private HttpRequest request; + + public ResponseSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath, + Resource resource, String url, String method, MapTerm header, JsonTerm body) { + super(simulator, channel, resourcePath, resource); + client = HttpClient.newHttpClient(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() + .uri(URI.create(url)); + + for(String key : header.keySet()) { + requestBuilder.header(key, header.get(key).toString()); + } + + switch(method) { + case "GET": + request = requestBuilder + .GET() + .build(); + break; + case "POST": + request = requestBuilder + .POST(BodyPublishers.ofString(body.toString())) + .build(); + break; + default: + request = requestBuilder + .GET() + .build(); + } + } + + public void sendRequest() { + CompletableFuture> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); + responseFuture.thenAccept(response -> { + sendResponse(response.body()); + }).exceptionally(e -> { + e.printStackTrace(); + return null; + }); + } + + private void sendResponse(String response) { + Constant res = new Constant(response, DataConstraintModel.typeString); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term)message.clone(); + ((Term) message).setChild(0, res); + sendToModel(message); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/RestPresenter.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/RestPresenter.java new file mode 100644 index 0000000..4276ddf --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/rest/RestPresenter.java @@ -0,0 +1,63 @@ +package simulator.interfaces.rest; + +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.MapTerm; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Event; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class RestPresenter implements INativeReceiver{ + + public final String changeStateChannelName = "changeState"; + public final String setResponseChannelName = "setResponse"; + + protected Simulator simulator; + + protected DataTransferChannel changeStateChannel; + protected DataTransferChannel setResponseChannel; + + public RestPresenter(Simulator simulator) { + this.simulator = simulator; + changeStateChannel = (DataTransferChannel) simulator.getModel().getChannel(changeStateChannelName); + setResponseChannel = (DataTransferChannel) simulator.getModel().getInputChannel(setResponseChannelName); + simulator.addNativeReceiver(this, changeStateChannel); + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + ResourcePath path = event.getInputResourcePath(); + ResourceIdentifier ri = event.getInputResourceIdentifier(path); + System.out.println(path); + System.out.println(ri); + String clientNumber = ri.getPathParams().get(0).toString(); + if(message instanceof Term && ((Term) message).getChildren().size() >= 1) { + Expression state = ((Term) message).getChild(0); + System.out.println(state); + if (state.toString().equals("1")) { + String url = simulator.getCurState().getResource("restClients." + clientNumber + ".url").getState().getValue().toString().replace("\"", ""); + String method = simulator.getCurState().getResource("restClients." + clientNumber + ".method").getState().getValue().toString(); +// MapTerm header = (MapTerm)simulator.getCurState().getResource("restClients." + clientNumber + ".header").getState().getValue(); +// JsonTerm body = (JsonTerm)simulator.getCurState().getResource("restClients." + clientNumber + ".body").getState().getValue(); + MapTerm header = new MapTerm(); + JsonTerm body = new JsonTerm(); + + Resource stateRes = nextSystemState.getResource(event.getInputResource().getResourceIdentifier()); + Resource responseRes = stateRes.getParent().getChildrenMap().get("response"); + System.out.println(responseRes.getResourceIdentifier()); + + ResourcePath resPath = setResponseChannel.getOutputResources().iterator().next(); + ResponseSender sender = new ResponseSender(simulator, setResponseChannel, resPath, responseRes, url, method, header, body); + sender.sendRequest(); + } + } + } + +}