From: Zoltán Felleg Date: Tue, 16 May 2023 15:25:35 +0000 (+0200) Subject: Initial commit. X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;h=HEAD;p=mki-fd.git Initial commit. --- e3e0793ac75cb6f86df68ac33149156f480caefe diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/CommonDto/pom.xml b/CommonDto/pom.xml new file mode 100644 index 0000000..e976f76 --- /dev/null +++ b/CommonDto/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + hu.user + CreditCardFraudDetect + 1.0-SNAPSHOT + + + CommonDto + + + 11 + 11 + UTF-8 + + + + + com.fasterxml.jackson.core + jackson-annotations + 2.14.1 + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + 2.14.1 + + + org.projectlombok + lombok + 1.18.24 + true + + + + + + + \ No newline at end of file diff --git a/Core/Dockerfile b/Core/Dockerfile new file mode 100644 index 0000000..c3c2d68 --- /dev/null +++ b/Core/Dockerfile @@ -0,0 +1,4 @@ +FROM adoptopenjdk:14-jre-hotspot +WORKDIR /opt/app +COPY target/*.jar core.jar +CMD ["java","-jar","core.jar"] \ No newline at end of file diff --git a/Core/pom.xml b/Core/pom.xml new file mode 100644 index 0000000..5ec5a64 --- /dev/null +++ b/Core/pom.xml @@ -0,0 +1,118 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.1 + + + hu.user + Core + 0.0.1-SNAPSHOT + Core + Core + + 11 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-web-services + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-jdbc + + + mysql + mysql-connector-java + runtime + + + wsdl4j + wsdl4j + + + org.jvnet.jaxb2_commons + jaxb2-basics + 0.9.5 + + + org.jvnet.jaxb2_commons + jaxb2-value-constructor + 3.0 + + + org.glassfish.jaxb + jaxb-runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + hu.user + CommonDto + 1.0-SNAPSHOT + compile + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 2.5.0 + + + xjc + + xjc + + + + -Xvalue-constructor + + + + + + + ${project.basedir}/src/main/resources/detection.xsd + + + + + + + + diff --git a/Core/src/main/java/hu/user/core/CoreApplication.java b/Core/src/main/java/hu/user/core/CoreApplication.java new file mode 100644 index 0000000..14159e3 --- /dev/null +++ b/Core/src/main/java/hu/user/core/CoreApplication.java @@ -0,0 +1,13 @@ +package hu.user.core; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CoreApplication { + + public static void main(String[] args) { + SpringApplication.run(CoreApplication.class, args); + } + +} diff --git a/Core/src/main/java/hu/user/core/config/RestConfig.java b/Core/src/main/java/hu/user/core/config/RestConfig.java new file mode 100644 index 0000000..8749e49 --- /dev/null +++ b/Core/src/main/java/hu/user/core/config/RestConfig.java @@ -0,0 +1,18 @@ +package hu.user.core.config; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestConfig { + + @Bean + public RestTemplate getRestTemplate(RestTemplateBuilder builder) { + RestTemplate restTemplate = builder + .build(); + return restTemplate; + + } +} diff --git a/Core/src/main/java/hu/user/core/config/StatisticConfig.java b/Core/src/main/java/hu/user/core/config/StatisticConfig.java new file mode 100644 index 0000000..b930367 --- /dev/null +++ b/Core/src/main/java/hu/user/core/config/StatisticConfig.java @@ -0,0 +1,31 @@ +package hu.user.core.config; + +import org.springframework.stereotype.Component; + +import hu.user.core.dto.StatisticsDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Component +@Getter +@Setter +public class StatisticConfig { + + private String cardNumberFieldName; + private String transactionTimeFieldName; + private boolean enabled; + + public void setParameters(StatisticsDto statisticsDto) { + this.cardNumberFieldName = statisticsDto.getCardNumberFieldName(); + this.transactionTimeFieldName = statisticsDto.getTransactionTimeFieldName(); + this.enabled = enabled; + } + + public void deleteParameters() { + this.cardNumberFieldName = null; + this.transactionTimeFieldName = null; + this.enabled = false; + } + +} diff --git a/Core/src/main/java/hu/user/core/config/WebServiceConfig.java b/Core/src/main/java/hu/user/core/config/WebServiceConfig.java new file mode 100644 index 0000000..8036346 --- /dev/null +++ b/Core/src/main/java/hu/user/core/config/WebServiceConfig.java @@ -0,0 +1,40 @@ +package hu.user.core.config; + +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.ws.config.annotation.EnableWs; +import org.springframework.ws.config.annotation.WsConfigurerAdapter; +import org.springframework.ws.transport.http.MessageDispatcherServlet; +import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; +import org.springframework.xml.xsd.SimpleXsdSchema; +import org.springframework.xml.xsd.XsdSchema; + +@EnableWs +@Configuration +public class WebServiceConfig extends WsConfigurerAdapter { + @Bean + public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { + MessageDispatcherServlet servlet = new MessageDispatcherServlet(); + servlet.setApplicationContext(applicationContext); + servlet.setTransformWsdlLocations(true); + return new ServletRegistrationBean<>(servlet, "/ws/*"); + } + + @Bean(name = "detection") + public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { + DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); + wsdl11Definition.setPortTypeName("DetectionPort"); + wsdl11Definition.setLocationUri("/ws"); + wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service"); + wsdl11Definition.setSchema(countriesSchema); + return wsdl11Definition; + } + + @Bean + public XsdSchema countriesSchema() { + return new SimpleXsdSchema(new ClassPathResource("detection.xsd")); + } +} diff --git a/Core/src/main/java/hu/user/core/controller/EstimatorController.java b/Core/src/main/java/hu/user/core/controller/EstimatorController.java new file mode 100644 index 0000000..b054c83 --- /dev/null +++ b/Core/src/main/java/hu/user/core/controller/EstimatorController.java @@ -0,0 +1,50 @@ +package hu.user.core.controller; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.core.estimators.EstimatorContainer; + +@Controller +public class EstimatorController { + + private EstimatorContainer estimatorContainer; + + public EstimatorController(EstimatorContainer estimatorContainer) { + this.estimatorContainer = estimatorContainer; + } + + @PostMapping("/estimator") + public ResponseEntity> addEstimator( + @RequestBody EstimatorRegistryParameterDto estimatorRegistryParameterDto) { + List registeredEstimators = + estimatorContainer.addEstimator(estimatorRegistryParameterDto); + return new ResponseEntity<>(registeredEstimators, HttpStatus.OK); + } + + @GetMapping("/estimator") + public ResponseEntity> getEstimators() { + return new ResponseEntity<>(estimatorContainer.getEstimator(), HttpStatus.OK); + } + + @PutMapping("estimator") + public ResponseEntity> modifyEstimator( + @RequestBody EstimatorRegistryParameterDto estimatorRegistryParameterDto) { + return new ResponseEntity<>(estimatorContainer.updateEstimator(estimatorRegistryParameterDto), HttpStatus.OK); + } + + @DeleteMapping("estimator/{id}") + public ResponseEntity> deleteEstimator(@PathVariable("id") int id) { + return new ResponseEntity<>(estimatorContainer.deleteEstimator(id), HttpStatus.OK); + } +} diff --git a/Core/src/main/java/hu/user/core/controller/StatisticController.java b/Core/src/main/java/hu/user/core/controller/StatisticController.java new file mode 100644 index 0000000..e1cf4dd --- /dev/null +++ b/Core/src/main/java/hu/user/core/controller/StatisticController.java @@ -0,0 +1,57 @@ +package hu.user.core.controller; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import hu.user.common.dto.ConfusionMatrixDto; +import hu.user.core.dto.ObservedValue; +import hu.user.core.service.FraudService; +import hu.user.core.service.StatisticService; + +@Controller +public class StatisticController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired private FraudService fraudService; + @Autowired private StatisticService statisticService; + + @GetMapping("/confusion_matrix") + public ResponseEntity getConfusionMatrix() { + logger.info("get confusion matrix"); + return new ResponseEntity<>(fraudService.qualify(), HttpStatus.OK); + } + + @PostMapping("/observed") + public ResponseEntity storeObservedValues(@RequestBody List observedValues) { + statisticService.storeObservedValues(observedValues); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/transaction") + public ResponseEntity getAllTransaction() { + return new ResponseEntity<>(statisticService.getAllTransaction(), HttpStatus.OK); + } + + @GetMapping("/observed") + public ResponseEntity getAllObservedTransaction() { + return new ResponseEntity<>(statisticService.getAllObservedTransaction(), HttpStatus.OK); + } + + @PostMapping("/transaction_clear") + public ResponseEntity deleteAllTransaction() { + fraudService.deleteAllFraud(); + return new ResponseEntity<>(HttpStatus.OK); + } + } + + diff --git a/Core/src/main/java/hu/user/core/domain/Fraud.java b/Core/src/main/java/hu/user/core/domain/Fraud.java new file mode 100644 index 0000000..bd03811 --- /dev/null +++ b/Core/src/main/java/hu/user/core/domain/Fraud.java @@ -0,0 +1,44 @@ +package hu.user.core.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class Fraud { + + @Id +// @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long Id; + private String transactionUuid; + private Integer predictedValue; + + private Integer observedValue; + + private boolean predicted; + + private boolean observed; + + private double positiveProbability; + + private double negativeProbability; + + public Fraud(String transactionUuid, int predictedValue,double positiveProbability,double negativeProbability) { + this.transactionUuid = transactionUuid; + this.predictedValue = predictedValue; + this.predicted = true; + this.observed = false; + this.positiveProbability = positiveProbability; + this.negativeProbability = negativeProbability; + } + + public Fraud() { + } +} diff --git a/Core/src/main/java/hu/user/core/dto/CommulatedResponseFromEstimator.java b/Core/src/main/java/hu/user/core/dto/CommulatedResponseFromEstimator.java new file mode 100644 index 0000000..f8619d5 --- /dev/null +++ b/Core/src/main/java/hu/user/core/dto/CommulatedResponseFromEstimator.java @@ -0,0 +1,23 @@ +package hu.user.core.dto; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@JsonIgnoreProperties(ignoreUnknown = true) +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class CommulatedResponseFromEstimator implements Serializable { + + private Map response = new HashMap<>(); + +} diff --git a/Core/src/main/java/hu/user/core/dto/ObservedValue.java b/Core/src/main/java/hu/user/core/dto/ObservedValue.java new file mode 100644 index 0000000..f71ae92 --- /dev/null +++ b/Core/src/main/java/hu/user/core/dto/ObservedValue.java @@ -0,0 +1,14 @@ +package hu.user.core.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class ObservedValue { + + private String uuid; + private int observedFraud; +} diff --git a/Core/src/main/java/hu/user/core/dto/ResponseFromSingleEstimator.java b/Core/src/main/java/hu/user/core/dto/ResponseFromSingleEstimator.java new file mode 100644 index 0000000..9bf0cdd --- /dev/null +++ b/Core/src/main/java/hu/user/core/dto/ResponseFromSingleEstimator.java @@ -0,0 +1,29 @@ +package hu.user.core.dto; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@Setter +public class ResponseFromSingleEstimator implements Serializable { + + protected int prediction; + protected double negativeProbability; + protected double positiveProbability; + + public ResponseFromSingleEstimator(@JsonProperty(value = "prediction", required = true) int prediction, + @JsonProperty(value = "negative_probability", required = true) double negativeProbability, + @JsonProperty(value = "positive_probability", required = true) double positiveProbability) { + this.prediction = prediction; + this.negativeProbability = negativeProbability; + this.positiveProbability = positiveProbability; + } +} diff --git a/Core/src/main/java/hu/user/core/dto/StatisticsDto.java b/Core/src/main/java/hu/user/core/dto/StatisticsDto.java new file mode 100644 index 0000000..9faa917 --- /dev/null +++ b/Core/src/main/java/hu/user/core/dto/StatisticsDto.java @@ -0,0 +1,22 @@ +package hu.user.core.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; + +@Getter +public class StatisticsDto { + + private String cardNumberFieldName; + private String transactionTimeFieldName; + private boolean enabled; + + public StatisticsDto(@JsonProperty(value = "card_number_field_name", required = true) String cardNumberFieldName, + @JsonProperty(value = "transaction_time_field_name", required = true) String transactionTimeFieldName, + @JsonProperty(value = "enabled", required = true) boolean enabled) { + + this.cardNumberFieldName = cardNumberFieldName; + this.transactionTimeFieldName = transactionTimeFieldName; + this.enabled = enabled; + } +} diff --git a/Core/src/main/java/hu/user/core/endpoint/WebserviceEndpoint.java b/Core/src/main/java/hu/user/core/endpoint/WebserviceEndpoint.java new file mode 100644 index 0000000..196e7e8 --- /dev/null +++ b/Core/src/main/java/hu/user/core/endpoint/WebserviceEndpoint.java @@ -0,0 +1,65 @@ +package hu.user.core.endpoint; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; + +import hu.user.core.service.StatisticService; +import hu.user.core.service.VoteModul; +import io.spring.guides.gs_producing_web_service.DetectionResponse; +import io.spring.guides.gs_producing_web_service.GenerateDetectionRequest; +import io.spring.guides.gs_producing_web_service.GenerateGenericDetectionRequest; +import io.spring.guides.gs_producing_web_service.ObjectFactory; +import io.spring.guides.gs_producing_web_service.GenerateDetectionResponse; +import io.spring.guides.gs_producing_web_service.StoreRealTransactionRequest; +import io.spring.guides.gs_producing_web_service.StoreRealTransactionResponse; +import io.spring.guides.gs_producing_web_service.StoreResult; +import lombok.AllArgsConstructor; + +@Endpoint +@AllArgsConstructor +public class WebserviceEndpoint { + + private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service"; + + private VoteModul voteModul; + private StatisticService statisticService; + + + + @PayloadRoot(namespace = NAMESPACE_URI, localPart = "generateDetectionRequest") + @ResponsePayload + public GenerateDetectionResponse getPrediction(@RequestPayload GenerateDetectionRequest generateDetectionRequest) { + ObjectFactory objectFactory =new ObjectFactory(); + DetectionResponse detectionResponse = voteModul.voting(generateDetectionRequest); + GenerateDetectionResponse generateDetectionResponse = objectFactory.createGenerateDetectionResponse(); + generateDetectionResponse.setDetectionResponse(detectionResponse); + return generateDetectionResponse; + } + + @PayloadRoot(namespace = NAMESPACE_URI, localPart = "generateGenericDetectionRequest") + @ResponsePayload + public GenerateDetectionResponse getGenericPrediction(@RequestPayload + GenerateGenericDetectionRequest generateGenericDetectionRequest) { + ObjectFactory objectFactory =new ObjectFactory(); + DetectionResponse detectionResponse = voteModul.genericVoting(generateGenericDetectionRequest); + GenerateDetectionResponse generateDetectionResponse = objectFactory.createGenerateDetectionResponse(); + generateDetectionResponse.setDetectionResponse(detectionResponse); + return generateDetectionResponse; + } + + @PayloadRoot(namespace = NAMESPACE_URI, localPart = "storeRealTransactionRequest") + @ResponsePayload + public StoreRealTransactionResponse storeRealTransactions( + @RequestPayload StoreRealTransactionRequest storeRealTransactionRequest) { + ObjectFactory objectFactory =new ObjectFactory(); + StoreRealTransactionResponse storeRealTransactionResponse=objectFactory.createStoreRealTransactionResponse(); + StoreResult storeResult = statisticService.storeRealTransactions(storeRealTransactionRequest); + storeRealTransactionResponse.setStoreResult(storeResult); + return storeRealTransactionResponse; + + } + +} diff --git a/Core/src/main/java/hu/user/core/estimators/EstimatorContainer.java b/Core/src/main/java/hu/user/core/estimators/EstimatorContainer.java new file mode 100644 index 0000000..4709ab2 --- /dev/null +++ b/Core/src/main/java/hu/user/core/estimators/EstimatorContainer.java @@ -0,0 +1,69 @@ +package hu.user.core.estimators; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.core.service.TrainClient; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Component +@Getter +@Setter +@Slf4j +public class EstimatorContainer { + + private static final String ID = "id"; + + private TrainClient trainClient; + private Map estimatorWeightById = new HashMap<>(); + private String transactionIdentifierFieldName; + + public EstimatorContainer(TrainClient trainClient) { + this.trainClient = trainClient; + } + + public List addEstimator(EstimatorRegistryParameterDto registryParameterDto) { + if (transactionIdentifierFieldName == null) { + transactionIdentifierFieldName = trainClient.getTransactionIdentifierFieldNameByEstimatorId( + Map.of(ID, String.valueOf(registryParameterDto.getEstimatorId()))); + } + estimatorWeightById.put(registryParameterDto.getEstimatorId(), registryParameterDto.getWeight()); + log.debug( + "Estimator registered, estimator id: " + registryParameterDto.getEstimatorId() + ", weight: " + registryParameterDto.getWeight()); + return convertToDtos(); + } + + public List getEstimator() { + return convertToDtos(); + } + + public List updateEstimator(EstimatorRegistryParameterDto registryParameterDto) { + int id = registryParameterDto.getEstimatorId(); + if (estimatorWeightById.containsKey(id)) { + estimatorWeightById.put(registryParameterDto.getEstimatorId(), registryParameterDto.getWeight()); + log.debug( + "Estimator weight updated, estimator id: " + registryParameterDto.getEstimatorId() + ", weight: " + registryParameterDto.getWeight()); + } + return convertToDtos(); + } + + public List deleteEstimator(int estimatorId) { + if (estimatorWeightById.containsKey(estimatorId)) { + estimatorWeightById.remove(estimatorId); + log.debug("Estimator removed, estimator id: " + estimatorId); + } + return convertToDtos(); + } + + private List convertToDtos() { + return estimatorWeightById.entrySet().stream() + .map(e -> new EstimatorRegistryParameterDto(e.getKey(), e.getValue())).collect(Collectors.toList()); + } +} diff --git a/Core/src/main/java/hu/user/core/estimators/WeightAndTransactionIdentifierFieldName.java b/Core/src/main/java/hu/user/core/estimators/WeightAndTransactionIdentifierFieldName.java new file mode 100644 index 0000000..094b717 --- /dev/null +++ b/Core/src/main/java/hu/user/core/estimators/WeightAndTransactionIdentifierFieldName.java @@ -0,0 +1,15 @@ +package hu.user.core.estimators; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class WeightAndTransactionIdentifierFieldName { + + private int weight; + private String transactionIdentifierFieldName; + +} diff --git a/Core/src/main/java/hu/user/core/repository/FraudRepository.java b/Core/src/main/java/hu/user/core/repository/FraudRepository.java new file mode 100644 index 0000000..ae08e2a --- /dev/null +++ b/Core/src/main/java/hu/user/core/repository/FraudRepository.java @@ -0,0 +1,23 @@ +package hu.user.core.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import hu.user.core.domain.Fraud; + +public interface FraudRepository extends JpaRepository { + + + @Query("SELECT COUNT(f) FROM Fraud f WHERE f.predicted = true and f.observed=true and f.predictedValue=1 and f.observedValue=1") + int getNumberOfTruePositivePrediction(); + @Query("SELECT COUNT(f) FROM Fraud f WHERE f.predicted = true and f.observed=true and f.predictedValue=1 and f.observedValue=0") + int getNumberOfFalsePositivePrediction(); + @Query("SELECT COUNT(f) FROM Fraud f WHERE f.predicted = true and f.observed=true and f.predictedValue=0 and f.observedValue=0") + int getNumberOfTrueNegativePrediction(); + @Query("SELECT COUNT(f) FROM Fraud f WHERE f.predicted = true and f.observed=true and f.predictedValue=0 and f.observedValue=1") + int getNumberOfFalseNegativePrediction(); + public Fraud getFraudByTransactionUuid(String transactionUuid); + public int countAllByObserved(boolean observed); + @Query("SELECT COUNT(f) FROM Fraud f") + public int countAllFraud(); +} diff --git a/Core/src/main/java/hu/user/core/service/FraudService.java b/Core/src/main/java/hu/user/core/service/FraudService.java new file mode 100644 index 0000000..e49db04 --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/FraudService.java @@ -0,0 +1,41 @@ +package hu.user.core.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import hu.user.common.dto.ConfusionMatrixDto; +import hu.user.core.domain.Fraud; +import hu.user.core.dto.ObservedValue; +import hu.user.core.repository.FraudRepository; + +@Service +public class FraudService { + + @Autowired private FraudRepository fraudRepository; + + public void savePredictionResult(String transactionUuid, int predictedValue, double positiveProbability,double negativeProbability) { + Fraud fraud = fraudRepository.getFraudByTransactionUuid(transactionUuid); + if (fraud != null) { + fraudRepository.delete(fraud); + } + fraud = new Fraud(transactionUuid, predictedValue, positiveProbability, negativeProbability); + fraudRepository.save(fraud); + } + + public ConfusionMatrixDto qualify() { + int truePositivePredictionNumber = fraudRepository.getNumberOfTruePositivePrediction(); + int falsePositivePredictionNumber = fraudRepository.getNumberOfFalsePositivePrediction(); + int trueNegativePredictionNumber = fraudRepository.getNumberOfTrueNegativePrediction(); + int falseNegativePredictionNumber = fraudRepository.getNumberOfFalseNegativePrediction(); + ConfusionMatrixDto confusionMatrixDto = + new ConfusionMatrixDto(truePositivePredictionNumber, falsePositivePredictionNumber, + trueNegativePredictionNumber, falseNegativePredictionNumber); + return confusionMatrixDto; + } + + public void deleteAllFraud() { + fraudRepository.deleteAll(); + } +} diff --git a/Core/src/main/java/hu/user/core/service/PredictionService.java b/Core/src/main/java/hu/user/core/service/PredictionService.java new file mode 100644 index 0000000..80204b5 --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/PredictionService.java @@ -0,0 +1,69 @@ +package hu.user.core.service; + +import java.net.URI; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import hu.user.core.dto.ResponseFromSingleEstimator; +import io.spring.guides.gs_producing_web_service.DetectionRequest; +import io.spring.guides.gs_producing_web_service.GenericDetectionRequest; + +@Service +public class PredictionService { + + @Value("${estimatorUrl}/prediction") URI estimatorUrl; + + @Autowired private RestTemplate restTemplate; + + public Map getPrediction(DetectionRequest detectionRequest) { + Map requestParameters = new HashMap<>(); + requestParameters.put("card_number", detectionRequest.getCardNumber()); + requestParameters.put("transaction_type", detectionRequest.getTransactionType()); + requestParameters.put("timestamp", detectionRequest.getTimestamp()); + requestParameters.put("amount", detectionRequest.getAmount()); + requestParameters.put("currency_name", detectionRequest.getCurrencyName()); + requestParameters.put("response_code", detectionRequest.getResponseCode()); + requestParameters.put("country_name", detectionRequest.getCountryName()); + requestParameters.put("vendor_code", detectionRequest.getVendorCode()); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(requestParameters, httpHeaders); + ParameterizedTypeReference> typeReference = + new ParameterizedTypeReference<>() { + }; + ResponseEntity> responseEntity = + restTemplate.exchange(estimatorUrl, HttpMethod.POST,httpEntity, typeReference); + Map response= responseEntity.getBody(); + return response; + } + + public Map getGenericPrediction(List requests) { + Map requestParameters = new HashMap<>(); + requests.stream().forEach(e->requestParameters.put(e.getFieldName(),e.getValue())); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(requestParameters, httpHeaders); + ParameterizedTypeReference> typeReference = + new ParameterizedTypeReference<>() { + }; + ResponseEntity> responseEntity = + restTemplate.exchange(estimatorUrl, HttpMethod.POST,httpEntity, typeReference); + Map response= responseEntity.getBody(); + return response; + } +} diff --git a/Core/src/main/java/hu/user/core/service/StatisticService.java b/Core/src/main/java/hu/user/core/service/StatisticService.java new file mode 100644 index 0000000..64a613e --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/StatisticService.java @@ -0,0 +1,62 @@ +package hu.user.core.service; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; + +import hu.user.core.domain.Fraud; +import hu.user.core.dto.ObservedValue; +import hu.user.core.repository.FraudRepository; +import io.spring.guides.gs_producing_web_service.StoreRealTransactionRequest; +import io.spring.guides.gs_producing_web_service.StoreRequest; +import io.spring.guides.gs_producing_web_service.StoreResult; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class StatisticService { + + private final static String SUCCESSFUL = "successful"; + private FraudRepository fraudRepository; + + public StoreResult storeRealTransactions(StoreRealTransactionRequest storeRealTransactionRequest) { + int recordNumber; + List observedFrauds = new ArrayList<>(); + List requests = storeRealTransactionRequest.getStoreRequest(); + for (StoreRequest request : requests) { + String transactionUuid = request.getTransactionId(); + Fraud fraud = fraudRepository.getFraudByTransactionUuid(transactionUuid); + fraud.setObserved(true); + fraud.setObservedValue(request.getFraud()); + observedFrauds.add(fraud); + } + fraudRepository.saveAll(observedFrauds); + StoreResult result = new StoreResult(SUCCESSFUL, observedFrauds.size()); + return result; + } + + public void storeObservedValues(List observedValues) { + List observedFrauds = new ArrayList<>(); + for (ObservedValue observedValue : observedValues) { + String transactionUuid = observedValue.getUuid(); + Fraud fraud = fraudRepository.getFraudByTransactionUuid(transactionUuid); + if (fraud != null) { + fraud.setObserved(true); + fraud.setObservedValue(observedValue.getObservedFraud()); + observedFrauds.add(fraud); + } + } + if (!observedFrauds.isEmpty()) { + fraudRepository.saveAll(observedFrauds); + } + } + + public int getAllTransaction() { + return fraudRepository.countAllFraud(); + } + + public int getAllObservedTransaction() { + return fraudRepository.countAllByObserved(true); + } +} diff --git a/Core/src/main/java/hu/user/core/service/TrainClient.java b/Core/src/main/java/hu/user/core/service/TrainClient.java new file mode 100644 index 0000000..09acf37 --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/TrainClient.java @@ -0,0 +1,33 @@ +package hu.user.core.service; + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) +public class TrainClient { + + private static final String TRANSACTION_IDENTIFIER_FIELD_NAME_PATH = "/transaction_identifier_field_name"; + @Value("${trainUrl}") String trainUrl; + @Autowired private RestTemplate restTemplate; + + public String getTransactionIdentifierFieldNameByEstimatorId(Map queryParamValueByName) { + String url = trainUrl + TRANSACTION_IDENTIFIER_FIELD_NAME_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ResponseEntity responseFromTrainModule = restTemplate.getForEntity(urlTemplate, String.class, params); + String result = responseFromTrainModule.getBody(); + return result; + } + + +} diff --git a/Core/src/main/java/hu/user/core/service/UrlBuilder.java b/Core/src/main/java/hu/user/core/service/UrlBuilder.java new file mode 100644 index 0000000..675618b --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/UrlBuilder.java @@ -0,0 +1,50 @@ +package hu.user.core.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.web.util.UriComponentsBuilder; + +public class UrlBuilder { + + private String url; + private Map queryParams = new HashMap<>(); + + public String getUrl() { + return url; + } + + public Map getQueryParams() { + return queryParams; + } + + public void build(String url, Map queryValueByParamName) { + List paramNames = new ArrayList<>(); + List paramValues = new ArrayList<>(); + for (var entry : queryValueByParamName.entrySet()) { + paramNames.add(entry.getKey()); + paramValues.add(entry.getValue()); + } + buildUrl(url, paramNames); + fillQueryParams(paramNames, paramValues); + } + + private void buildUrl(String url, List queryParamNames) { + String urlTemplate; + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(url); + for (String queryParamName : queryParamNames) { + uriComponentsBuilder = uriComponentsBuilder.queryParam(queryParamName, "{" + queryParamName + "}"); + } + this.url = uriComponentsBuilder.encode().toUriString(); + } + + private void fillQueryParams(List paramNames, List paramValuee) { + Map params = new HashMap<>(); + for (int i = 0; i < paramNames.size(); i++) { + params.put(paramNames.get(i), paramValuee.get(i)); + } + this.queryParams = params; + } +} diff --git a/Core/src/main/java/hu/user/core/service/VoteModul.java b/Core/src/main/java/hu/user/core/service/VoteModul.java new file mode 100644 index 0000000..fdd872b --- /dev/null +++ b/Core/src/main/java/hu/user/core/service/VoteModul.java @@ -0,0 +1,97 @@ +package hu.user.core.service; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import hu.user.core.dto.ResponseFromSingleEstimator; +import hu.user.core.estimators.EstimatorContainer; +import io.spring.guides.gs_producing_web_service.DetectionRequest; +import io.spring.guides.gs_producing_web_service.DetectionResponse; +import io.spring.guides.gs_producing_web_service.GenerateDetectionRequest; +import io.spring.guides.gs_producing_web_service.GenerateGenericDetectionRequest; +import io.spring.guides.gs_producing_web_service.GenericDetectionRequest; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Service +@Getter +@Setter +@Slf4j +public class VoteModul { + + private EstimatorContainer estimatorContainer; + private PredictionService predictionService; + private FraudService fraudService; + + public VoteModul(EstimatorContainer estimatorContainer, PredictionService predictionService, + FraudService fraudService) { + this.estimatorContainer = estimatorContainer; + this.predictionService = predictionService; + this.fraudService = fraudService; + } + + public DetectionResponse voting(GenerateDetectionRequest generateDetectionRequest) { + DetectionRequest detectionRequest = generateDetectionRequest.getDetectionRequest(); + Map responseFromEstimator = + predictionService.getPrediction(detectionRequest); + DetectionResponse detectionResponse = evaluate(responseFromEstimator); + String transactionId = generateDetectionRequest.getTransactionId(); + fraudService.savePredictionResult(transactionId, detectionResponse.getPrediction(), + detectionResponse.getPositiveProbability(), detectionResponse.getNegativeProbability()); + log.info( + "Prediction: " + detectionResponse.getPrediction() + ", positive probability: " + detectionResponse.getPositiveProbability() + ", negative probability: " + detectionResponse.getNegativeProbability()); + return detectionResponse; + } + + public DetectionResponse genericVoting(GenerateGenericDetectionRequest generateGenericDetectionRequest) { + List genericDetectionRequests = generateGenericDetectionRequest.getDetectionRequest(); + Map responseFromEstimator = + predictionService.getGenericPrediction(genericDetectionRequests); + DetectionResponse detectionResponse = evaluate(responseFromEstimator); + String transactionIdentifierFieldName = estimatorContainer.getTransactionIdentifierFieldName(); + String transactionIdentifierValue = null; + for (GenericDetectionRequest request : genericDetectionRequests) { + if (request.getFieldName().equals(transactionIdentifierFieldName)) { + transactionIdentifierValue = request.getValue(); + } + } + fraudService.savePredictionResult(transactionIdentifierValue, detectionResponse.getPrediction(), + detectionResponse.getPositiveProbability(), detectionResponse.getNegativeProbability()); + return detectionResponse; + } + + private DetectionResponse evaluate(Map responseFromEstimator) { + DetectionResponse summaryzedResponse = new DetectionResponse(); + Map estimatorWeightById = estimatorContainer.getEstimatorWeightById(); + int noOKNumber = 0; + int oKNumber = 0; + double noOKProbability = 1; + double oKProbability = 1; + + for (Map.Entry entry : responseFromEstimator.entrySet()) { + int estimatorId = entry.getKey(); + ResponseFromSingleEstimator responseFromSingleEstimator = entry.getValue(); + int weight = estimatorWeightById.get(estimatorId); + if (responseFromSingleEstimator.getPrediction() == 1) { + noOKNumber += weight; + noOKProbability *= responseFromSingleEstimator.getPositiveProbability(); + } else { + oKNumber += weight; + oKProbability *= responseFromSingleEstimator.getNegativeProbability(); + } + } + if (oKNumber > noOKNumber) { + summaryzedResponse.setPrediction(0); + summaryzedResponse.setNegativeProbability(oKProbability); + summaryzedResponse.setPositiveProbability(1 - oKProbability); + } else if (oKNumber < noOKNumber) { + summaryzedResponse.setPrediction(1); + summaryzedResponse.setPositiveProbability(noOKProbability); + summaryzedResponse.setNegativeProbability(1 - noOKProbability); + } + return summaryzedResponse; + } +} diff --git a/Core/src/main/resources/application.properties b/Core/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Core/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/Core/src/main/resources/application.yml b/Core/src/main/resources/application.yml new file mode 100644 index 0000000..a9bb31e --- /dev/null +++ b/Core/src/main/resources/application.yml @@ -0,0 +1,51 @@ +spring: + profiles: + default: "dev" + application: + name: Core + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:3306/common_fraud?serverTimezone=UTC + username: root + password: pwd + jpa: + hibernate: + ddl-auto: create +logging: + level: + root: info + pattern: + console: = %d{yyyy-MM-dd HH:mm:ss} - %msg%n + file: =%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + file: + name: /home/tomi/log/${spring.application.name}.log +server: + port: 8081 +estimatorUrl: http://localhost:8083 +trainUrl: http://localhost:8085 +showProgressRepeatTime: 500 +trainLivenessRepeatTime: 100 + +--- +spring: + config: + activate: + on-profile: dockerized +# jpa: +# show-sql: true +# generate-ddl: true +# hibernate: +# formar_sql: true +server: + port: 8081 +logging: + pattern: + console: = %d{yyyy-MM-dd HH:mm:ss} - %msg%n + file: =%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + file: + name: /opt/app/log/${spring.application.name}.log +estimatorUrl: http://estimator:8083 +trainUrl: http://train:8085 +showProgressRepeatTime: 500 +trainLivenessRepeatTime: 100 + +--- diff --git a/Core/src/main/resources/detection.xsd b/Core/src/main/resources/detection.xsd new file mode 100644 index 0000000..79c726c --- /dev/null +++ b/Core/src/main/resources/detection.xsd @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Core/src/test/java/hu/user/core/CoreApplicationTests.java b/Core/src/test/java/hu/user/core/CoreApplicationTests.java new file mode 100644 index 0000000..8522a48 --- /dev/null +++ b/Core/src/test/java/hu/user/core/CoreApplicationTests.java @@ -0,0 +1,13 @@ +package hu.user.core; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CoreApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/CoreCli/.mvn/wrapper/maven-wrapper.jar b/CoreCli/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..c1dd12f Binary files /dev/null and b/CoreCli/.mvn/wrapper/maven-wrapper.jar differ diff --git a/CoreCli/.mvn/wrapper/maven-wrapper.properties b/CoreCli/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..b74bf7f --- /dev/null +++ b/CoreCli/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/CoreCli/mvnw b/CoreCli/mvnw new file mode 100755 index 0000000..8a8fb22 --- /dev/null +++ b/CoreCli/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/CoreCli/mvnw.cmd b/CoreCli/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/CoreCli/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/CoreCli/pom.xml b/CoreCli/pom.xml new file mode 100644 index 0000000..e8392d5 --- /dev/null +++ b/CoreCli/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.3 + + + hu.user + CoreCli + 0.0.1-SNAPSHOT + CoreCli + CoreCli + + 11 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-web-services + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + com.sun.xml.bind + jaxb-impl + 4.0.1 + runtime + + + jakarta.xml.bind + jakarta.xml.bind-api + + + org.glassfish.jaxb + jaxb-core + 4.0.1 + + + hu.user + CommonDto + 1.0-SNAPSHOT + compile + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 2.5.0 + + + org.jvnet.jaxb2_commons + jaxb2-value-constructor + 3.0 + + + + + xjc + + xjc + + + + + wsdl + + ${project.basedir}/src/main/resources/wsdl/detection.wsdl + + + -Xvalue-constructor + + true + hu.user.corecli + + + + + + diff --git a/CoreCli/src/main/java/hu/user/corecli/CoreCliApplication.java b/CoreCli/src/main/java/hu/user/corecli/CoreCliApplication.java new file mode 100644 index 0000000..54ada8e --- /dev/null +++ b/CoreCli/src/main/java/hu/user/corecli/CoreCliApplication.java @@ -0,0 +1,164 @@ +package hu.user.corecli; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.corecli.dto.ConfusionMatrix; +import hu.user.corecli.service.CoreClient; +import hu.user.corecli.service.EstimatorClient; + +@SpringBootApplication +public class CoreCliApplication implements CommandLineRunner { + + private final static String ADD_ESTIMATOR = "add_estimator"; + private final static String GET_ESTIMATOR = "get_estimator"; + private final static String UPDATE_ESTIMATOR_WEIGHT = "update_estimator_weight"; + private final static String DELETE_ESTIMATOR = "delete_estimator"; + private final static String PREDICT = "predict"; + private final static String CONFUSION_MATRIX = "confusion_matrix"; + + private final static String ID = "id"; + private final static String WEIGHT = "weight"; + + @Autowired EstimatorClient estimatorClient; + @Autowired CoreClient coreClient; + + public static void main(String[] args) { + SpringApplication.run(CoreCliApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + String idAsString; + String weigthAsString; + if (args.length > 0) { + String command = args[0]; + switch (command) { + case ADD_ESTIMATOR: + if (args.length < 2) { + System.out.println("Estimator id is missing"); + break; + } else { + idAsString = args[1]; + if (!isParameterInteger(idAsString, ID)) { + break; + } + } + if (args.length < 3) { + System.out.println("Estimator's weight is missing"); + break; + } else { + weigthAsString = args[2]; + if (!isParameterInteger(weigthAsString, WEIGHT)) { + break; + } + } + List registeredEstimatorIdsInEstimatorModul = + estimatorClient.addEstimatorInEstimatorModule(idAsString); + weigthAsString = args[2]; + List registeredEstimatorIdAndWeigthInCoreModule = + coreClient.addEstimatorInCoreModule(idAsString, weigthAsString); + printResponseFromModules(registeredEstimatorIdsInEstimatorModul, + registeredEstimatorIdAndWeigthInCoreModule); + System.exit(0); + break; + case GET_ESTIMATOR: + registeredEstimatorIdsInEstimatorModul = estimatorClient.getEstimatorInEstimatorModule(); + registeredEstimatorIdAndWeigthInCoreModule = coreClient.getEstimatorInCoreModule(); + printResponseFromModules(registeredEstimatorIdsInEstimatorModul, + registeredEstimatorIdAndWeigthInCoreModule); + System.exit(0); + break; + case UPDATE_ESTIMATOR_WEIGHT: + if (args.length < 2) { + System.out.println("Estimator id is missing"); + break; + } else { + idAsString = args[1]; + if (!isParameterInteger(idAsString, ID)) { + break; + } + } + if (args.length < 3) { + System.out.println("Estimator's weight is missing"); + break; + } else { + weigthAsString = args[2]; + if (!isParameterInteger(weigthAsString, WEIGHT)) { + break; + } + } + registeredEstimatorIdsInEstimatorModul = estimatorClient.getEstimatorInEstimatorModule(); + registeredEstimatorIdAndWeigthInCoreModule = + coreClient.modifyEstimatorWeightInCoreModule(idAsString, weigthAsString); + printResponseFromModules(registeredEstimatorIdsInEstimatorModul, + registeredEstimatorIdAndWeigthInCoreModule); + System.exit(0); + break; + + case DELETE_ESTIMATOR: + if (args.length < 2) { + System.out.println("Estimator id is missing"); + break; + } + idAsString = args[1]; + if (!isParameterInteger(idAsString, ID)) { + break; + } + registeredEstimatorIdsInEstimatorModul = estimatorClient.deleteEstimatorInEstimatorModule(idAsString); + registeredEstimatorIdAndWeigthInCoreModule = coreClient.deleteEstimatorInCoreModule(idAsString); + printResponseFromModules(registeredEstimatorIdsInEstimatorModul, + registeredEstimatorIdAndWeigthInCoreModule); + System.exit(0); + break; + case CONFUSION_MATRIX: + ConfusionMatrix confusionMatrix = coreClient.getConfusionMatrix(); + System.out.println("True positive: " + confusionMatrix.getTruePositive()); + System.out.println("False positive: " + confusionMatrix.getFalsePositive()); + System.out.println("True negative: " + confusionMatrix.getTrueNegative()); + System.out.println("False negative: " + confusionMatrix.getFalseNegative()); + System.exit(0); + default: + System.out.println("Available commmands:"); + System.out.println( + "Register estimator in Estimator and Core module: add_estimator "); + System.out.println( + "List registered estimator in Estimator and Core module: get_estimator"); + System.out.println( + "Update registered estimator's weight in Estimator and Core module: update_estimator "); + System.out.println( + "Delete registered estimator in Estimator and Core module: delete_estimator "); + System.out.println( + "Print system prediction quality: confusion_matrix"); + System.exit(0); + } + } + } + private static boolean isParameterInteger(String parameter, String parameterName) { + boolean isInt = false; + try { + Integer.parseInt(parameter); + isInt = true; + } catch (NumberFormatException e) { + System.out.printf("The %s parameter isn't integer", parameterName); + } + return isInt; + } + + private static void printResponseFromModules(List registeredEstimatorIdsInEstimatorModul, + List registeredEstimatorIdAndWeigthInCoreModule) { + String ids = registeredEstimatorIdsInEstimatorModul.stream().map(e -> String.valueOf(e)) + .collect(Collectors.joining(",", "{", "}")); + System.out.println("Registered estimator ids in Estimator module: " + ids); + String idsAndWeights = registeredEstimatorIdAndWeigthInCoreModule.stream() + .map(e -> "id: " + e.getEstimatorId() + " ; weight: " + e.getWeight()) + .collect(Collectors.joining("; ", "{", "}")); + System.out.println("Registered estimator ids and weights in Core module: " + idsAndWeights); + } +} diff --git a/CoreCli/src/main/java/hu/user/corecli/config/RestConfig.java b/CoreCli/src/main/java/hu/user/corecli/config/RestConfig.java new file mode 100644 index 0000000..764d8cc --- /dev/null +++ b/CoreCli/src/main/java/hu/user/corecli/config/RestConfig.java @@ -0,0 +1,18 @@ +package hu.user.corecli.config; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestConfig { + + @Bean + public RestTemplate getRestTemplate(RestTemplateBuilder builder) { + RestTemplate restTemplate = builder + .build(); + return restTemplate; + + } +} diff --git a/CoreCli/src/main/java/hu/user/corecli/dto/ConfusionMatrix.java b/CoreCli/src/main/java/hu/user/corecli/dto/ConfusionMatrix.java new file mode 100644 index 0000000..5859ff8 --- /dev/null +++ b/CoreCli/src/main/java/hu/user/corecli/dto/ConfusionMatrix.java @@ -0,0 +1,38 @@ +package hu.user.corecli.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ConfusionMatrix { + + private int truePositive; + private int falsePositive; + private int trueNegative; + private int falseNegative; + + public ConfusionMatrix(@JsonProperty(value = "true_positive", required = true) int truePositive, + @JsonProperty(value = "false_positive", required = true) int falsePositive, + @JsonProperty(value = "true_negative", required = true) int trueNegative, + @JsonProperty(value = "false_negative", required = true) int falseNegative) { + + this.truePositive = truePositive; + this.falsePositive = falsePositive; + this.trueNegative = trueNegative; + this.falseNegative = falseNegative; + } + + public int getTruePositive() { + return truePositive; + } + + public int getFalsePositive() { + return falsePositive; + } + + public int getTrueNegative() { + return trueNegative; + } + + public int getFalseNegative() { + return falseNegative; + } +} diff --git a/CoreCli/src/main/java/hu/user/corecli/service/CoreClient.java b/CoreCli/src/main/java/hu/user/corecli/service/CoreClient.java new file mode 100644 index 0000000..f73cb06 --- /dev/null +++ b/CoreCli/src/main/java/hu/user/corecli/service/CoreClient.java @@ -0,0 +1,86 @@ +package hu.user.corecli.service; + +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.corecli.dto.ConfusionMatrix; + +@Service +public class CoreClient { + + private static final String ESTIMATOR_PATH = "/estimator"; + private static final String ESTIMATOR_DELETE_PATH = "/estimator/{id}"; + private static final String CONFUSION_MATRIX_PATH = "/confusion_matrix"; + private static final String WEIGHT = "weight"; + private static final String ID = "id"; + private static final String ESTIMATOR_ID = "estimator_id"; + + @Value("${coreUrl}") URI coreURI; + + private RestTemplate restTemplate; + + public CoreClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public List addEstimatorInCoreModule(String id, String weigth) { + Map input = Map.of(ESTIMATOR_ID, Integer.parseInt(id), WEIGHT, Integer.parseInt(weigth)); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + List result = + exchangeAsMap(ESTIMATOR_PATH, HttpMethod.POST, input, responseType, Collections.emptyMap()); + return result; + } + + public List getEstimatorInCoreModule() { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + List result = + exchangeAsMap(ESTIMATOR_PATH, HttpMethod.GET, Collections.emptyMap(), responseType, Collections.emptyMap()); + return result; + } + + public List modifyEstimatorWeightInCoreModule(String id, String weigth) { + Map input = Map.of(ESTIMATOR_ID, Integer.parseInt(id), WEIGHT, Integer.parseInt(weigth)); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + List result = + exchangeAsMap(ESTIMATOR_PATH, HttpMethod.PUT, input, responseType, Collections.emptyMap()); + return result; + } + public List deleteEstimatorInCoreModule(String idAsString) { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + Map uriParam = Map.of(ID, Integer.parseInt(idAsString)); + List result = + exchangeAsMap(ESTIMATOR_DELETE_PATH, HttpMethod.DELETE, Collections.emptyMap(), responseType, uriParam); + return result; + } + public ConfusionMatrix getConfusionMatrix() { + String url = coreURI + CONFUSION_MATRIX_PATH; + ConfusionMatrix confusionMatrix = restTemplate.getForObject(url, ConfusionMatrix.class); + return confusionMatrix; + } + private List exchangeAsMap(String path, HttpMethod httpMethod, Map input, + ParameterizedTypeReference> responseType, Map uriVariables) { + String url = coreURI + path; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(input, httpHeaders); + return restTemplate.exchange(url, httpMethod, httpEntity, responseType, uriVariables).getBody(); + } +} diff --git a/CoreCli/src/main/java/hu/user/corecli/service/EstimatorClient.java b/CoreCli/src/main/java/hu/user/corecli/service/EstimatorClient.java new file mode 100644 index 0000000..1183d58 --- /dev/null +++ b/CoreCli/src/main/java/hu/user/corecli/service/EstimatorClient.java @@ -0,0 +1,61 @@ +package hu.user.corecli.service; + +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class EstimatorClient { + + private static final String PREDICTION_PATH = "/prediction"; + private static final String ESTIMATOR_PATH = "/estimator"; + private static final String ESTIMATOR_DELETE_PATH = "/estimator/{id}"; + private static final String ID = "id"; + private static final String ESTIMATOR_ID = "estimator_id"; + + @Value("${estimatorUrl}") URI estimatorURI; + private RestTemplate restTemplate; + + public EstimatorClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + public List addEstimatorInEstimatorModule(String id) { + Map input = Map.of(ESTIMATOR_ID, Integer.parseInt(id)); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + List result = exchangeAsList(ESTIMATOR_PATH, HttpMethod.POST, input, responseType, Collections.emptyMap()); + return result; + } + public List getEstimatorInEstimatorModule() { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + List result = exchangeAsList(ESTIMATOR_PATH, HttpMethod.GET, Collections.emptyMap(), responseType, Collections.emptyMap()); + return result; + } + public List deleteEstimatorInEstimatorModule(String idAsString) { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + Map uriParam = Map.of(ID, Integer.parseInt(idAsString)); + List result = exchangeAsList(ESTIMATOR_DELETE_PATH, HttpMethod.DELETE, Collections.emptyMap(), responseType, uriParam); + return result; + } + private List exchangeAsList(String path, HttpMethod httpMethod, Map input, + ParameterizedTypeReference> responseType, Map uriVariables) { + String url = estimatorURI + path; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(input, httpHeaders); + return restTemplate.exchange(url, httpMethod, httpEntity, responseType, uriVariables).getBody(); + } +} diff --git a/CoreCli/src/main/resources/application-mkigui.properties b/CoreCli/src/main/resources/application-mkigui.properties new file mode 100644 index 0000000..13fee12 --- /dev/null +++ b/CoreCli/src/main/resources/application-mkigui.properties @@ -0,0 +1,5 @@ +server.port=8087 +estimatorUrl=http://mkigui:8083 +coreUrl=http://mkigui:8081 +spring.main.banner-mode=off +logging.pattern.console= \ No newline at end of file diff --git a/CoreCli/src/main/resources/application.properties b/CoreCli/src/main/resources/application.properties new file mode 100644 index 0000000..25eb20d --- /dev/null +++ b/CoreCli/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.port=8087 +estimatorUrl=http://localhost:8083 +coreUrl=http://localhost:8081 + diff --git a/CoreCli/src/main/resources/wsdl/detection.wsdl b/CoreCli/src/main/resources/wsdl/detection.wsdl new file mode 100644 index 0000000..288eca3 --- /dev/null +++ b/CoreCli/src/main/resources/wsdl/detection.wsdl @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CoreCli/src/test/java/hu/user/corecli/CoreCliApplicationTests.java b/CoreCli/src/test/java/hu/user/corecli/CoreCliApplicationTests.java new file mode 100644 index 0000000..8839d4a --- /dev/null +++ b/CoreCli/src/test/java/hu/user/corecli/CoreCliApplicationTests.java @@ -0,0 +1,13 @@ +package hu.user.corecli; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CoreCliApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/CoreManager/Dockerfile b/CoreManager/Dockerfile new file mode 100644 index 0000000..de10e57 --- /dev/null +++ b/CoreManager/Dockerfile @@ -0,0 +1,4 @@ +FROM adoptopenjdk:14-jre-hotspot +WORKDIR /opt/app +COPY target/*.jar coremanager.jar +CMD ["java","-jar","coremanager.jar"] \ No newline at end of file diff --git a/CoreManager/pom.xml b/CoreManager/pom.xml new file mode 100644 index 0000000..8a28608 --- /dev/null +++ b/CoreManager/pom.xml @@ -0,0 +1,204 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.3 + + + hu.user + CoreManager + 0.0.1-SNAPSHOT + CoreManager + CoreManager + + 11 + 2.5.3 + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + ZK CE + ZK CE Repository + http://mavensync.zkoss.org/maven2 + + + ZK EVAL + ZK Evaluation Repository + http://mavensync.zkoss.org/eval + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-web-services + + + org.zkoss.zkspringboot + zkspringboot-starter + pom + ${zkspringboot.version} + + + org.zkoss.zk + zkplus + 9.6.0-Eval + + + + mysql + mysql-connector-java + runtime + + + org.projectlombok + lombok + true + + + com.google.guava + guava + 31.0.1-jre + + + com.opencsv + opencsv + 4.1 + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + org.glassfish.jaxb + jaxb-core + 4.0.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.sun.xml.bind + jaxb-impl + 4.0.1 + runtime + + + jakarta.xml.bind + jakarta.xml.bind-api + + + hu.user + CommonDto + 1.0-SNAPSHOT + compile + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 2.5.0 + + + org.jvnet.jaxb2_commons + jaxb2-value-constructor + 3.0 + + + + + xjc + + xjc + + + + + wsdl + + ${project.basedir}/src/main/resources/wsdl/detection.wsdl + + + -Xvalue-constructor + + true + hu.user.coremanager + + + + + diff --git a/CoreManager/src/main/java/hu/user/coremanager/CoreManagerApplication.java b/CoreManager/src/main/java/hu/user/coremanager/CoreManagerApplication.java new file mode 100644 index 0000000..39168d6 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/CoreManagerApplication.java @@ -0,0 +1,13 @@ +package hu.user.coremanager; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CoreManagerApplication { + + public static void main(String[] args) { + SpringApplication.run(CoreManagerApplication.class, args); + } + +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/config/CoreSoapClientConfiguration.java b/CoreManager/src/main/java/hu/user/coremanager/config/CoreSoapClientConfiguration.java new file mode 100644 index 0000000..b60c2f6 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/config/CoreSoapClientConfiguration.java @@ -0,0 +1,30 @@ +package hu.user.coremanager.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; + +import hu.user.coremanager.service.CoreSoapClient; + +@Configuration +public class CoreSoapClientConfiguration { + + @Bean + public Jaxb2Marshaller marshaller() { + Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); + // this package must match the package in the specified in + // pom.xml +// marshaller.setContextPath("com.example.consumingwebservice.wsdl"); + marshaller.setContextPath("hu.user.coremanager"); + return marshaller; + } + + @Bean + public CoreSoapClient coreSoapClient(Jaxb2Marshaller marshaller) { + CoreSoapClient client = new CoreSoapClient(); + client.setDefaultUri("http://localhost:8081/ws"); + client.setMarshaller(marshaller); + client.setUnmarshaller(marshaller); + return client; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/config/DevelopmentConfig.java b/CoreManager/src/main/java/hu/user/coremanager/config/DevelopmentConfig.java new file mode 100644 index 0000000..03e1fae --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/config/DevelopmentConfig.java @@ -0,0 +1,36 @@ +package hu.user.coremanager.config; + +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.zkoss.lang.Library; +import org.zkoss.zk.ui.WebApps; + +@Configuration +@Profile("dev") +public class DevelopmentConfig { + private static Logger logger = LoggerFactory.getLogger(DevelopmentConfig.class); + + @PostConstruct + public void initDevelopmentProperties() throws Exception { + logger.info("**************************************************************"); + logger.info("**** ZK-Springboot-Demo: development configuration active ****"); + logger.info("**************************************************************"); + + //disable various caches to avoid server restarts + Library.setProperty("org.zkoss.zk.ZUML.cache", "false"); + Library.setProperty("org.zkoss.zk.WPD.cache", "false"); + Library.setProperty("org.zkoss.zk.WCS.cache", "false"); + Library.setProperty("org.zkoss.web.classWebResource.cache", "false"); + Library.setProperty("org.zkoss.util.label.cache", "false"); + + // enable non minified js + WebApps.getCurrent().getConfiguration().setDebugJS(true); + + // enable for debugging MVVM commands and binding (very verbose) + Library.setProperty("org.zkoss.bind.DebuggerFactory.enable", "false"); + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/config/RestConfig.java b/CoreManager/src/main/java/hu/user/coremanager/config/RestConfig.java new file mode 100644 index 0000000..071fdd3 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/config/RestConfig.java @@ -0,0 +1,21 @@ +package hu.user.coremanager.config; + +import java.time.Duration; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestConfig { + + @Bean + public RestTemplate getRestTemplate(RestTemplateBuilder builder) { + RestTemplate restTemplate = builder + .setReadTimeout(Duration.ofSeconds(7)) + .build(); + return restTemplate; + + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/ConfusionMatrixDto.java b/CoreManager/src/main/java/hu/user/coremanager/dto/ConfusionMatrixDto.java new file mode 100644 index 0000000..63f1826 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/ConfusionMatrixDto.java @@ -0,0 +1,19 @@ +package hu.user.coremanager.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class ConfusionMatrixDto { + + private int tp; + private int tn; + private int fp; + private int fn; + + + +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/DirectoryProperty.java b/CoreManager/src/main/java/hu/user/coremanager/dto/DirectoryProperty.java new file mode 100644 index 0000000..ea33922 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/DirectoryProperty.java @@ -0,0 +1,18 @@ +package hu.user.coremanager.dto; + +import java.io.File; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class DirectoryProperty { + + private String displayName; + private File directory; + +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/DownStreamErrorDto.java b/CoreManager/src/main/java/hu/user/coremanager/dto/DownStreamErrorDto.java new file mode 100644 index 0000000..eee6eb5 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/DownStreamErrorDto.java @@ -0,0 +1,21 @@ +package hu.user.coremanager.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; + +@Getter +public class DownStreamErrorDto { + + private int errorCode; + private String errorName; + private String errorMessage; + + public DownStreamErrorDto(@JsonProperty(value = "error_code", required = true) int errorCode, + @JsonProperty(value = "error_name", required = true) String errorName, + @JsonProperty(value = "error_message", required = true) String errorMessage) { + this.errorCode = errorCode; + this.errorName = errorName; + this.errorMessage = errorMessage; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorMetricsDto.java b/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorMetricsDto.java new file mode 100644 index 0000000..28ed470 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorMetricsDto.java @@ -0,0 +1,35 @@ +package hu.user.coremanager.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class EstimatorMetricsDto { + private int id; + private int tp; + private int tn; + private int fp; + private int fn; + private double sensitivity; + private double specifity; + private double accuracy; + private double balancedAccuracy; + private double prec; + private double recall; + private double ppv; + private double npv; + private double fnr; + private double fpr; + private double fdr; + private double _for; + private double f1; + private double f05; + private double f2; + private double mcc; + private double rocauc; + private double youden; + +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorParameter.java b/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorParameter.java new file mode 100644 index 0000000..a170db3 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/EstimatorParameter.java @@ -0,0 +1,19 @@ +package hu.user.coremanager.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EstimatorParameter { + + private int estimatorId; + private int weight; + + public EstimatorParameter(@JsonProperty(value = "estimator_id",required = true) int estimatorId, int weight) { + this.estimatorId = estimatorId; + this.weight = weight; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/FieldProperty.java b/CoreManager/src/main/java/hu/user/coremanager/dto/FieldProperty.java new file mode 100644 index 0000000..f003e5f --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/FieldProperty.java @@ -0,0 +1,14 @@ +package hu.user.coremanager.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class FieldProperty { + + private String fieldName; + private String fieldType; +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/FileProperty.java b/CoreManager/src/main/java/hu/user/coremanager/dto/FileProperty.java new file mode 100644 index 0000000..21085a8 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/FileProperty.java @@ -0,0 +1,14 @@ +package hu.user.coremanager.dto; + +import java.io.File; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class FileProperty { + + private File file; + private String fileName; +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/GenericRecordCollectionDto.java b/CoreManager/src/main/java/hu/user/coremanager/dto/GenericRecordCollectionDto.java new file mode 100644 index 0000000..f6b7068 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/GenericRecordCollectionDto.java @@ -0,0 +1,28 @@ +package hu.user.coremanager.dto; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class GenericRecordCollectionDto { + private List fieldTypes = new ArrayList<>(); + private List fieldNames = new ArrayList<>(); + private List> records = new ArrayList<>(); + + // @formatter:off + public GenericRecordCollectionDto( + @JsonProperty(value = "field_types", required = true) List fieldTypes, + @JsonProperty(value = "field_names", required = true) List fieldNames, + @JsonProperty(value = "records", required = true) List> records) { + this.fieldTypes = fieldTypes; + this.fieldNames = fieldNames; + this.records = records; + } + // @formatter:on +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsAndTrainTaskName.java b/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsAndTrainTaskName.java new file mode 100644 index 0000000..b7dd1f8 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsAndTrainTaskName.java @@ -0,0 +1,12 @@ +package hu.user.coremanager.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class MetricsAndTrainTaskName { + + private String trainTaskName; + private MetricsDto metricsDto; +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsDto.java b/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsDto.java new file mode 100644 index 0000000..3281aea --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/MetricsDto.java @@ -0,0 +1,91 @@ +package hu.user.coremanager.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MetricsDto { + + private int id; + + private int estimatorId; + private int truePositive; + private int trueNegative; + private int falsePositive; + private int falseNegative; + private double accuracy; + private double balancedAccuracy; + private double sensitivity; + private double specifity; + private double prec; + private double recall; + private double ppv; + private double npv; + private double fnr; + private double fpr; + private double fdr; + private double _for; + private double f1; + private double f05; + private double f2; + private double mcc; + private double rocauc; + private double youden; + + // @formatter:off + public MetricsDto( + @JsonProperty(value = "id", required = true) int id, + @JsonProperty(value = "estimator_id", required = true) int estimatorId, + @JsonProperty(value = "TP", required = true) int truePositive, + @JsonProperty(value = "TN", required = true) int trueNegative, + @JsonProperty(value = "FP", required = true) int falsePositive, + @JsonProperty(value = "FN", required = true) int falseNegative, + @JsonProperty(value = "accuracy", required = true) double accuracy, + @JsonProperty(value = "balanced_accuracy", required = true) double balancedAccuracy, + @JsonProperty(value = "sensitivity", required = true) double sensitivity, + @JsonProperty(value = "specificity", required = true) double specifity, + @JsonProperty(value = "precision", required = true) double prec, + @JsonProperty(value = "recall", required = true) double recall, + @JsonProperty(value = "PPV", required = true) double ppv, + @JsonProperty(value = "NPV", required = true) double npv, + @JsonProperty(value = "FNR", required = true) double fnr, + @JsonProperty(value = "FPR", required = true) double fpr, + @JsonProperty(value = "FDR", required = true) double fdr, + @JsonProperty(value = "FOR", required = true) double _for, + @JsonProperty(value = "f1", required = true) double f1, + @JsonProperty(value = "f0.5", required = true) double f05, + @JsonProperty(value = "f2", required = true) double f2, + @JsonProperty(value = "MCC", required = true) double mcc, + @JsonProperty(value = "ROCAUC", required = true) double rocauc, + @JsonProperty(value = "Youdens_statistic", required = true) double youden) + // @formatter:on + { + this.id = id; + this.estimatorId = estimatorId; + this.truePositive = truePositive; + this.trueNegative = trueNegative; + this.falsePositive = falsePositive; + this.falseNegative = falseNegative; + this.accuracy = accuracy; + this.balancedAccuracy = balancedAccuracy; + this.sensitivity = sensitivity; + this.specifity = specifity; + this.prec = prec; + this.recall = recall; + this.ppv = ppv; + this.npv = npv; + this.fnr = fnr; + this.fpr = fpr; + this.fdr = fdr; + this._for = _for; + this.f1 = f1; + this.f05 = f05; + this.f2 = f2; + this.mcc = mcc; + this.rocauc = rocauc; + this.youden = youden; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/dto/ObservedValue.java b/CoreManager/src/main/java/hu/user/coremanager/dto/ObservedValue.java new file mode 100644 index 0000000..a532d9b --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/dto/ObservedValue.java @@ -0,0 +1,14 @@ +package hu.user.coremanager.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class ObservedValue { + + private String uuid; + private int observedFraud; +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/exception/ParametersExistYetException.java b/CoreManager/src/main/java/hu/user/coremanager/exception/ParametersExistYetException.java new file mode 100644 index 0000000..b9e19a9 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/exception/ParametersExistYetException.java @@ -0,0 +1,14 @@ +package hu.user.coremanager.exception; + +public class ParametersExistYetException extends RuntimeException{ + + private String errorMessage; + + public ParametersExistYetException(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/CoreClient.java b/CoreManager/src/main/java/hu/user/coremanager/service/CoreClient.java new file mode 100644 index 0000000..61eb606 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/CoreClient.java @@ -0,0 +1,137 @@ +package hu.user.coremanager.service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import hu.user.common.dto.ConfusionMatrixDto; +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.coremanager.dto.ObservedValue; + +@Service +public class CoreClient { + + @Value("${coreUrl}") String coreUrl; + @Autowired private RestTemplate restTemplate; + + private static final String ESTIMATOR_PATH = "/estimator"; + private static final String OBSERVED_PATH = "/observed"; + private static final String TRANSACTIONM_PATH = "/transaction"; + private static final String CONFUSION_MATRIX_PATH = "/confusion_matrix"; + private static final String TRANSACTION_CLEAR_PATH = "/transaction_clear"; + + private static final String ID = "id"; + + public List registryEstimator(EstimatorRegistryParameterDto estimatorRegistryParameterDto) { + String url = coreUrl + ESTIMATOR_PATH; + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(estimatorRegistryParameterDto, httpHeaders); + ResponseEntity> responseFromCoreModul = + restTemplate.exchange(url, HttpMethod.POST, httpEntity, typeReference, Collections.emptyMap()); + List registeredEstimatorDtos = responseFromCoreModul.getBody(); + return registeredEstimatorDtos; + } + + public List getRegisteredEstimators() { + String url = coreUrl + ESTIMATOR_PATH; + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(httpHeaders); + ResponseEntity> responseFromCoreModul = + restTemplate.exchange(url, HttpMethod.GET, httpEntity, typeReference); + List registeredEstimatorDtos = responseFromCoreModul.getBody(); + return registeredEstimatorDtos; + } + + public List deleteEstimator(Integer id) { + String url = coreUrl + ESTIMATOR_PATH + "/{id}"; + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(httpHeaders); + ResponseEntity> responseFromCoreModul = + restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, typeReference, Map.of(ID, id)); + List registeredEstimatorDtos = responseFromCoreModul.getBody(); + return registeredEstimatorDtos; + } + + public List modifyEstimatorWeight(EstimatorRegistryParameterDto estimatorRegistryParameterDto) { + String url = coreUrl + ESTIMATOR_PATH; + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(estimatorRegistryParameterDto, httpHeaders); + ResponseEntity> responseFromCoreModul = + restTemplate.exchange(url, HttpMethod.PUT, httpEntity, typeReference, Collections.emptyMap()); + List registeredEstimatorDtos = responseFromCoreModul.getBody(); + return registeredEstimatorDtos; + } + + public ConfusionMatrixDto getSysTemConfusionMatrix() { + String url = coreUrl + CONFUSION_MATRIX_PATH; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + ResponseEntity responseFromCoreModul = restTemplate.getForEntity(url, ConfusionMatrixDto.class); + return responseFromCoreModul.getBody(); + } + + public boolean uploadToCoreModuleObservedValues(List observedValues) { + String url = coreUrl + OBSERVED_PATH; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(observedValues,httpHeaders); + ResponseEntity responseFromCoreModul = + restTemplate.exchange(url, HttpMethod.POST, httpEntity, ResponseEntity.class, Collections.emptyMap()); + if (responseFromCoreModul.getStatusCode().is2xxSuccessful()) { + return true; + } else { + return false; + } + } + public int getAllObservedTransaction() { + String url = coreUrl + OBSERVED_PATH; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + ResponseEntity responseFromCoreModul = restTemplate.getForEntity(url, Integer.class); + return responseFromCoreModul.getBody(); + } + public int getAllTransaction() { + String url = coreUrl + TRANSACTIONM_PATH; + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + ResponseEntity responseFromCoreModul = restTemplate.getForEntity(url, Integer.class); + return responseFromCoreModul.getBody(); + } + + public void clearAllTransaction() { + String url = coreUrl + TRANSACTION_CLEAR_PATH; + ResponseEntity responseFromCoreModul = restTemplate.postForEntity(url, null, null, Collections.emptyMap()); + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/CoreSoapClient.java b/CoreManager/src/main/java/hu/user/coremanager/service/CoreSoapClient.java new file mode 100644 index 0000000..0e2c54e --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/CoreSoapClient.java @@ -0,0 +1,25 @@ +package hu.user.coremanager.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.ws.client.core.support.WebServiceGatewaySupport; +import org.springframework.ws.soap.client.core.SoapActionCallback; + +import hu.user.coremanager.DetectionResponse; +import hu.user.coremanager.GenerateDetectionResponse; +import hu.user.coremanager.GenerateGenericDetectionRequest; + +public class CoreSoapClient extends WebServiceGatewaySupport { + + @Value("${coreSoapUri}") String coreSoapUri; + + public DetectionResponse getResponse(GenerateGenericDetectionRequest request) { + + + GenerateDetectionResponse response = (GenerateDetectionResponse) getWebServiceTemplate() + .marshalSendAndReceive(coreSoapUri, request, + new SoapActionCallback( + "http://spring.io/guides/gs-producing-web-service/generateGenericDetectionRequest")); + + return response.getDetectionResponse(); + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/EstimatorClient.java b/CoreManager/src/main/java/hu/user/coremanager/service/EstimatorClient.java new file mode 100644 index 0000000..b702041 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/EstimatorClient.java @@ -0,0 +1,39 @@ +package hu.user.coremanager.service; + +import java.util.Arrays; +import java.util.EmptyStackException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.coremanager.dto.EstimatorParameter; + +@Service +public class EstimatorClient { + + private static final String ID = "id"; + + @Value("${estimatorUrl}") String estimatorUrl; + @Autowired private RestTemplate restTemplate; + + private static final String ESTIMATOR_PATH = "/estimator"; + + public List registerEstimator(EstimatorRegistryParameterDto estimatorRegistryParameterDto) { + String url = estimatorUrl + ESTIMATOR_PATH; + int[] result = restTemplate.postForEntity(url, estimatorRegistryParameterDto, int[].class).getBody(); + return Arrays.stream(result).boxed().collect(Collectors.toList()); + } + + public List deleteEstimator(int id) { + String url = estimatorUrl + ESTIMATOR_PATH + "/{id}"; + int[] result = restTemplate.exchange(url, HttpMethod.DELETE, null, int[].class, Map.of(ID, id)).getBody(); + return Arrays.stream(result).boxed().collect(Collectors.toList()); + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/EvaluationService.java b/CoreManager/src/main/java/hu/user/coremanager/service/EvaluationService.java new file mode 100644 index 0000000..10269b8 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/EvaluationService.java @@ -0,0 +1,64 @@ +package hu.user.coremanager.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import hu.user.coremanager.DetectionResponse; +import hu.user.coremanager.GenerateGenericDetectionRequest; +import hu.user.coremanager.GenericDetectionRequest; +import hu.user.coremanager.dto.GenericRecordCollectionDto; + +@Service +public class EvaluationService { + private static final String SCHEMA_NAME = "schema_name"; + private static final String TABLE_NAME = "table_name"; + private static final String PREDICTED_POSITIVE = "predicted_positive"; + private static final String PREDICTED_NEGATIVE = "predicted_negative"; + + private TrainClient trainClient; + private CoreSoapClient coreSoapClient; + + public EvaluationService(TrainClient trainClient, CoreSoapClient coreSoapClient) { + + this.trainClient = trainClient; + this.coreSoapClient = coreSoapClient; + } + + public Map predictForEvaluation(String schema, String table) { + int positivePredictionCaseNumber = 0; + int negativePredictionCaseNumber = 0; + GenericRecordCollectionDto genericRecordCollectionDto = + trainClient.getGenericRecordsForEvaluation(Map.of(SCHEMA_NAME, schema, TABLE_NAME, table)); + List> records = genericRecordCollectionDto.getRecords(); + List fieldNames = genericRecordCollectionDto.getFieldNames(); + int fieldNumber = fieldNames.size(); + List genericDetectionRequests = new ArrayList<>(); + for (List record : records) { + for (int i = 0; i < fieldNumber; i++) { + GenericDetectionRequest genericDetectionRequest = + new GenericDetectionRequest(fieldNames.get(i), record.get(i)); + genericDetectionRequest.setFieldName(fieldNames.get(i)); + genericDetectionRequests.add(genericDetectionRequest); + } + GenerateGenericDetectionRequest generateGenericDetectionRequest = + new GenerateGenericDetectionRequest(genericDetectionRequests); + + DetectionResponse response = coreSoapClient.getResponse(generateGenericDetectionRequest); + if (response.getPrediction() == 0) { + negativePredictionCaseNumber++; + } else { + positivePredictionCaseNumber++; + } + System.out.println("Prediction: " + response.getPrediction()); + System.out.println("Positive probability: " + response.getPositiveProbability()); + System.out.println("Negatíve probability: " + response.getNegativeProbability()); + + } + Map result = Map.of(PREDICTED_POSITIVE, positivePredictionCaseNumber, PREDICTED_NEGATIVE, + negativePredictionCaseNumber); + return result; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/FileHandler.java b/CoreManager/src/main/java/hu/user/coremanager/service/FileHandler.java new file mode 100644 index 0000000..af718d4 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/FileHandler.java @@ -0,0 +1,37 @@ +package hu.user.coremanager.service; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.opencsv.CSVReader; +import com.opencsv.CSVReaderBuilder; + +import hu.user.coremanager.dto.ObservedValue; + +@Service +public class FileHandler { + + public List readObservedValueFromCsvFile(File csvFile) { + List observedValues = new ArrayList<>(); + try { + FileReader filereader = new FileReader(csvFile); + CSVReader csvReader = new CSVReaderBuilder(filereader).withSkipLines(1).build(); + List allData = csvReader.readAll(); + for (String[] row : allData) { + ObservedValue observedValue = new ObservedValue(row[0], Integer.valueOf(row[1])); + observedValues.add(observedValue); + } + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + return observedValues; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/TrainClient.java b/CoreManager/src/main/java/hu/user/coremanager/service/TrainClient.java new file mode 100644 index 0000000..33fdb3e --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/TrainClient.java @@ -0,0 +1,239 @@ +package hu.user.coremanager.service; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import hu.user.coremanager.dto.ConfusionMatrixDto; +import hu.user.coremanager.dto.GenericRecordCollectionDto; +import hu.user.coremanager.dto.MetricsDto; +import hu.user.coremanager.exception.ParametersExistYetException; +import lombok.extern.slf4j.Slf4j; + +@Service +@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) +@Slf4j +public class TrainClient { + + private static final String OK = "OK"; + private static final String ENCODING_AND_FEATURE_ENGINEERING_PATH = "/encoding_and_feature_engineering_plan"; + private static final String TRAIN_TASK_PATH = "/train_task"; + private static final String FIT_PATH = "/fit"; + private static final String SCHEMA_PATH = "/schema"; + private static final String TABLE_PATH = "/table"; + private static final String FIELD_NAME_AND_TYPE_PATH = "/field_name_and_type"; + private static final String FIELD_NAME_IN_ORIDNAL_POSITION_PATH = "/field_name_in_ordinal_position"; + private static final String FIELD_TYPE_IN_ORIDNAL_POSITION_PATH = "/field_type_in_ordinal_position"; + private static final String RECORD_PATH = "/record"; + private static final String METRICS_PATH = "/metrics"; + private static final String CPU_PATH = "/cpu"; + private static final String ESTIMATOR_PATH = "/estimator"; + private static final String CONFUSION_MATRIX_PATH = "/confusion_matrix"; + private static final String LIVENESS_PATH = "/liveness"; + private static final String TABLE_INFO_PATH = "/table_info"; + private static final String GENERIC_RECORD_PATH = "/generic_records"; + private static final String TRAIN_TASK_NAME_BY_ESTIMATOR_ID_PATH = "/train_task_name_by_estimator_id"; + + @Value("${trainUrl}") String trainUrl; + @Value("${home.directory}") private String homeDirectory; + @Autowired private RestTemplate restTemplate; + +// public TrainModuleStatus testLiveness() { +// TrainModuleStatus trainModuleStatus = null; +// String url = trainUrl + LIVENESS_PATH; +// try { +// LivenessDto livenessDto = restTemplate.getForEntity(url, LivenessDto.class).getBody(); +// if (livenessDto.getResponse().equals(OK)) { +// trainModuleStatus = TrainModuleStatus.OK; +// } +// } catch (ResourceAccessException exception) { +// if (exception.getCause() instanceof ConnectException) { +// trainModuleStatus = TrainModuleStatus.NOT_ACCESSIBLE; +// } +// if (exception.getCause() instanceof SocketTimeoutException) { +// //TO-DO logging +// trainModuleStatus = TrainModuleStatus.RESPONSE_TIMEOUT; +// } +// } +// return trainModuleStatus; +// } + + public String getHomeDirectory() { + return homeDirectory; + } + + public int getCpuCoreNumber() { + String url = trainUrl + CPU_PATH; + int coreNumber = restTemplate.getForEntity(url, Integer.class).getBody(); + return coreNumber; + } + + public String[] getSchemas() { + String url = trainUrl + SCHEMA_PATH; + String[] schemas = restTemplate.getForEntity(url, String[].class).getBody(); + return schemas; + } + + public String[] getTables(Map queryParamValueByName) { + String url = trainUrl + TABLE_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + String[] tables = restTemplate.getForEntity(urlTemplate, String[].class, params).getBody(); + return tables; + } + + public String[] getFieldNameInOrdinalPosition(Map queryParamValueByName) { + String url = trainUrl + FIELD_NAME_IN_ORIDNAL_POSITION_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + String[] tables = restTemplate.getForEntity(urlTemplate, String[].class, params).getBody(); + return tables; + } + public String[] getFieldTypeInOrdinalPosition(Map queryParamValueByName) { + String url = trainUrl + FIELD_TYPE_IN_ORIDNAL_POSITION_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + String[] tables = restTemplate.getForEntity(urlTemplate, String[].class, params).getBody(); + return tables; + } + + public Map getFieldTypeByName(Map queryParamValueByName) { + String url = trainUrl + FIELD_NAME_AND_TYPE_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + Map result = + restTemplate.exchange(urlTemplate, HttpMethod.GET, null, typeReference, params).getBody(); + return result; + } + + public String getRecordsAsString(Map queryParamValueByName) { + String url = trainUrl + RECORD_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ResponseEntity tableProperties = restTemplate.getForEntity(urlTemplate, String.class, params); + String result = tableProperties.getBody(); + return result; + } + + public List> getRecords(Map queryParamValueByName) { + String url = trainUrl + RECORD_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ParameterizedTypeReference>> typeReference = new ParameterizedTypeReference<>() { + }; + List> records = exchangeAsList(urlTemplate, typeReference, params); + return records; + } + + public Map getFeatureSelectors() { + return useCommmonQuery("/available_feature_selector"); + } + + public Map getSamplers() { + return useCommmonQuery("/available_sampler"); + } + + public Map getScalers() { + return useCommmonQuery("/available_scaler"); + } + + public Map getModels() { + return useCommmonQuery("/available_model"); + } + + public Map useCommmonQuery(String path) { + String url = trainUrl + path; + Map parameters = restTemplate.getForEntity(url, Map.class).getBody(); + return parameters; + } + + public List getMetrics(Map queryParamValueByName) { + String url = trainUrl + METRICS_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + List metrics = exchangeAsList(urlTemplate, typeReference, params); + return metrics; + } + + public ConfusionMatrixDto getConfusionMatrixElements(Map queryParamValueByName) { + String url = trainUrl + CONFUSION_MATRIX_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ResponseEntity responseEntity = + restTemplate.getForEntity(urlTemplate, ConfusionMatrixDto.class, params); + return responseEntity.getBody(); + } + + public GenericRecordCollectionDto getGenericRecordsForEvaluation(Map queryParamValueByName) { + String url = trainUrl + GENERIC_RECORD_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ResponseEntity responseEntity = + restTemplate.getForEntity(urlTemplate, GenericRecordCollectionDto.class, params); + return responseEntity.getBody(); + } + + public String getTrainTaskNameByEstimatorId(Map queryParamValueByName) { + String url = trainUrl + TRAIN_TASK_NAME_BY_ESTIMATOR_ID_PATH; + UrlBuilder urlBuilder = new UrlBuilder(); + urlBuilder.build(url, queryParamValueByName); + String urlTemplate = urlBuilder.getUrl(); + Map params = urlBuilder.getQueryParams(); + ResponseEntity responseEntity = + restTemplate.getForEntity(urlTemplate, String.class, params); + return responseEntity.getBody(); + } + + + public Integer addGenericParameters(T parameters, String path) { + String url = trainUrl + path; + try { + ResponseEntity responseFromTrainModule = + restTemplate.postForEntity(url, parameters, Integer.class); + return responseFromTrainModule.getBody(); + } catch (HttpClientErrorException httpClientErrorException) { + String errorMessage = httpClientErrorException.getResponseBodyAsString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + private List exchangeAsList(String uri, ParameterizedTypeReference> responseType, + Map uriVariables) { + return restTemplate.exchange(uri, HttpMethod.GET, null, responseType, uriVariables).getBody(); + } + +} + diff --git a/CoreManager/src/main/java/hu/user/coremanager/service/UrlBuilder.java b/CoreManager/src/main/java/hu/user/coremanager/service/UrlBuilder.java new file mode 100644 index 0000000..82fc4ae --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/service/UrlBuilder.java @@ -0,0 +1,50 @@ +package hu.user.coremanager.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.web.util.UriComponentsBuilder; + +public class UrlBuilder { + + private String url; + private Map queryParams = new HashMap<>(); + + public String getUrl() { + return url; + } + + public Map getQueryParams() { + return queryParams; + } + + public void build(String url, Map queryValueByParamName) { + List paramNames = new ArrayList<>(); + List paramValues = new ArrayList<>(); + for (var entry : queryValueByParamName.entrySet()) { + paramNames.add(entry.getKey()); + paramValues.add(entry.getValue()); + } + buildUrl(url, paramNames); + fillQueryParams(paramNames, paramValues); + } + + private void buildUrl(String url, List queryParamNames) { + String urlTemplate; + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(url); + for (String queryParamName : queryParamNames) { + uriComponentsBuilder = uriComponentsBuilder.queryParam(queryParamName, "{" + queryParamName + "}"); + } + this.url = uriComponentsBuilder.encode().toUriString(); + } + + private void fillQueryParams(List paramNames, List paramValuee) { + Map params = new HashMap<>(); + for (int i = 0; i < paramNames.size(); i++) { + params.put(paramNames.get(i), paramValuee.get(i)); + } + this.queryParams = params; + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/viewmodel/EstimatorRegistryViewModel.java b/CoreManager/src/main/java/hu/user/coremanager/viewmodel/EstimatorRegistryViewModel.java new file mode 100644 index 0000000..5017d3f --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/viewmodel/EstimatorRegistryViewModel.java @@ -0,0 +1,164 @@ +package hu.user.coremanager.viewmodel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.zkoss.bind.BindUtils; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; +import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.zk.ui.select.annotation.WireVariable; +import org.zkoss.zul.ListModelList; + +import hu.user.common.dto.EstimatorRegistryParameterDto; +import hu.user.coremanager.dto.MetricsAndTrainTaskName; +import hu.user.coremanager.dto.MetricsDto; +import hu.user.coremanager.service.CoreClient; +import hu.user.coremanager.service.EstimatorClient; +import hu.user.coremanager.service.TrainClient; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class) +public class EstimatorRegistryViewModel { + + private static final String ESTIMATOR_ID = "estimator_id"; + + @WireVariable private TrainClient trainClient; + @WireVariable private CoreClient coreClient; + @WireVariable private EstimatorClient estimatorClient; + + private Integer chosenEstimatorId; + private List availableWeights = new ArrayList<>(); + private int currentWeight; + + private int truePositive; + private int trueNegative; + private int falsePositive; + private int falseNegative; + + private Map registeredEstimatorWeightById = new HashMap<>(); + private ListModelList estimatorRegistryParameters = new ListModelList<>(); + + private ListModelList metrics = new ListModelList<>(); + private ListModelList metricsAndTrainTaskNames; + + private Integer selected; + + private Integer chosenWeight; + + private boolean registryButtonDisabled; + private boolean updateButtonDisabled; + private boolean enablePredictionButtonDisabled; + private boolean disablePredictionButtonDisabled; + + @Init + public void init() { + registryButtonDisabled = true; + fillMetrics(); + availableWeights = IntStream.rangeClosed(1, 8).boxed().collect(Collectors.toList()); + List responseFromCore = + coreClient.getRegisteredEstimators(); + estimatorRegistryParameters = new ListModelList<>(responseFromCore); + if (!responseFromCore.isEmpty()) { + BindUtils.postGlobalCommand(null, null, "enableTestPredictionStartButton", null); + } + } + + public void fillMetrics() { + List metricsAndTrainTaskNameCollection = new ArrayList<>(); + List metricsDtos = trainClient.getMetrics(Collections.emptyMap()); + for (MetricsDto metricsDto : metricsDtos) { + int estimatorId = metricsDto.getEstimatorId(); + String trainTaskName = + trainClient.getTrainTaskNameByEstimatorId(Map.of(ESTIMATOR_ID, String.valueOf(estimatorId))); + MetricsAndTrainTaskName metricsAndTrainTaskName = new MetricsAndTrainTaskName(trainTaskName, metricsDto); + metricsAndTrainTaskNameCollection.add(metricsAndTrainTaskName); + } + metricsAndTrainTaskNames = new ListModelList<>(metricsAndTrainTaskNameCollection); + } + + @Command + @NotifyChange({"chosenEstimatorId", "truePositive", "trueNegative", "falsePositive", "falseNegative"}) + public void selectEstimatorId(@BindingParam("param") int selectedEstimatorId) { + for (MetricsAndTrainTaskName metricsAndTrantaskName : metricsAndTrainTaskNames) { + if (metricsAndTrantaskName.getMetricsDto().getId() == selectedEstimatorId) { + truePositive = metricsAndTrantaskName.getMetricsDto().getTruePositive(); + trueNegative = metricsAndTrantaskName.getMetricsDto().getTrueNegative(); + falsePositive = metricsAndTrantaskName.getMetricsDto().getFalsePositive(); + falseNegative = metricsAndTrantaskName.getMetricsDto().getFalseNegative(); + } + if (!estimatorRegistryParameters.stream().map(e -> e.getEstimatorId()).collect(Collectors.toList()) + .contains(selectedEstimatorId)) { + chosenEstimatorId = selectedEstimatorId; + } + } +// estimatorId = metrics.get(selected).getId(); + } + + @Command + @NotifyChange({"estimatorRegistryParameters", "chosenEstimatorId", "chosenWeight"}) + public void registryEstimator() { + EstimatorRegistryParameterDto estimatorRegistryParameterDto = + new EstimatorRegistryParameterDto(chosenEstimatorId, chosenWeight); + List responseFromCore = + coreClient.registryEstimator(estimatorRegistryParameterDto); + estimatorRegistryParameters = new ListModelList<>(responseFromCore); + responseFromCore.stream().map(e -> "id: " + e.getEstimatorId() + " weight: " + e.getWeight()) + .collect(Collectors.toList()).forEach(System.out::println); + List responseFromEstimator = estimatorClient.registerEstimator(estimatorRegistryParameterDto); + responseFromEstimator.forEach(System.out::println); + if (!responseFromEstimator.isEmpty()) { + BindUtils.postGlobalCommand(null, null, "enableTestPredictionStartButton", null); + } + chosenEstimatorId = null; + chosenWeight = null; + } + + @Command + public void increaseWeight(@BindingParam("param") int chosenEstimatorId) { + estimatorRegistryParameters.stream().filter(e -> e.getEstimatorId() == chosenEstimatorId).findFirst() + .ifPresent(this::increaseEstimatorWeight); + } + + @Command + public void decreaseWeight(@BindingParam("param") int chosenEstimatorId) { + estimatorRegistryParameters.stream().filter(e -> e.getEstimatorId() == chosenEstimatorId).findFirst() + .ifPresent(this::decreaseEstimatorWeight); + } + + private void increaseEstimatorWeight(EstimatorRegistryParameterDto parameterDto) { + int weigth = parameterDto.getWeight(); + parameterDto.setWeight(weigth + 1); + estimatorRegistryParameters = new ListModelList<>(coreClient.modifyEstimatorWeight(parameterDto)); + BindUtils.postNotifyChange(null, null, this, "estimatorRegistryParameters"); + } + + private void decreaseEstimatorWeight(EstimatorRegistryParameterDto parameterDto) { + int weigth = parameterDto.getWeight(); + if (weigth > 1) { + parameterDto.setWeight(weigth - 1); + estimatorRegistryParameters = new ListModelList<>(coreClient.modifyEstimatorWeight(parameterDto)); + BindUtils.postNotifyChange(null, null, this, "estimatorRegistryParameters"); + } + } + + @Command + @NotifyChange("estimatorRegistryParameters") + public void deleteEstimator(@BindingParam("param") int chosenEstimatorId) { + estimatorRegistryParameters = new ListModelList<>(coreClient.deleteEstimator(chosenEstimatorId)); + List registeredEstimatorIdEstimatorModule = estimatorClient.deleteEstimator(chosenEstimatorId); + if (registeredEstimatorIdEstimatorModule.isEmpty()) { + BindUtils.postGlobalCommand(null, null, "disableTestPredictionStartButton", null); + } + } +} diff --git a/CoreManager/src/main/java/hu/user/coremanager/viewmodel/QualifyingViewModel.java b/CoreManager/src/main/java/hu/user/coremanager/viewmodel/QualifyingViewModel.java new file mode 100644 index 0000000..2a0c7e7 --- /dev/null +++ b/CoreManager/src/main/java/hu/user/coremanager/viewmodel/QualifyingViewModel.java @@ -0,0 +1,217 @@ +package hu.user.coremanager.viewmodel; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.yaml.snakeyaml.events.Event; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.GlobalCommand; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; +import org.zkoss.zk.ui.annotation.Command; +import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.zk.ui.select.annotation.WireVariable; +import org.zkoss.zul.Messagebox; + +import com.google.common.io.Files; + +import hu.user.common.dto.ConfusionMatrixDto; +import hu.user.coremanager.dto.DirectoryProperty; +import hu.user.coremanager.dto.FieldProperty; +import hu.user.coremanager.dto.FileProperty; +import hu.user.coremanager.dto.ObservedValue; +import hu.user.coremanager.service.CoreClient; +import hu.user.coremanager.service.EvaluationService; +import hu.user.coremanager.service.FileHandler; +import hu.user.coremanager.service.TrainClient; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class) +public class QualifyingViewModel { + + private static final String ID = "id"; + private static final String TRANSACTION_IDENTIFIER = "transaction_identifier"; + private static final String CSV = "csv"; + private static final String SCHEMA_NAME = "schema_name"; + private static final String TABLE_NAME = "table_name"; + private static final String PREDICTED_POSITIVE = "predicted_positive"; + private static final String PREDICTED_NEGATIVE = "predicted_negative"; + private static final String REAL = "real"; + private static final String EVALUATION = "evaluation"; + + @WireVariable private FileHandler fileHandler; + @WireVariable private CoreClient coreClient; + @WireVariable private TrainClient trainClient; + @WireVariable private EvaluationService evaluationService; + private String testTransactionSchema; + private String realTransactionSchema; + private List schemas = new ArrayList<>(); + private String testTransactiontable; + private String realTransactiontable; + private List testTransactionTables = new ArrayList<>(); + private List realTransactionTables = new ArrayList<>(); + private List fieldProperties = new ArrayList<>(); + private List folders = new ArrayList<>(); + private List selectedFolders; + private List files = new ArrayList<>(); + private List fileNames = new ArrayList<>(); + private File selectedFolder; + private String fullPath; + private List fileProperties = new ArrayList<>(); + private List directoryProperties = new ArrayList<>(); + + private Integer selectedFileNameIndex; + private ConfusionMatrixDto confusionMatrixDto; + + private Integer positivePredictionResultForEvaluation; + private Integer negativePredictionResultForEvaluation; + private String homeDirectory; + private boolean disabledTestPredictionStartButton; + + @Init + public void init() { + disabledTestPredictionStartButton = true; + schemas = Arrays.stream(trainClient.getSchemas()).collect(Collectors.toList()); + homeDirectory = trainClient.getHomeDirectory(); + File root = new File(homeDirectory); + directoryProperties = getDirectoryProperties(root); + fullPath = root.getAbsolutePath(); + } + + public String getExtensionByGuava(String filename) { + return Files.getFileExtension(filename); + } + + @Command + @NotifyChange("testTransactionTables") + public void changeTestTransactionSchema() { + if (testTransactionSchema != null && schemas.contains(testTransactionSchema)) { + String[] tablesOfSelectedSchema = trainClient.getTables(Map.of(SCHEMA_NAME, testTransactionSchema)); + testTransactionTables = Arrays.stream(tablesOfSelectedSchema).filter(e -> e.contains(EVALUATION)) + .collect(Collectors.toList()); + } + } + + @Command + @NotifyChange("realTransactionTables") + public void changeRealTransactionSchema() { + if (realTransactionSchema != null && schemas.contains(realTransactionSchema)) { + String[] tablesOfSelectedSchema = trainClient.getTables(Map.of(SCHEMA_NAME, realTransactionSchema)); + realTransactionTables = + Arrays.stream(tablesOfSelectedSchema).filter(e -> e.contains(REAL)).collect(Collectors.toList()); + } + } + + @Command + @NotifyChange("fieldProperties") + public void changeRealTransactionTable() { + Map fieldTypeByName = trainClient.getFieldTypeByName( + Map.of(SCHEMA_NAME, realTransactionSchema, TABLE_NAME, realTransactiontable)); + fieldProperties = fieldTypeByName.entrySet().stream().map(e -> new FieldProperty(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + } + + @Command + @NotifyChange({"positivePredictionResultForEvaluation", "negativePredictionResultForEvaluation"}) + public void predictForEvaluation() { + positivePredictionResultForEvaluation = null; + negativePredictionResultForEvaluation = null; + Map resultFromCoreModule = + evaluationService.predictForEvaluation(testTransactionSchema, testTransactiontable); + positivePredictionResultForEvaluation = resultFromCoreModule.get(PREDICTED_POSITIVE); + negativePredictionResultForEvaluation = resultFromCoreModule.get(PREDICTED_NEGATIVE); + } + + @Command + public void uploadRealTransactionFromCsvFile(@BindingParam("param") File selectedFile) { + List observedValues = fileHandler.readObservedValueFromCsvFile(selectedFile); + coreClient.uploadToCoreModuleObservedValues(observedValues); + } + + @Command + public void uploadRealTransactionFromDatabase() { + List> recordsInDatabase = + trainClient.getRecords(Map.of(SCHEMA_NAME, realTransactionSchema, TABLE_NAME, realTransactiontable)); + String[] fieldNamesInArray = trainClient.getFieldNameInOrdinalPosition( + Map.of(SCHEMA_NAME, realTransactionSchema, TABLE_NAME, realTransactiontable)); + List fieldNames = Arrays.stream(fieldNamesInArray).collect(Collectors.toList()); + int idIndex = fieldNames.indexOf(ID); + int transactionIdentifierIndex = fieldNames.indexOf(TRANSACTION_IDENTIFIER); + int fieldNameNumber = fieldNames.size(); + List observedValues = new ArrayList<>(); + for (List record : recordsInDatabase) { + ObservedValue observedValue = new ObservedValue(String.valueOf(record.get(transactionIdentifierIndex)), + (Integer) record.get(fieldNameNumber - 1)); + observedValues.add(observedValue); + } + coreClient.uploadToCoreModuleObservedValues(observedValues); + Messagebox.show("Real transaction has been uploaded."); + } + + @Command + @NotifyChange({"directoryProperties", "fileProperties", "fullPath"}) + public void changeDirectory(@BindingParam("param") String selectedDirectoryName) { + File selectedDirectory = new File(selectedDirectoryName); + directoryProperties.clear(); + directoryProperties.add(new DirectoryProperty("..", selectedDirectory.getParentFile())); + directoryProperties.addAll(getDirectoryProperties(selectedDirectory)); + fileProperties = getFileProperties(selectedDirectory); + fullPath = selectedDirectoryName; + } + + @Command + @NotifyChange("fileProperties") + public void displayFiles() { + System.out.println(selectedFolder); + } + + @Command + @NotifyChange("confusionMatrixDto") + public void refreshSystemConfusionMatrix() { + confusionMatrixDto = coreClient.getSysTemConfusionMatrix(); + } + + @GlobalCommand + @NotifyChange("disabledTestPredictionStartButton") + public void enableTestPredictionStartButton() { + System.out.println("enable"); + disabledTestPredictionStartButton = false; + } + + @GlobalCommand + @NotifyChange("disabledTestPredictionStartButton") + public void disableTestPredictionStartButton() { + System.out.println("disable"); + disabledTestPredictionStartButton = true; + } + + @Command + @NotifyChange("confusionMatrixDto") + public void clearAllTransaction() { + coreClient.clearAllTransaction(); + confusionMatrixDto = null; + } + + private List getDirectories(File file) { + return Arrays.stream(file.listFiles()).filter(e -> e.isDirectory() && e.isHidden() == false) + .collect(Collectors.toList()); + } + + private List getDirectoryProperties(File directory) { + return Arrays.stream(directory.listFiles()).filter(e -> e.isDirectory() && !e.isHidden()) + .map(e -> new DirectoryProperty(e.getName(), new File(e.toURI()))).collect(Collectors.toList()); + } + + private List getFileProperties(File directory) { + return Arrays.stream(directory.listFiles()) + .filter(e -> e.isFile() && getExtensionByGuava(e.getName()).equals(CSV)) + .map(e -> new FileProperty(e, e.getName())).collect(Collectors.toList()); + } +} diff --git a/CoreManager/src/main/resources/META-INF/spring-devtools.properties b/CoreManager/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000..0161707 --- /dev/null +++ b/CoreManager/src/main/resources/META-INF/spring-devtools.properties @@ -0,0 +1 @@ +restart.include.zklibs=/z[\\w]+-[\\w\\d-\.]+\.jar diff --git a/CoreManager/src/main/resources/application.properties b/CoreManager/src/main/resources/application.properties new file mode 100644 index 0000000..23cad3e --- /dev/null +++ b/CoreManager/src/main/resources/application.properties @@ -0,0 +1,4 @@ +zk.homepage=start +zk.zul-view-resolver-prefix=/zul +zk.resource-uri=/zkres + diff --git a/CoreManager/src/main/resources/application.yml b/CoreManager/src/main/resources/application.yml new file mode 100644 index 0000000..21e9e2b --- /dev/null +++ b/CoreManager/src/main/resources/application.yml @@ -0,0 +1,55 @@ +spring: + profiles: + default: "dev" + application: + name: CoreManager + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:3306/common_fraud?serverTimezone=UTC + username: root + password: pwd +logging: + level: + root: info + pattern: + console: = %d{yyyy-MM-dd HH:mm:ss} - %msg%n + file: =%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + file: + name: /home/tomi/log/${spring.application.name}.log +server: + port: 8082 +trainUrl: http://localhost:8085 +estimatorUrl: http://localhost:8083 +coreUrl: http://localhost:8081 +coreSoapUri: http://localhost:8081/ws/detection +home: + directory: /home/tomi + +--- +spring: + config: + activate: + on-profile: dockerized +# datasource: +# url: ${DATASOURCE_URL} +# username: ${MYSQL_USER} +# password: ${MYSQL_PASSWORD} +# jpa: +# show-sql: true +# generate-ddl: true +# hibernate: +# ddl-auto: create +# formar_sql: true +logging: + pattern: + console: = %d{yyyy-MM-dd HH:mm:ss} - %msg%n + file: =%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + file: + name: /opt/app/log/${spring.application.name}.log +server: + port: 8082 +trainUrl: http://train:8085 +estimatorUrl: http://estimator:8083 +coreUrl: http://core:8081 +coreSoapUri: http://core:8081/ws/detection + +--- \ No newline at end of file diff --git a/CoreManager/src/main/resources/maven/generate b/CoreManager/src/main/resources/maven/generate new file mode 100644 index 0000000..6cf2d31 --- /dev/null +++ b/CoreManager/src/main/resources/maven/generate @@ -0,0 +1 @@ +mvn jaxb2:xjc \ No newline at end of file diff --git a/CoreManager/src/main/resources/metainfo.zk/lang-addon.xml b/CoreManager/src/main/resources/metainfo.zk/lang-addon.xml new file mode 100644 index 0000000..02e4b61 --- /dev/null +++ b/CoreManager/src/main/resources/metainfo.zk/lang-addon.xml @@ -0,0 +1,10 @@ + + zkspringboot-demo-addon + 1.0 + xul/html + + zkmax + + + + diff --git a/CoreManager/src/main/resources/metainfo.zk/zk.xml b/CoreManager/src/main/resources/metainfo.zk/zk.xml new file mode 100644 index 0000000..947a3a6 --- /dev/null +++ b/CoreManager/src/main/resources/metainfo.zk/zk.xml @@ -0,0 +1,22 @@ + + + zkspringboot-demo + + org.zkoss.zul.nativebar + true + + + + + + + + + + + + + + + + diff --git a/CoreManager/src/main/resources/static/css/static-globalstyles.css b/CoreManager/src/main/resources/static/css/static-globalstyles.css new file mode 100644 index 0000000..aaf6083 --- /dev/null +++ b/CoreManager/src/main/resources/static/css/static-globalstyles.css @@ -0,0 +1,6 @@ +.my-box2 { + border: 3px solid green; + padding: 15px; + display: block; + width: max-content; +} \ No newline at end of file diff --git a/CoreManager/src/main/resources/static/css/static-localstyles.css b/CoreManager/src/main/resources/static/css/static-localstyles.css new file mode 100644 index 0000000..264982f --- /dev/null +++ b/CoreManager/src/main/resources/static/css/static-localstyles.css @@ -0,0 +1,4 @@ +.my-button { + color: Maroon; + font-weight: bold; +} \ No newline at end of file diff --git a/CoreManager/src/main/resources/static/img/zklogo1.png b/CoreManager/src/main/resources/static/img/zklogo1.png new file mode 100644 index 0000000..24bc55b Binary files /dev/null and b/CoreManager/src/main/resources/static/img/zklogo1.png differ diff --git a/CoreManager/src/main/resources/web/css/airplane_background.jpg b/CoreManager/src/main/resources/web/css/airplane_background.jpg new file mode 100644 index 0000000..1e88ac3 Binary files /dev/null and b/CoreManager/src/main/resources/web/css/airplane_background.jpg differ diff --git a/CoreManager/src/main/resources/web/css/mySpecial.css b/CoreManager/src/main/resources/web/css/mySpecial.css new file mode 100644 index 0000000..c378172 --- /dev/null +++ b/CoreManager/src/main/resources/web/css/mySpecial.css @@ -0,0 +1,4 @@ +.bg { + background-image: url("plane.jpg"); + background-size: cover; +} \ No newline at end of file diff --git a/CoreManager/src/main/resources/web/css/plane.jpg b/CoreManager/src/main/resources/web/css/plane.jpg new file mode 100644 index 0000000..9474f6b Binary files /dev/null and b/CoreManager/src/main/resources/web/css/plane.jpg differ diff --git a/CoreManager/src/main/resources/web/css/style.css b/CoreManager/src/main/resources/web/css/style.css new file mode 100644 index 0000000..cdf5559 --- /dev/null +++ b/CoreManager/src/main/resources/web/css/style.css @@ -0,0 +1,5 @@ +.z-window-header{ + /*background-color: aqua;*/ + font-size: 40px; +} + diff --git a/CoreManager/src/main/resources/web/img/airplane_background.jpg b/CoreManager/src/main/resources/web/img/airplane_background.jpg new file mode 100644 index 0000000..1e88ac3 Binary files /dev/null and b/CoreManager/src/main/resources/web/img/airplane_background.jpg differ diff --git a/CoreManager/src/main/resources/web/img/logo.png b/CoreManager/src/main/resources/web/img/logo.png new file mode 100644 index 0000000..b7eaee5 Binary files /dev/null and b/CoreManager/src/main/resources/web/img/logo.png differ diff --git a/CoreManager/src/main/resources/web/img/zklogo3.png b/CoreManager/src/main/resources/web/img/zklogo3.png new file mode 100644 index 0000000..24bc55b Binary files /dev/null and b/CoreManager/src/main/resources/web/img/zklogo3.png differ diff --git a/CoreManager/src/main/resources/web/zul/estimatorRegistry.zul b/CoreManager/src/main/resources/web/zul/estimatorRegistry.zul new file mode 100644 index 0000000..ad417a7 --- /dev/null +++ b/CoreManager/src/main/resources/web/zul/estimatorRegistry.zul @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + Predicted positive + Predicted negative + + + + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/CoreManager/src/main/resources/web/zul/qualifying.zul b/CoreManager/src/main/resources/web/zul/qualifying.zul new file mode 100644 index 0000000..1900f59 --- /dev/null +++ b/CoreManager/src/main/resources/web/zul/qualifying.zul @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +