diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java index 66ef496..32f3486 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java @@ -1,4 +1,4 @@ -package ch.unisg.executorbase.executor.adapter.in.web; +package ch.unisg.executorBase.executor.adapter.in.web; import java.util.logging.Logger; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java index f683b81..5d832db 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java @@ -1,4 +1,4 @@ -package ch.unisg.executorbase.executor.adapter.out.web; +package ch.unisg.executorBase.executor.adapter.out.web; import java.io.IOException; import java.net.URI; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java index 09ded48..be5ddd6 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java @@ -1,10 +1,11 @@ package ch.unisg.executorbase.executor.domain; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import ch.unisg.common.valueobject.ExecutorURI; -import ch.unisg.executorbase.executor.adapter.out.web.ExecutionFinishedEventAdapter; +import ch.unisg.executorBase.executor.adapter.out.web.ExecutionFinishedEventAdapter; import ch.unisg.executorbase.executor.adapter.out.web.GetAssignmentAdapter; import ch.unisg.executorbase.executor.adapter.out.web.NotifyExecutorPoolAdapter; import ch.unisg.executorbase.executor.application.port.out.ExecutionFinishedEventPort; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java index 33ae142..30460e6 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java @@ -1,11 +1,11 @@ package ch.unisg.executorbase.executor.domain; public enum ExecutorType { - COMPUTATION, ROBOT; + COMPUTATION, ROBOT, HUMIDITY; /** * Checks if the give executor type exists. - * @return Wheter the given executor type exists + * @return Whether the given executor type exists **/ public static boolean contains(String test) { diff --git a/executor-humidity/pom.xml b/executor-humidity/pom.xml new file mode 100644 index 0000000..27ed3b6 --- /dev/null +++ b/executor-humidity/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.5 + + + org.unisg + executor-humidity + 1.0-SNAPSHOT + executor-humidity + Demo project for Spring Boot + + + jitpack.io + https://jitpack.io + + + + + org.springframework.boot + spring-boot-autoconfigure + 2.5.5 + compile + + + org.springframework + spring-web + 5.3.10 + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + org.eclipse.californium + californium-core + 3.0.0 + compile + + + com.github.Interactions-HSG + wot-td-java + 0.1.1 + + + + + 16 + 16 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java new file mode 100644 index 0000000..181cfeb --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java @@ -0,0 +1,16 @@ +package ch.unisg.executorhumidity; + + +import ch.unisg.executorhumidity.executor.domain.Executor; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExecutorhumidityApplication { + + public static void main(String[] args) { + SpringApplication.run(ExecutorhumidityApplication.class, args); + Executor.getExecutor(); + } + +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java new file mode 100644 index 0000000..b66472c --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java @@ -0,0 +1,38 @@ +package ch.unisg.executorhumidity.executor.adapter.in.web; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableCommand; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableUseCase; +import ch.unisg.executorbase.executor.domain.ExecutorType; + +import java.util.concurrent.CompletableFuture; + +@RestController +public class TaskAvailableController { + private final TaskAvailableUseCase taskAvailableUseCase; + + public TaskAvailableController(TaskAvailableUseCase taskAvailableUseCase) { + this.taskAvailableUseCase = taskAvailableUseCase; + } + + @GetMapping(path="/newtask/{taskType}") + public ResponseEntity retrieveTaskfromTaskList(@PathVariable("taskType") String taskType) { + + if (ExecutorType.contains(taskType.toUpperCase())) { + TaskAvailableCommand command = new TaskAvailableCommand( + ExecutorType.valueOf(taskType.toUpperCase())); + CompletableFuture.runAsync(() -> taskAvailableUseCase.newTaskAvailable(command)); + } + + // Add the content type as a response header + HttpHeaders responseHeaders = new HttpHeaders(); + + return new ResponseEntity<>("OK", responseHeaders, HttpStatus.OK); + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java new file mode 100644 index 0000000..c73e356 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java @@ -0,0 +1,78 @@ +package ch.unisg.executorhumidity.executor.adapter.out; + +import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.affordances.PropertyAffordance; +import ch.unisg.ics.interactions.wot.td.clients.TDCoapRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDCoapResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; +import org.eclipse.californium.core.CoapClient; +import org.eclipse.californium.elements.exception.ConnectorException; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Map; +import java.util.Optional; + + +@Component +@Primary +public class GetHumidityAdapter implements GetHumidityPort { + + @Override + public String getHumidity() { + + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/sparql-query") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); + + try { + String description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + Optional humidity = td.getPropertyByName("humidity"); + + if (humidity.isPresent()) { + Optional
form = humidity.get().getFirstFormForOperationType(TD.readProperty); + + if (form.isPresent()) { + TDCoapRequest request = new TDCoapRequest(form.get(), TD.readProperty); + try { + TDCoapResponse response = request.execute(); + + Map payload = response.getPayloadAsObject((ObjectSchema) humidity.get().getDataSchema()); + Object result = payload.get("https://interactions.ics.unisg.ch/mirogate#HumidityValue"); + return result.toString(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java new file mode 100644 index 0000000..d2cda18 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java @@ -0,0 +1,9 @@ +package ch.unisg.executorhumidity.executor.application.port.out; + +import org.eclipse.californium.elements.exception.ConnectorException; + +import java.io.IOException; + +public interface GetHumidityPort { + String getHumidity(); +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java new file mode 100644 index 0000000..0e467c4 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java @@ -0,0 +1,27 @@ +package ch.unisg.executorhumidity.executor.application.service; + +import ch.unisg.executorbase.executor.domain.ExecutorStatus; +import ch.unisg.executorhumidity.executor.domain.Executor; +import org.springframework.stereotype.Component; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableCommand; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableUseCase; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@RequiredArgsConstructor +@Component +@Transactional +public class TaskAvailableService implements TaskAvailableUseCase { + + @Override + public void newTaskAvailable(TaskAvailableCommand command) { + + Executor executor = Executor.getExecutor(); + + if(executor.getExecutorType() == command.getTaskType() && + executor.getStatus() == ExecutorStatus.IDLING) { + executor.getAssignment(); + } + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java new file mode 100644 index 0000000..ac73e65 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java @@ -0,0 +1,31 @@ +package ch.unisg.executorhumidity.executor.domain; + +import ch.unisg.executorbase.executor.domain.ExecutorBase; +import ch.unisg.executorbase.executor.domain.ExecutorType; +import ch.unisg.executorhumidity.executor.adapter.out.GetHumidityAdapter; +import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import org.eclipse.californium.elements.exception.ConnectorException; + +import java.io.IOException; + +public class Executor extends ExecutorBase{ + + private static final Executor executor = new Executor(ExecutorType.HUMIDITY); + + private final GetHumidityPort getHumidityPort = new GetHumidityAdapter(); + + private Executor(ExecutorType executorType) {super(executorType);} + + public static Executor getExecutor() {return executor;} + + + @Override + protected + String execution(String input) { + //TODO: Fill + + String result = getHumidityPort.getHumidity(); + + return result; + } +} diff --git a/executor-robot/pom.xml b/executor-robot/pom.xml index ca95edf..570bd18 100644 --- a/executor-robot/pom.xml +++ b/executor-robot/pom.xml @@ -18,6 +18,12 @@ scs-asse-fs21-group1 https://sonarcloud.io + + + jitpack.io + https://jitpack.io + + org.springframework.boot @@ -45,7 +51,43 @@ executor-base 0.0.1-SNAPSHOT - + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + com.github.Interactions-HSG + wot-td-java + 0.1.1 + compile + + diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java index 157bc3e..37b605a 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java @@ -17,16 +17,16 @@ public class DeleteUserFromRobotAdapter implements DeleteUserFromRobotPort { @Override public boolean deleteUserFromRobot(String key) { - String url = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/user/" + key; - + String url = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.4/user/" + key; + var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .DELETE() .build(); - + var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -38,5 +38,5 @@ public class DeleteUserFromRobotAdapter implements DeleteUserFromRobotPort { } return false; } - + } diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java index c7507e4..531b5eb 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java @@ -4,7 +4,21 @@ import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.ActionAffordance; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.DataSchema; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.schemas.StringSchema; +import ch.unisg.ics.interactions.wot.td.security.APIKeySecurityScheme; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -16,9 +30,70 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { @Override public boolean instructionToRobot(String key) { - + + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); + + try { + var description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + // Create the payload to be sent with the Http request + Map elbowPayload = new HashMap<>(); + elbowPayload.put("http://www.w3.org/2001/XMLSchema#int", 400); + + // Get the affordance "setElbow" from the TD + Optional action = td.getActionByName("setElbow"); + + // Get the first form + if (action.isPresent()) { + Optional form = action.get().getFirstForm(); + + // Retrieve the input data schema from the action affordance + Optional inputSchema = action.get().getInputSchema(); + + // If a form is found, use it to create and execute the Http request + if (form.isPresent()) { + TDHttpRequest request = new TDHttpRequest(form.get(), TD.invokeAction); + + if (inputSchema.isPresent()) { + request.setObjectPayload((ObjectSchema) inputSchema.get(), elbowPayload); + + try { + TDHttpResponse response = request.execute(); + System.out.println("Received response with status code: " + response.getStatusCode()); + return true; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return false; + + + + + /* String putEndpoint = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/elbow"; - + String inputJson = "{ \"value\": 400}"; var request = HttpRequest.newBuilder() .uri(URI.create(putEndpoint)) @@ -26,9 +101,9 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { .header("X-API-KEY", key) .PUT(HttpRequest.BodyPublishers.ofString(inputJson)) .build(); - + var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -40,7 +115,7 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { e.printStackTrace(); } return false; - + */ } - + } diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java index 92ca8c1..7c20616 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java @@ -4,7 +4,20 @@ import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.ActionAffordance; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.DataSchema; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; +import org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -16,17 +29,77 @@ public class UserToRobotAdapter implements UserToRobotPort { @Override public String userToRobot() { - String postEndpoint = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/user"; - + + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); + + try { + var description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + // Create the payload to be sent with the HTTP request + Map logInPayload = new HashMap<>(); + logInPayload.put("http://xmlns.com/foaf/0.1/Name", "keanu rahimian"); + logInPayload.put("http://xmlns.com/foaf/0.1/Mbox", "keanu.rahimian@student.unisg.ch"); + + // Get the affordance "Log-In" from the TD + Optional action = td.getActionByName("logIn"); + + // Get the first form + if (action.isPresent()) { + Optional form = action.get().getFirstForm(); + + // Retrieve the input data schema from the action affordance + Optional inputSchema = action.get().getInputSchema(); + + // If a form is found, use it to create and execute the HTTP request + if (form.isPresent()) { + TDHttpRequest request = new TDHttpRequest(form.get(), TD.invokeAction); + + if (inputSchema.isPresent()) { + request.setObjectPayload((ObjectSchema) inputSchema.get(), logInPayload); + + try { + TDHttpResponse response = request.execute(); + System.out.println("Received response with status code: " + response.getStatusCode()); + + // TODO: Get the key from the response and return it + // Not exactly sure how to get the headers from the payload, as we need them + // to get the key + + return null; + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + /* String inputJson = "{ \"name\":\"keanu rahimian\", \"email\":\"keanu.rahimian@student.unisg.ch\"}"; var request = HttpRequest.newBuilder() .uri(URI.create(postEndpoint)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(inputJson)) .build(); - - var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -40,7 +113,10 @@ public class UserToRobotAdapter implements UserToRobotPort { e.printStackTrace(); } return null; - + */ + + + return null; } - + }