diff --git a/.vscode/launch.json b/.vscode/launch.json index 35210bf..dd3f7d9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -40,11 +40,11 @@ }, { "type": "java", - "name": "Spring Boot-StorageRsApplication", + "name": "Spring Boot-StorageRsApplication", "request": "launch", "cwd": "${workspaceFolder}", - "mainClass": "ru.molokoin.storage_rs.StorageRsApplication", - "projectName": "storage_rs", + "mainClass": "ru.molokoin.storagers.StorageRsApplication", + "projectName": "storage-rs", "args": "", "envFile": "${workspaceFolder}/.env" } diff --git a/.vscode/settings.json b/.vscode/settings.json index 3466b3f..20aca5f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "java.compile.nullAnalysis.mode": "automatic" + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "interactive" } \ No newline at end of file diff --git a/client-service-teachers/docker-compose.yaml b/client-service-teachers/docker-compose.yaml index 4be2f94..7a30751 100644 --- a/client-service-teachers/docker-compose.yaml +++ b/client-service-teachers/docker-compose.yaml @@ -1,16 +1,20 @@ version: "3.7" services: client-service-teachers: + container_name: client-service-teachers + hostname: client-service-teachers build: context: ../client-service-teachers dockerfile: dockerfile image: "client-service-teachers" command: ["java","-jar","/app/client-service-teachers-0.1.jar"] ports: - - 80:8181 + - 84:8181 restart: unless-stopped + networks: + - tech_network networks: - default: - external: - name: tech_network + tech_network: + name: tech_network + external: true driver: bridge \ No newline at end of file diff --git a/client-service-teachers/src/main/java/ru/molokoin/clientserviceteachers/controllers/Hello.java b/client-service-teachers/src/main/java/ru/molokoin/clientserviceteachers/controllers/Hello.java new file mode 100644 index 0000000..e5aa4f4 --- /dev/null +++ b/client-service-teachers/src/main/java/ru/molokoin/clientserviceteachers/controllers/Hello.java @@ -0,0 +1,13 @@ +package ru.molokoin.clientserviceteachers.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class Hello { + @GetMapping("/hello") + public String hello(){ + return "hello"; + } +} diff --git a/client-service-teachers/src/main/resources/static/content/md/hello.md b/client-service-teachers/src/main/resources/static/content/md/hello.md new file mode 100644 index 0000000..e739bea --- /dev/null +++ b/client-service-teachers/src/main/resources/static/content/md/hello.md @@ -0,0 +1 @@ +# client-service-teacher \ No newline at end of file diff --git a/client-service-teachers/src/main/resources/static/teachers.md b/client-service-teachers/src/main/resources/static/teachers.md deleted file mode 100644 index e3aaae0..0000000 --- a/client-service-teachers/src/main/resources/static/teachers.md +++ /dev/null @@ -1 +0,0 @@ -# teachers.md \ No newline at end of file diff --git a/client-service-teachers/src/main/resources/templates/hello.html b/client-service-teachers/src/main/resources/templates/hello.html new file mode 100644 index 0000000..bcfeebc --- /dev/null +++ b/client-service-teachers/src/main/resources/templates/hello.html @@ -0,0 +1,14 @@ + + + + + + gates-hello + + + + + + + \ No newline at end of file diff --git a/storage_rs/src/main/resources/templates/view.html b/gates/.env similarity index 100% rename from storage_rs/src/main/resources/templates/view.html rename to gates/.env diff --git a/storage_rs/.gitignore b/gates/.gitignore similarity index 100% rename from storage_rs/.gitignore rename to gates/.gitignore diff --git a/storage_rs/.mvn/wrapper/maven-wrapper.properties b/gates/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from storage_rs/.mvn/wrapper/maven-wrapper.properties rename to gates/.mvn/wrapper/maven-wrapper.properties diff --git a/gates/README.md b/gates/README.md new file mode 100644 index 0000000..6ac99db --- /dev/null +++ b/gates/README.md @@ -0,0 +1,2 @@ +# GATES +Микросервис, предоставляющий пользовательский интерфейс для добавления документов из хранилища в базу данных \ No newline at end of file diff --git a/gates/docker-compose.yaml b/gates/docker-compose.yaml new file mode 100644 index 0000000..64d5913 --- /dev/null +++ b/gates/docker-compose.yaml @@ -0,0 +1,20 @@ +version: "3.7" +services: + gates: + container_name: "gates" + hostname: "gates" + build: + context: ../gates + dockerfile: dockerfile + image: "gates" + command: ["java","-jar","/app/gates/gates-0.0.1.jar"] + ports: + - 83:8383 + restart: unless-stopped + networks: + - tech_network +networks: + tech_network: + name: tech_network + external: true + driver: bridge \ No newline at end of file diff --git a/gates/dockerfile b/gates/dockerfile new file mode 100644 index 0000000..fe9e586 --- /dev/null +++ b/gates/dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:17-jdk-alpine +RUN apk update +RUN apk upgrade +COPY target/gates-0.0.1.jar /app/gates/gates-0.0.1.jar +WORKDIR /app/gates diff --git a/storage_rs/mvnw b/gates/mvnw similarity index 100% rename from storage_rs/mvnw rename to gates/mvnw diff --git a/storage_rs/mvnw.cmd b/gates/mvnw.cmd similarity index 100% rename from storage_rs/mvnw.cmd rename to gates/mvnw.cmd diff --git a/gates/pom.xml b/gates/pom.xml new file mode 100644 index 0000000..6938cad --- /dev/null +++ b/gates/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.0 + + + ru.mlokoin + gates + 0.0.1 + gates + Demo project for Spring Boot + + 17 + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/gates/src/main/java/ru/mlokoin/gates/GatesApplication.java b/gates/src/main/java/ru/mlokoin/gates/GatesApplication.java new file mode 100644 index 0000000..2dee858 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/GatesApplication.java @@ -0,0 +1,13 @@ +package ru.mlokoin.gates; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class GatesApplication { + + public static void main(String[] args) { + SpringApplication.run(GatesApplication.class, args); + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/config/WebConfig.java b/gates/src/main/java/ru/mlokoin/gates/config/WebConfig.java new file mode 100644 index 0000000..1acf8ba --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/config/WebConfig.java @@ -0,0 +1,24 @@ +package ru.mlokoin.gates.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebConfig { + @Bean + WebClient webClient() { + final int maxInMemorySize = 50 * 1024 * 1024; // 50MB + final ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(maxInMemorySize)) + .build(); + WebClient webClient = WebClient.builder() + .exchangeStrategies(exchangeStrategies) + // .baseUrl("http://resource-service-api:8181") + .build(); + return webClient; + } + + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/BuildingController.java b/gates/src/main/java/ru/mlokoin/gates/controller/BuildingController.java new file mode 100644 index 0000000..242cd47 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/BuildingController.java @@ -0,0 +1,37 @@ +package ru.mlokoin.gates.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.client.WebClient; + +import ru.mlokoin.gates.model.BuildingWraper; + +@Controller +@RequestMapping(path = "/buildings") +public class BuildingController { + @Autowired + private WebClient client; + + @GetMapping("/check/{id}") + public String checkBuildings(Model model, @PathVariable String id){ + return "buildings-check"; + // return "redirect:/document/view-as-educations/" + id; + } + + @PostMapping( + path="/save/{id}", + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = { + MediaType.APPLICATION_JSON_VALUE + }) + public String saveBuildings(@ModelAttribute("wrapBuildngs") BuildingWraper wraper, @PathVariable String id){ + return "redirect:/buildings/check/" + id; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/CretareaController.java b/gates/src/main/java/ru/mlokoin/gates/controller/CretareaController.java new file mode 100644 index 0000000..fc8d3f4 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/CretareaController.java @@ -0,0 +1,170 @@ +package ru.mlokoin.gates.controller; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; +import ru.mlokoin.gates.model.ProgramCretarea; +import ru.mlokoin.gates.model.ProgramCretareaWraper; +import ru.mlokoin.gates.model.XlsxCell; +import ru.mlokoin.gates.model.XlsxDocument; + +/** + * Контроллер, для работы с критериями + * - проверка соответствия критериев xlsx и базы данных + * - получение списка критериев, отсутствующих в базе + * - публикация новых критериев в базе + * + * Добавить возможности: + * - просмотра и редактирования критериев в базе + * - просмотра полного списка критериев в файле + * - настройка алиасов притериев + */ +@Controller +@RequestMapping(path = "/program-cretareas") +public class CretareaController { + @Autowired + private WebClient client; + + /** + * Проверка критериев xlsx-файла: + * - получание списка уникальных критериев из файла + * - получение списка внесенных в базу критериев + * - вывод пользователю критериев, не найденых в базе + * - редактирование пользователем не найденых критериев + * - отправка в базу новых критериев + * + * @param model + * @param id + * @return + */ + @GetMapping("/check/{id}") + public String checkCretareas(Model model, @PathVariable String id) { + System.out.println("Проверка критериев, для внесения в базу ..."); + System.out.println("Получение перечня критериев из xlsx-файла ..."); + XlsxDocument xlsx = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/document/content/" + + id + ".xlsx") + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + //список критериев из файла + ArrayList xlsx_cretareas = new ArrayList<>();//13 столбец + Map> map = xlsx.getData(); + for (Map.Entry> entry : map.entrySet()) { + ProgramCretarea pc = new ProgramCretarea(); + pc.setName_short(entry + .getValue() + .get(12) + .getContent()); + xlsx_cretareas.add(pc); + } + xlsx_cretareas.remove(0);//Удалили из списка заголовок "Критериий" + Set xlsx_cretareaSet = Set.copyOf(xlsx_cretareas); + + //список уникальных сокращенных наименований из файла + System.out.println("Список уникальных сокращенных наименований критериев из файла:"); + Set xlsx_ccs = new HashSet<>(); + for (ProgramCretarea pc : xlsx_cretareaSet) { + System.out.println(pc.getName_short()); + xlsx_ccs.add(pc.getName_short()); + } + + //Получение перечня критериев из базы + System.out.println("Получение списка критериев из базы ..."); + List base_cretareas = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/cretarea/list") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + Set base_cretareaSet = Set.copyOf(base_cretareas); + + //Список сокращенных наименований критериев из базы + System.out.println("Список уникальных сокращенных наименований критериев из базы:"); + Set base_ccs = new HashSet<>(); + for (ProgramCretarea pc : base_cretareaSet) { + System.out.println(pc.getName_short()); + base_ccs.add(pc.getName_short()); + } + + //Удаление критериев присутствующих в базе + xlsx_ccs.removeAll(base_ccs); + /** + * Если какието критерии файла отсутствуют в базе, вернуть страницу проверки критериев + */ + if (xlsx_ccs.size() != 0) { + //Подготовка списка, для передачи в представление + ArrayList list = new ArrayList<>(); + for (String string : xlsx_ccs) { + ProgramCretarea pc = new ProgramCretarea(); + pc.setName_short(string); + list.add(pc); + } + + ProgramCretareaWraper pcwraper = new ProgramCretareaWraper(list); + + model.addAttribute("wrapCretareas", pcwraper); + // model.addAttribute("cretareas", list); + model.addAttribute("id", id); + + return "cretareas-check"; + } + return "redirect:/document/view-as-educations/" + id; + } + + /** + * Добавление всех критериев скопом + * @param wraper + * @param id + * @return + */ + @PostMapping( + path="/save/{id}", + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = { + MediaType.APPLICATION_JSON_VALUE + }) + public String saveCretareas(@ModelAttribute("wrapCretareas") ProgramCretareaWraper wraper, @PathVariable String id){ + /** + * Отправляем запросы на добавление новых критериев в базу + */ + System.out.println("Критерии для добавления в базу: " + + wraper.getList().toString()); + + for (ProgramCretarea cretarea : wraper.getList()) { + //Проверка наличия полного наименования критерия + if (!cretarea.getName().equals("")) { + client.post() + .uri("http://resource-service-api:8181/cretarea/create") + .body(Mono.just(cretarea), ProgramCretarea.class) + .retrieve() + .toBodilessEntity() + .timeout(Duration.ofSeconds(1)) + .block(); + } + } + /** + * Возвращаем пользователя на страницу перечня новых критериев + * - если он не пустой + */ + return "redirect:/cretareas/check/" + id; + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/EducationsController.java b/gates/src/main/java/ru/mlokoin/gates/controller/EducationsController.java new file mode 100644 index 0000000..ef23796 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/EducationsController.java @@ -0,0 +1,46 @@ +package ru.mlokoin.gates.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.client.WebClient; + +import ru.mlokoin.gates.model.XlsxDocument; + +@Controller +@RequestMapping(path = "/") +public class EducationsController { + @Autowired + private WebClient client; + + /** + * Предоставление пользователю формы "view-as-educations" + * - просмотр xlsx-файла + * - проверки соответствия форме "Реестра обученных" + * - кнопки запуска механизмов проверок полей формы (критерии, программы, итд ...) + * @param model + * @param id + * @return + */ + @GetMapping("/document/view-as-educations/{id}") + public String viewAsEducations(Model model, @PathVariable String id) { + System.out.println("Просмотр содержимого файла ..."); + XlsxDocument xlsx = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/document/content/" + + id + ".xlsx") + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + + model.addAttribute("filename", xlsx.getDocument().getName()); + model.addAttribute("id", id); + model.addAttribute("xlsx", xlsx.getData()); + model.addAttribute("headers", xlsx.getHeaders()); + return "view-as-educations"; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/GatesController.java b/gates/src/main/java/ru/mlokoin/gates/controller/GatesController.java new file mode 100644 index 0000000..f886ba4 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/GatesController.java @@ -0,0 +1,279 @@ +package ru.mlokoin.gates.controller; + +import java.net.URI; +import java.net.URISyntaxException; +import java.time.Duration; +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; +import ru.mlokoin.gates.model.Document; +import ru.mlokoin.gates.model.XlsxDocument; +import ru.mlokoin.gates.util.CustomMultipartFile; + +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.bind.annotation.PostMapping; + +/** + * Контроллер предоставления графического интерфейса + */ +@Controller +@RequestMapping(path = "/") +public class GatesController { + @Autowired + private WebClient client; + + /** + * Получение списка файлов с сервера и доступа к инструментам извлечения данных + * - template : storage.html + * @param model + * @return + */ + @GetMapping("/storage") + public String getStorage(Model model){ + List docs = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/list-uploads") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + model.addAttribute("documents", docs); + return "storage"; + } + + /** + * Отправка файла в хранилище и сведений о нем в базу + * Возвращение ползователю обновленной страницы списка файлов + * - добавление метаданных файла в базу + * - получение id файла + * - отправка файла с новым именем в хранилище + * + * @param file + * @return + */ + @PostMapping("/storage/upload") + public String postMethodName(@RequestParam("file") MultipartFile file) { + + Document doc = new Document(); + doc.setName(file.getOriginalFilename()); + doc.setSize(file.getSize()); + /** + * Hfcibhtybt + */ + Optional ext = Optional.ofNullable(file.getOriginalFilename()) + .filter(f -> f.contains(".")) + .map(f -> f.substring(file.getOriginalFilename().lastIndexOf(".") + 1)); + doc.setExtension(ext.get()); + doc.setExtension( ext.get()); + // doc.setPath(); + + doc = client.post() + .uri("http://resource-service-api:8181/storage-entry/create") + .body(Mono.just(doc), Document.class) + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .timeout(Duration.ofSeconds(1)) + .block(); + + MultipartBodyBuilder builder = new MultipartBodyBuilder(); + Boolean ok; + MultipartFile out = new CustomMultipartFile(file, doc.getId()+"." + doc.getExtension()); + builder.part("file", out.getResource()); + + ok = client.method(HttpMethod.POST) + .uri("http://storage-rs:8282/api/document/store") + .body(BodyInserters + .fromMultipartData(builder.build())) + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + + System.out.println("Файл добавлен в хранилище: " + ok); + System.out.println("ID: " + doc.getId()); + System.out.println(doc.toString()); + return "redirect:/storage"; + } + + + /** + * Удаление файла из хранилища + * и возврат пользователю страницы работы с файлами + * !!! Добавить удаление записи из базы + * !!! Обернуть в транзакцию + * + * @param name + * @return + */ + @GetMapping("/storage/delete/{name}") + public String deleteFromStorage(@PathVariable String name) { + String filename = name; + String prefix = "http://storage-rs:8282/api/document/"; + String postfix = "/delete"; + URI uri; + + try { + uri = new URI(prefix + filename + postfix); + client.method(HttpMethod.DELETE) + .uri(uri) + .retrieve() + .bodyToMono(new ParameterizedTypeReference <>(){}) + .block(); + } catch (URISyntaxException e) { + System.out.println("Не верный URI: " + e.getMessage()); + } + return "redirect:/storage"; + } + + @GetMapping("/document/list") + public String getMethodName(Model model) { + List docs = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/storage-entry/list") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + model.addAttribute("documents", docs); + return "documents"; + } + + @GetMapping("/document/delete/{id}") + public String deleteFromDatabase(@PathVariable String id) { + System.out.println("gates# получение сведений о файле ... " + id); + /** + * Получеие сведений о файле из базы + */ + Document doc = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/storage-entry/" + id) + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + + System.out.println("Документ для удаления: " + doc.toString()); + System.out.println("Удаление из хранилища ..."); + + /** + * Удаление файла из хранилища + */ + client.delete() + .uri("http://storage-rs:8282/api/document/delete/" + + id + + "." + + doc.getExtension()) + .retrieve() + .bodyToMono(String.class) + .timeout(Duration.ofSeconds(1)) + .block(); + + + System.out.println("Удаление из базы ..."); + /** + * Удаление записи о файле из базы + */ + client.delete() + .uri("http://resource-service-api:8181/storage-entry/delete/" + id) + .retrieve() + .bodyToMono(String.class) + .timeout(Duration.ofSeconds(1)) + .block(); + + System.out.println("Файл успешно удален!"); + + return "redirect:/document/list"; + } + + /** + * Загрузка файла на сервер, + * - создание записи с метаданными файла в resource-service + * - передача его сервису storage-rs + * @param file + * @return + */ + @PostMapping("/document/upload") + public String upload(@RequestParam("file") MultipartFile file) { + + Document doc = new Document(); + doc.setName(file.getOriginalFilename()); + doc.setSize(file.getSize()); + /** + * Hfcibhtybt + */ + Optional ext = Optional.ofNullable(file.getOriginalFilename()) + .filter(f -> f.contains(".")) + .map(f -> f.substring(file.getOriginalFilename().lastIndexOf(".") + 1)); + doc.setExtension(ext.get()); + doc.setExtension( ext.get()); + // doc.setPath(); + + /** + * Добавление записи о файле в базу данных + */ + doc = client.post() + .uri("http://resource-service-api:8181/storage-entry/create") + .body(Mono.just(doc), Document.class) + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .timeout(Duration.ofSeconds(1)) + .block(); + + /** + * Добавление файла в файловое хранилище + */ + MultipartBodyBuilder builder = new MultipartBodyBuilder(); + Boolean ok; + MultipartFile out = new CustomMultipartFile(file, doc.getId()+"." + doc.getExtension()); + builder.part("file", out.getResource()); + + ok = client.method(HttpMethod.POST) + .uri("http://storage-rs:8282/api/document/store") + .body(BodyInserters + .fromMultipartData(builder.build())) + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + + System.out.println("Файл добавлен в хранилище: " + ok); + System.out.println("ID: " + doc.getId()); + System.out.println(doc.toString()); + return "redirect:/document/list"; + } + + /** + * Просмотр содержимого файла: + * - предусмотреть возможность фильтрации + */ + @GetMapping("/document/view-xlsx/{id}") + public String view(Model model, @PathVariable String id) { + System.out.println("Просмотр содержимого файла ..."); + XlsxDocument xlsx = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/document/content/" + + id + ".xlsx") + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + + model.addAttribute("filename", xlsx.getDocument().getName()); + model.addAttribute("id", id); + model.addAttribute("xlsx", xlsx.getData()); + model.addAttribute("headers", xlsx.getHeaders()); + return "view-xlsx"; + } + + /** + * Публикация "Реестра обученных" + * - просмотр + * - фильтры + * - запись в базу типа документа + * - настройка всех промежуточных состояний импорта + */ +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/Hello.java b/gates/src/main/java/ru/mlokoin/gates/controller/Hello.java new file mode 100644 index 0000000..d50bbcd --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/Hello.java @@ -0,0 +1,13 @@ +package ru.mlokoin.gates.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class Hello { + @GetMapping("/hello") + public String hello(){ + return "hello"; + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/ProgramController.java b/gates/src/main/java/ru/mlokoin/gates/controller/ProgramController.java new file mode 100644 index 0000000..86f60ff --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/ProgramController.java @@ -0,0 +1,173 @@ +package ru.mlokoin.gates.controller; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; +import ru.mlokoin.gates.model.Program; +import ru.mlokoin.gates.model.ProgramCretarea; +import ru.mlokoin.gates.model.ProgramWraper; +import ru.mlokoin.gates.model.XlsxCell; +import ru.mlokoin.gates.model.XlsxDocument; + +@Controller +@RequestMapping(path = "/programs") +public class ProgramController { + @Autowired + private WebClient client; + + /** + * Проверка соответствия программ обучения из файла - содержащимся в базе + * @param model + * @param id + * @return + */ + @GetMapping("/check/{id}") + public String checkPrograms(Model model, @PathVariable String id) { + System.out.println("Проверка программ обучения, для внесения в базу ..."); + System.out.println("Получение перечня программ из xlsx-файла ..."); + //получение данных файла в переменную xlsx + XlsxDocument xlsx = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/document/content/" + + id + ".xlsx") + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + //список программ из файла + ArrayList xlsx_programs = new ArrayList<>();//7 столбец + Map> map = xlsx.getData(); + for (Map.Entry> entry : map.entrySet()) { + Program programm = new Program(); + programm.setName(entry + .getValue() + .get(6) + .getContent()); + xlsx_programs.add(programm); + } + xlsx_programs.remove(0);//Удалили из списка заголовок + Set xlsx_programSet = Set.copyOf(xlsx_programs); + + //список уникальных наименований из файла + System.out.println("Список уникальных сокращенных наименований критериев из файла:"); + Set xlsx_stringSet = new HashSet<>(); + for (Program pc : xlsx_programSet) { + System.out.println(pc.getName()); + xlsx_stringSet.add(pc.getName()); + } + + //Получение перечня программ из базы + System.out.println("Получение списка программ из базы ..."); + List base_programs = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/program/list") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + Set base_programSet = Set.copyOf(base_programs); + + //Список наименований программ из базы + System.out.println("Список уникальных наименований программ из базы:"); + Set base_stringSet = new HashSet<>(); + for (Program pc : base_programSet) { + System.out.println(pc.getName()); + base_stringSet.add(pc.getName()); + } + + //Удаление программ присутствующих в базе + xlsx_stringSet.removeAll(base_stringSet); + + if (xlsx_stringSet.size() != 0) { + //Подготовка списка, для передачи в представление + ArrayList list = new ArrayList<>(); + for (String string : xlsx_stringSet) { + Program pc = new Program(); + pc.setName(string); + list.add(pc); + } + + /** + * Подготавлеваем обертку формы + */ + // передаем список новых программ + ProgramWraper pwraper = new ProgramWraper(list); + + //подготавливаем список критериев + List base_cretareas = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/cretarea/list") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + //передаем список критериев в обертку формы, для селекта + pwraper.setCretareas(base_cretareas); + + //передаем обертку в модель + model.addAttribute("wrapPrograms", pwraper); + model.addAttribute("id", id); + + return "programs-check"; + } + return "redirect:/document/view-as-educations/" + id; + } + + /** + * Добавление новых программ обучения в базу + * @param wraper + * @param id + * @return + */ + @PostMapping( + path="/save/{id}", + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = { + MediaType.APPLICATION_JSON_VALUE + }) + public String savePrograms(@ModelAttribute("wrapPrograms") ProgramWraper wraper, @PathVariable String id){ + /** + * Отправляем запросы на добавление новых программ в базу + */ + System.out.println("Программы для добавления в базу: " + + wraper.getPrograms().toString()); + for (Program program : wraper.getPrograms()) { + //Проверка наличия полного наименования имени программы + if (!program.getName().equals("")) { + //проверка наличия длительности программы + if (program.getLenght() != null) { + //проверка наличия направления обучения + if (!program.getStudy_direction().equals("")){ + //проверка наличия критерия + if (program.getCretarea() != null){ + client.post() + .uri("http://resource-service-api:8181/program/create") + .body(Mono.just(program), Program.class) + .retrieve() + .toBodilessEntity() + .timeout(Duration.ofSeconds(1)) + .block(); + } + } + } + } + } + /** + * Возвращаем пользователя на страницу перечня новых критериев + * - если он не пустой + */ + return "redirect:/programs/check/" + id; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/controller/TeacherController.java b/gates/src/main/java/ru/mlokoin/gates/controller/TeacherController.java new file mode 100644 index 0000000..3ed1137 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/controller/TeacherController.java @@ -0,0 +1,268 @@ +package ru.mlokoin.gates.controller; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; +import ru.mlokoin.gates.model.ProgramCretarea; +import ru.mlokoin.gates.model.ProgramCretareaWraper; +import ru.mlokoin.gates.model.Teacher; +import ru.mlokoin.gates.model.TeacherWraper; +import ru.mlokoin.gates.model.XlsxCell; +import ru.mlokoin.gates.model.XlsxDocument; + +@Controller +@RequestMapping(path = "/teachers") +public class TeacherController { + @Autowired + private WebClient client; + + @GetMapping("/check/{id}") + public String checkTeachers(Model model, @PathVariable String id) { + List errors = new ArrayList<>();//список ошибок + System.out.println("Проверка преподавателей, для внесения в базу ..."); + System.out.println("Получение перечня преподавателей из xlsx-файла ..."); + XlsxDocument xlsx = client.method(HttpMethod.GET) + .uri("http://storage-rs:8282/api/document/content/" + + id + ".xlsx") + .retrieve() + .bodyToMono(new ParameterizedTypeReference (){}) + .block(); + //список преподавателей из файла + // ArrayList xlsx_teachers = new ArrayList<>();//18 столбец + Map> map = xlsx.getData(); + + /** + * удалили строку заголовков + */ + map.remove(0); + System.out.println("Количество записей: " + map.size()); + + /** + * что делать с пустыми строками??? + * - "- - -" + * - Указано два преподавателя (оставляем только первого) + * - Указан формат обучения "дистанционно" (удаляем) + * - Теоретически могут быть окончания "-угли, -оглы и т.д. ..." (писать через пробел чтобы отсутствовал сохранить исходное состояние) + */ + Set xlsx_strings = new HashSet<>();//строки для браузера + Set xlsx_teachers = new HashSet<>();//объекты для обработки + for (Map.Entry> entry : map.entrySet()) { + + + /** + * получаем значение поля "Преподаватель" + * заменяем пустые поля на "- - -" + * добавляем запись в список уникальных значений + */ + String string = ""; + try { + string = entry + .getValue() + .get(18) + .getContent(); + } catch (Exception e) { + System.out.println("Не указан преподаватель: " + entry.getKey() + " :: " + e.getMessage()); + string = "- - -"; + } + + /** + * Преобразование строки в объект Преподавателя + * - обработка возможных ошибок в файле + * - разбор строк происходит в основном переборе, чтобы можно было извлечь номер строки с ошибками для пользователя + */ + Teacher t = new Teacher(); + String[] arr = string.split(" "); + for (int i = 0; i < arr.length; i++){ + switch (i) { + case 0: { + if (arr.length > 1){ + t.setSecond_name(arr[i]);//Фамилия + break; + } + t.setSecond_name("-");//Фамилия + t.setFirst_name("-");//Имя + t.setLast_name("-");//Отчество + errors.add("Возможна ошибка в строке документа: " + entry.getKey() + " :: В поле *Преподаватель* указано одно слово ... " + string); + break; + } + case 1: { + t.setFirst_name(arr[i]);//Имя + break; + } + case 2: { + t.setLast_name(arr[i]);//Отчество + break; + } + /** + * Обработка четвертого слова в строке + * Преподавателей, имеющих окончания в фамилии у нас нет. + * можно все что после 3-го слова откинуть .. + * + */ + case 3: { + // t.setLast_name(arr[(i-1)] + " " + arr[i]);//Окончание отчества - оглы, угли итд. + errors.add("Возможна ошибка в строке документа: " + entry.getKey() + " :: В поле *Преподаватель* указано больше трех слов ... " + string); + break; + } + default: + break; + } + } + xlsx_strings.add(string); + xlsx_teachers.add(t); + } + /** + * Промежуточные результаты в консоль + */ + System.out.println("Всего преподавателей(obj): " + xlsx_teachers.size()); + System.out.println("Всего преподавателей(str): " + xlsx_strings.size()); + for (Teacher teacher : xlsx_teachers) { + System.out.println("Преподаватель (obj): " + teacher.toString()); + } + System.out.println(">> errors: " + errors.size()); + for (String msg : errors) { + System.out.println("msg: " + msg); + } + + /** + * Получение перечня преподавателей из базы + */ + System.out.println("Получение списка преподавателей из базы ..."); + Set base_teachers = client.method(HttpMethod.GET) + .uri("http://resource-service-api:8181/teacher/list") + .retrieve() + .bodyToMono(new ParameterizedTypeReference >(){}) + .block(); + + /** + * Удаление преподавателей присутствующих в базе + * сравнение по объектам не проходит: + * - в объектах xlsx отсутствуют id, которые приходят с объектами из базы + * - менять Teacher.equals не хочется, он на lombok завязан + * - перевожу ФИО в строку и сравниваю строки!!! + */ + // xlsx_teachers.removeAll(base_teachers); + Set xlsx_teachers_str = new HashSet<>(); + Set base_teachers_str = new HashSet<>(); + for (Teacher t : xlsx_teachers) { + String s = t.getSecond_name() + " " + + t.getFirst_name() + " " + + t.getLast_name(); + xlsx_teachers_str.add(s); + } + + for (Teacher t : base_teachers) { + String s = t.getSecond_name() + " " + + t.getFirst_name() + " " + + t.getLast_name(); + base_teachers_str.add(s); + } + + xlsx_teachers_str.removeAll(base_teachers_str); + + + /** + * Если какието преподаватели отсутствуют в базе, + * вернуть страницу проверки преподавателей + */ + if (xlsx_teachers_str.size() != 0) { + /** + * Подготовка списка, для передачи в представление + * - опять преобразуем список из строкового в объектный + */ + ArrayList list = new ArrayList<>(); + for (String string : xlsx_teachers_str) { + Teacher t = new Teacher(); + String[] arr = string.split(" "); + for (int i = 0; i < arr.length; i++){ + switch (i) { + case 0: { + t.setSecond_name(arr[i]);//Фамилия + break; + } + case 1: { + t.setFirst_name(arr[i]);//Имя + break; + } + case 2: { + t.setLast_name(arr[i]);//Отчество + break; + } + default: + break; + } + } + list.add(t); + + } + + //кладем список в обертку для формы + TeacherWraper teacherWraper = new TeacherWraper(list); + + model.addAttribute("wrapTeachers", teacherWraper); + model.addAttribute("errors", errors); + model.addAttribute("id", id); + + return "teachers-check"; + } + return "redirect:/document/view-as-educations/" + id; + } + + /** + * Добавление всех критериев скопом + * @param wraper + * @param id + * @return + */ + @PostMapping( + path="/save/{id}", + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = { + MediaType.APPLICATION_JSON_VALUE + }) + public String saveTeachers(@ModelAttribute("wrapTeachers") TeacherWraper wraper, @PathVariable String id){ + /** + * Отправляем запросы на добавление новых критериев в базу + */ + System.out.println("Преподаватели для добавления в базу: " + + wraper.getList().toString()); + + for (Teacher teacher : wraper.getList()) { + //Проверка наличия флага для добавления в базу + //по полю табельного номера + if (teacher.getEmployee_id() != ""){ + client.post() + .uri("http://resource-service-api:8181/teacher/create") + .body(Mono.just(teacher), Teacher.class) + .retrieve() + .toBodilessEntity() + .timeout(Duration.ofSeconds(1)) + .block(); + } + } + /** + * Возвращаем пользователя на страницу перечня новых критериев + * - если он не пустой + */ + return "redirect:/teachers/check/" + id; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Building.java b/gates/src/main/java/ru/mlokoin/gates/model/Building.java new file mode 100644 index 0000000..bd866a5 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Building.java @@ -0,0 +1,29 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Сущность объекта строительства + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Building implements Serializable{ + private long id; + private String name_short;//Сокращенное наименование + private String name_full;//Полное наименование + private String code_short;//Краткий код + private String code_full;//Полный код + + // подготовить конструкторы на все варианты внесения информации о преподавателях + public Building(String name_short, String name_full, String code_short, String code_full){ + this.name_short = name_short; + this.name_full = name_full; + this.code_short = code_short; + this.code_full = code_full; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/BuildingWraper.java b/gates/src/main/java/ru/mlokoin/gates/model/BuildingWraper.java new file mode 100644 index 0000000..c193d9e --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/BuildingWraper.java @@ -0,0 +1,35 @@ +package ru.mlokoin.gates.model; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +/** + * Обертка для списка объектов строительства, обеспечивающая работоспособность thymeleaf + * при отправке из формы перечня объектов строительства + */ +@Data +public class BuildingWraper { + List list; + + public BuildingWraper(){ + init(); + } + + public BuildingWraper(List list){ + this.list = list; + } + + public void init(){ + this.list = new ArrayList<>(); + } + + public void add(Building building){ + this.list.add(building); + } + public String toString(){ + return this.list.toString(); + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Course.java b/gates/src/main/java/ru/mlokoin/gates/model/Course.java new file mode 100644 index 0000000..bc03270 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Course.java @@ -0,0 +1,45 @@ +package ru.mlokoin.gates.model; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Course { + private long id;//уникальный идентификатор курса + private String place;//место проведения занятий + private Date start_date;//дата начала курса + private Date protocol_date;//дата протокола + private String protocol_number;//номер протоколаssss + private String report_period;//отчетный период (наименование месяца) + private Teacher teacher;//сведения о преподаватле + private Program program;//сведения о программе обучения + private Building building;//сведения об объекте строительства + + /** + * Конструктор без id + * @param place + * @param start_date + * @param protocol_date + * @param protocol_number + * @param report_period + * @param teacher + * @param program + * @param building + */ + public Course(String place, Date start_date, Date protocol_date, String protocol_number, String report_period, + Teacher teacher, Program program, Building building) { + this.place = place; + this.start_date = start_date; + this.protocol_date = protocol_date; + this.protocol_number = protocol_number; + this.report_period = report_period; + this.teacher = teacher; + this.program = program; + this.building = building; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Document.java b/gates/src/main/java/ru/mlokoin/gates/model/Document.java new file mode 100644 index 0000000..d77f405 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Document.java @@ -0,0 +1,32 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Document implements Serializable{ + private Long id; + private String name;//наименование файла в файловой системе ({id}.{extension}) + private String path;//путь в файловой системе (root/{id}.{extension}) + private String extension;//расширение файла + private Long size;//размер файла + + /** + * без id + * @param name + * @param path + * @param extension + * @param size + */ + public Document(String name, String path, String extension, long size) { + this.name = name; + this.path = path; + this.extension = extension; + this.size = size; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/EducatonEntry.java b/gates/src/main/java/ru/mlokoin/gates/model/EducatonEntry.java new file mode 100644 index 0000000..bbd088f --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/EducatonEntry.java @@ -0,0 +1,38 @@ +package ru.mlokoin.gates.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class EducatonEntry { + private long id; + private String sertificate_number;//номер удостоверения + private String frdo_number;//ФРДО номер по реестру + private String eisot_number;//ЕИСОТ номер по реестру + private String ones;//единички (вспомогатльный столбец) + private Course course;//сведения о курсе + private Student student;//сведения о студенте + + /** + * Конструктор без id + * @param sertificate_number + * @param frdo_number + * @param eisot_number + * @param ones + * @param course + * @param student + */ + public EducatonEntry(String sertificate_number, String frdo_number, String eisot_number, String ones, + Course course, Student student) { + this.sertificate_number = sertificate_number; + this.frdo_number = frdo_number; + this.eisot_number = eisot_number; + this.ones = ones; + this.course = course; + this.student = student; + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Organization.java b/gates/src/main/java/ru/mlokoin/gates/model/Organization.java new file mode 100644 index 0000000..a173822 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Organization.java @@ -0,0 +1,38 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Сущность организации + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Organization implements Serializable{ + private long id; + private String ownership;//Форма собственности ПСК + private String name_short;//Сокращенное наименование + private String name_full;//Полное наименование + private String type;//вид ПСК - производственная/сервисная + private String inn;//ИНН организации + + /** + * Конструктор без id + * @param ownership + * @param name_short + * @param name_full + * @param type + * @param inn + */ + public Organization(String ownership, String name_short, String name_full, String type, String inn) { + this.ownership = ownership; + this.name_short = name_short; + this.name_full = name_full; + this.type = type; + this.inn = inn; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Program.java b/gates/src/main/java/ru/mlokoin/gates/model/Program.java new file mode 100644 index 0000000..e9c3e18 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Program.java @@ -0,0 +1,45 @@ +package ru.mlokoin.gates.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Program { + private long id; + private String name;//Наименование + private Integer lenght;//длительность программы в часах + + /** + * Направление обучения: + * - Обязательное обучение + * - Производственное обучение + * - Обучение вновь внедряемым процедурам + * - Обучение водителей + */ + private String study_direction; + private Integer price;//рублей + private ProgramCretarea cretarea; + + /** + * конструктор со всеми полями сущности, за исключением id + * Подготовить все варианты конструкторов + * @param name + * @param lenght + * @param study_direction + * @param price + * @param cretarea + */ + public Program(String name, Integer lenght, String study_direction, Integer price, ProgramCretarea cretarea) { + this.name = name; + this.lenght = lenght; + this.study_direction = study_direction; + this.price = price; + this.cretarea = cretarea; + } + + + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretarea.java b/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretarea.java new file mode 100644 index 0000000..f758aba --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretarea.java @@ -0,0 +1,28 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class ProgramCretarea implements Serializable{ + private long id; + private String name;//Наименование + private String name_short;//Наименование : сокращенно + + /** + * подготовить конструкторы на все варианты внесения информации о преподавателях + * + * @param name + * @param name_short + */ + public ProgramCretarea(String name, String name_short) { + this.name = name; + this.name_short = name_short; + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretareaWraper.java b/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretareaWraper.java new file mode 100644 index 0000000..be5a093 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/ProgramCretareaWraper.java @@ -0,0 +1,34 @@ +package ru.mlokoin.gates.model; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +/** + * Обертка для списка критериев, обеспечивающая работоспособность thymeleaf + * при отправке из формы списка критериев + */ +@Data +public class ProgramCretareaWraper { + List list; + + public ProgramCretareaWraper(){ + init(); + } + + public ProgramCretareaWraper(List list){ + this.list = list; + } + + public void init(){ + this.list = new ArrayList<>(); + } + + public void add(ProgramCretarea cretarea){ + this.list.add(cretarea); + } + public String toString(){ + return this.list.toString(); + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/ProgramWraper.java b/gates/src/main/java/ru/mlokoin/gates/model/ProgramWraper.java new file mode 100644 index 0000000..d31478f --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/ProgramWraper.java @@ -0,0 +1,39 @@ +package ru.mlokoin.gates.model; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +/** + * Обертка для списка программ обучения - для thymeleaf + */ +@Data +public class ProgramWraper { + List programs; + List cretareas; + + public ProgramWraper(){ + init(); + } + + public ProgramWraper(ArrayList list) { + this.programs = list; + } + + public void init(){ + this.programs = new ArrayList<>(); + } + + public void addProgram(Program program){ + this.programs.add(program); + } + + public void addCretarea(ProgramCretarea cretarea){ + this.cretareas.add(cretarea); + } + + public String toString(){ + return this.programs.toString(); + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Student.java b/gates/src/main/java/ru/mlokoin/gates/model/Student.java new file mode 100644 index 0000000..21634f8 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Student.java @@ -0,0 +1,55 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Student implements Serializable{ + private long id; + private String first_name;//Имя + private String second_name;//Отчество + private String last_name;//Фамилия + private String profession;//Профессия + private String category;//Категория (ИТР или рабочий) + private String direction;//Структурное подразделение + private String snils;//СНИЛС + private Date berth;//Дата рождения + private String sitizenship;//Гражданство + private String sex;//Пол (Муж/Жен) + private Organization organization;//Организация - работодатель + + /** + * Конструктор со всеми полями сущности кроме id + * @param first_name + * @param second_name + * @param last_name + * @param profession + * @param category + * @param direction + * @param snils + * @param berth + * @param sitizenship + * @param sex + * @param organization + */ + public Student(String first_name, String second_name, String last_name, String profession, String category, + String direction, String snils, Date berth, String sitizenship, String sex, Organization organization) { + this.first_name = first_name; + this.second_name = second_name; + this.last_name = last_name; + this.profession = profession; + this.category = category; + this.direction = direction; + this.snils = snils; + this.berth = berth; + this.sitizenship = sitizenship; + this.sex = sex; + this.organization = organization; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/Teacher.java b/gates/src/main/java/ru/mlokoin/gates/model/Teacher.java new file mode 100644 index 0000000..11997b6 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/Teacher.java @@ -0,0 +1,44 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Сущьность преподавателя + * добавить данные: + * - телефоны (список) + * - эл почты (список) + * - программы которые преподает + * - график работы + * - основное место работы (офис, наимеование ОП) + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Teacher implements Serializable{ + private long id; + private String first_name;//Имя + private String second_name;//Фамилия + private String last_name;//Отчество + private String employee_id; + private String snils; + + // подготовить конструкторы на все варианты внесения информации о преподавателях + public Teacher(String first_name, String second_name, String last_name){ + this.first_name = first_name; + this.second_name = second_name; + this.last_name = last_name; + } + + //конструктор - все аргуметы кроме id + public Teacher(String first_name, String second_name, String last_name, String employee_id, String snils){ + this.first_name = first_name; + this.second_name = second_name; + this.last_name = last_name; + this.employee_id = employee_id; + this.snils = snils; + } +} \ No newline at end of file diff --git a/gates/src/main/java/ru/mlokoin/gates/model/TeacherWraper.java b/gates/src/main/java/ru/mlokoin/gates/model/TeacherWraper.java new file mode 100644 index 0000000..f8c850d --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/TeacherWraper.java @@ -0,0 +1,31 @@ +package ru.mlokoin.gates.model; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +@Data +public class TeacherWraper { + List list; + + public TeacherWraper(){ + init(); + } + + public TeacherWraper(List list){ + this.list = list; + } + + public void init(){ + this.list = new ArrayList<>(); + } + + public void add(Teacher teacher){ + this.list.add(teacher); + } + public String toString(){ + return this.list.toString(); + } + +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/XlsxCell.java b/gates/src/main/java/ru/mlokoin/gates/model/XlsxCell.java new file mode 100644 index 0000000..08fe136 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/XlsxCell.java @@ -0,0 +1,21 @@ +package ru.mlokoin.gates.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class XlsxCell { + private String content; //содержимое ячейки + private String textColor; //цвет шрифта + private String bgColor; // цвет заливки ячейки + private String textSize; //8-12-14-24 размеры шрифта + private int textWeight; //жирность: bold (900), normal(500), + private String type;// STRING, NUMERIC, BOOLEAN, FORMULA + + public XlsxCell(String content){ + this.content = content; + } +} diff --git a/gates/src/main/java/ru/mlokoin/gates/model/XlsxDocument.java b/gates/src/main/java/ru/mlokoin/gates/model/XlsxDocument.java new file mode 100644 index 0000000..cdb8182 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/model/XlsxDocument.java @@ -0,0 +1,18 @@ +package ru.mlokoin.gates.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class XlsxDocument implements Serializable{ + private Map> data; + private Document document; + private List headers; +} diff --git a/gates/src/main/java/ru/mlokoin/gates/util/CustomMultipartFile.java b/gates/src/main/java/ru/mlokoin/gates/util/CustomMultipartFile.java new file mode 100644 index 0000000..358d0d0 --- /dev/null +++ b/gates/src/main/java/ru/mlokoin/gates/util/CustomMultipartFile.java @@ -0,0 +1,69 @@ +package ru.mlokoin.gates.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.web.multipart.MultipartFile; + +public class CustomMultipartFile implements MultipartFile{ + private MultipartFile file; + private String name; + + /** + * @param file + * @param name + */ + public CustomMultipartFile(MultipartFile file, String name) { + this.file = file; + this.name = name; + } + + @NonNull + @Override + public byte[] getBytes() throws IOException { + return file.getBytes(); + } + + @Override + @Nullable + public String getContentType() { + return file.getContentType(); + } + + @NonNull + @Override + public InputStream getInputStream() throws IOException { + return file.getInputStream(); + } + + @NonNull + @Override + public String getName() { + return file.getName(); + } + + @Override + @Nullable + public String getOriginalFilename() { + return this.name; + } + + @Override + public long getSize() { + return file.getSize(); + } + + @Override + public boolean isEmpty() { + return file.isEmpty(); + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + //NO REALIZATION + } + +} diff --git a/gates/src/main/resources/application.yaml b/gates/src/main/resources/application.yaml new file mode 100644 index 0000000..6ca9081 --- /dev/null +++ b/gates/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +spring: + application: + name: gates + jpa: + hibernate: + ddl-auto: update + database-platform: org.hibernate.dialect.PostgreSQLDialect + datasource: + url: "jdbc:postgresql://postgres-service:5432/tech-services" + username: tech-services + password: password + servlet: + multipart: + max-file-size: 50MB + max-request-size: 50MB + mvc: + hiddenmethod: + filter: + enabled: true + format: + date: yyyy-MM-dd + date-time: yyyy-MM-dd HH:mm:ss + time: HH:mm:ss +server: + port: 8383 + + diff --git a/gates/src/main/resources/static/content/md/hello.md b/gates/src/main/resources/static/content/md/hello.md new file mode 100644 index 0000000..d36e840 --- /dev/null +++ b/gates/src/main/resources/static/content/md/hello.md @@ -0,0 +1,2 @@ +# gates +сервис для экспорта данных из файлов в базу \ No newline at end of file diff --git a/gates/src/main/resources/templates/buildings-check.html b/gates/src/main/resources/templates/buildings-check.html new file mode 100644 index 0000000..1874eb6 --- /dev/null +++ b/gates/src/main/resources/templates/buildings-check.html @@ -0,0 +1,53 @@ + + + + + check-buildings + + + + + + +
+

check-buildings

+
    +
  • +
  • +
  • +
+ +
+
+
+

Объекты строительства, отсутствующие в базе:

+ +
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/cretareas-check.html b/gates/src/main/resources/templates/cretareas-check.html new file mode 100644 index 0000000..73bb233 --- /dev/null +++ b/gates/src/main/resources/templates/cretareas-check.html @@ -0,0 +1,61 @@ + + + + + check-cretareas + + + + + + +
+

check-cretareas

+
    +
  • POST NEW CRETAREAS привязать к пути на контроллере
  • +
  • Отправка формы, для передачи сервису ресурсов данных о новых критериях ...
  • +
  • Для новых критериев сделать пустой объект списка критериев, который будет отправляться после заполнения ...
  • +
  • Критерии добавлять в базу по одному, вдруг какие-то критерии окажутся опечатками и нужно будет редактировать исходный файл ...
  • +
  • Кнопка возврата к странице экспорта документа
  • +
  • +
  • +
  • +
+ +
+
+
+

Критерии, отсутствующие в базе:

+
+ + + + + + + + + + + + +
+ КРАТКО + + ПОЛНО +
+ + + +
+ +
+
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/documents.html b/gates/src/main/resources/templates/documents.html new file mode 100644 index 0000000..1a10e18 --- /dev/null +++ b/gates/src/main/resources/templates/documents.html @@ -0,0 +1,92 @@ + + + + + + + documents + + + + + +
+

documents

+ menu : auth : documents +
+
+
+
+ + +

Добавление пакетов:

+
+
+ +
+ +
+

Перечень файлов:

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
idnameextensionsize(bytes) + +
+ + + + + + + + +
+ + +
+
+
+ +
+
+ +
+
+ + + \ No newline at end of file diff --git a/gates/src/main/resources/templates/hello.html b/gates/src/main/resources/templates/hello.html new file mode 100644 index 0000000..bcfeebc --- /dev/null +++ b/gates/src/main/resources/templates/hello.html @@ -0,0 +1,14 @@ + + + + + + gates-hello + + + + + + + \ No newline at end of file diff --git a/gates/src/main/resources/templates/programs-check.html b/gates/src/main/resources/templates/programs-check.html new file mode 100644 index 0000000..73c1bf8 --- /dev/null +++ b/gates/src/main/resources/templates/programs-check.html @@ -0,0 +1,69 @@ + + + + + check-programs + + + + + + +
+

check-programs

+
    +
  • Наименование программы не должно содержать знаков переноса строки. + При внесении в базу они заменяются пробелами и не проходят проверку при сравнении с наименованием в xlsx
  • +
  • +
  • +
+ +
+
+
+ + + + + + + + + + + + + + + + + +
Наименование программы (name)Продолжительность, часов (lenght)Направление обучения (study_direction)Стоимость (price)Критерий (cretarea_id)
+ + + + + + + + + +
+ +
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/storage-add.html b/gates/src/main/resources/templates/storage-add.html new file mode 100644 index 0000000..cf3a8c1 --- /dev/null +++ b/gates/src/main/resources/templates/storage-add.html @@ -0,0 +1,28 @@ + + + + + gates-uploads + + + + + +
+

gates-uploads

+
+
+
+
+

Загрузка файла на сервер

+
+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/storage.html b/gates/src/main/resources/templates/storage.html new file mode 100644 index 0000000..c37eb4a --- /dev/null +++ b/gates/src/main/resources/templates/storage.html @@ -0,0 +1,91 @@ + + + + + + + Uploads + + + + + +
+

Gates

+ menu : auth : Storage +
+
+
+
+ + +

Добавление пакетов:

\ + +

Перечень файлов:

+
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
namepathextensionsize(bytes) + +
+ + + + + + + + +
+ + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/gates/src/main/resources/templates/teachers-check.html b/gates/src/main/resources/templates/teachers-check.html new file mode 100644 index 0000000..b52d09d --- /dev/null +++ b/gates/src/main/resources/templates/teachers-check.html @@ -0,0 +1,67 @@ + + + + + check-teachers + + + + + + +
+

check-teachers

+
    +
  • Преподаватели добавляются в базу если указан табельный номер.
  • +
  • +
  • +
  • +
  • +
+
+
+
+ + + + + + + + + + + + + + + + + +
Имя (first_name)Фамилия (second_name)Отчество (last_name)Табельный номер (employee_id)СНИЛС (snils)
+ + + + + + + + + +
+ +
+
+

errors (потенциальные ошибки в исходном документе): + +

+
    +
  • +
+
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/view-as-educations.html b/gates/src/main/resources/templates/view-as-educations.html new file mode 100644 index 0000000..8c7e1dc --- /dev/null +++ b/gates/src/main/resources/templates/view-as-educations.html @@ -0,0 +1,73 @@ + + + + + view-as-educations + + + + + +
+

view-as-educations (предусмотреть):

+
    +
  • Добавиь на страницу обработки ошибок и результатов отработки проверок
  • +
  • Удалить перед загрузкой xlsx-файла все знаки переноса строки (при отправке в базу автоматически меняются на пробелы)
  • +
  • Предусмотреть автоматический погон проверок
  • +
  • Разделить контроллеры по характеру взаимодействия с базой
  • +
  • +
  • +
  • +
+

+ +

CONTROLS:

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + +
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/gates/src/main/resources/templates/view-xlsx.html b/gates/src/main/resources/templates/view-xlsx.html new file mode 100644 index 0000000..a1f4bd6 --- /dev/null +++ b/gates/src/main/resources/templates/view-xlsx.html @@ -0,0 +1,59 @@ + + + + + View-xlsx + + + + + +
+

View-xlsx (предусмотреть):

+
    +
  • +
+

+

ЭКСПОРТИРОВАТЬ ФАЙЛ КАК:

+
    +
  • +
    + +
    +
  • +
  • +
    + +
    +
  • +
  • +
    + +
    +
  • +
+
+
+
+ + + + + + + + + + + + +
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/gates/src/test/java/ru/mlokoin/gates/GatesApplicationTests.java b/gates/src/test/java/ru/mlokoin/gates/GatesApplicationTests.java new file mode 100644 index 0000000..db6880c --- /dev/null +++ b/gates/src/test/java/ru/mlokoin/gates/GatesApplicationTests.java @@ -0,0 +1,13 @@ +package ru.mlokoin.gates; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class GatesApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/postgres-service/docker-compose.yaml b/postgres-service/docker-compose.yaml index 47e7b48..87f388b 100644 --- a/postgres-service/docker-compose.yaml +++ b/postgres-service/docker-compose.yaml @@ -24,8 +24,8 @@ volumes: external: true networks: default: - external: - name: tech_network + name: tech_network + external: true driver: bridge # docker volume create db_tech-services diff --git a/resource-service-api/docker-compose.yaml b/resource-service-api/docker-compose.yaml index d592bad..fa6994f 100644 --- a/resource-service-api/docker-compose.yaml +++ b/resource-service-api/docker-compose.yaml @@ -1,6 +1,8 @@ version: "3.7" services: resource-service-api: + container_name: resource-service-api + hostname: resource-service-api build: context: ../resource-service-api dockerfile: dockerfile @@ -9,8 +11,10 @@ services: ports: - 81:8181 restart: unless-stopped + networks: + - tech_network networks: - default: - external: - name: tech_network + tech_network: + name: tech_network + external: true driver: bridge \ No newline at end of file diff --git a/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java index f243c8a..2aa9b12 100644 --- a/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java +++ b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/EducationEntryController.java @@ -45,7 +45,7 @@ public class EducationEntryController { @PutMapping(path = "/education/update/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity updateProgram(@PathVariable Integer id, @RequestBody EducationEntry educationEntry) { + public ResponseEntity updateEducationEntry(@PathVariable Integer id, @RequestBody EducationEntry educationEntry) { EducationEntry ee = repo.findEducationEntryById(id); ee.setSertificate_number(educationEntry.getSertificate_number()); ee.setFrdo_number(educationEntry.getFrdo_number()); @@ -58,7 +58,7 @@ public class EducationEntryController { } @DeleteMapping("/education/delete/{id}") - public ResponseEntity deleteProgram(@PathVariable Long id){ + public ResponseEntity deleteEducationEntry(@PathVariable Long id){ EducationEntry ee = repo.findEducationEntryById(id); System.out.println(ee.toString()); repo.delete(ee); diff --git a/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/StorageController.java b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/StorageController.java new file mode 100644 index 0000000..a8acfac --- /dev/null +++ b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/controllers/StorageController.java @@ -0,0 +1,68 @@ +package ru.molokoin.resourceserviceapi.controllers; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import ru.molokoin.resourceserviceapi.entities.StorageEntry; +import ru.molokoin.resourceserviceapi.repositories.StorageEntryFace; + +/** + * Контроллер для работы с таблицей, хранящей сведения о файлах в файловом хранилище + */ +@RestController +@RequestMapping(path = "/", consumes = {"*/*"}) +public class StorageController { + @Autowired + private StorageEntryFace repo; + + @GetMapping("/storage-entry/list") + public ResponseEntity> getStorageEntries(){ + return new ResponseEntity<>(repo.findAll(), HttpStatus.OK); + } + + @GetMapping("/storage-entry/{id}") + public ResponseEntity getStorageEntryByID(@PathVariable Integer id){ + return new ResponseEntity<>(repo.findStorageEntryById(id), HttpStatus.OK); + } + + @PostMapping(path = "/storage-entry/create", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity saveStorageEntry(@RequestBody StorageEntry storageEntry) { + repo.save(storageEntry); + return new ResponseEntity<>(storageEntry, HttpStatus.CREATED); + } + + @PutMapping(path = "/storage-entry/update/{id}", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateStorageEntry(@PathVariable Integer id, @RequestBody StorageEntry storageEntry) { + StorageEntry se = repo.findStorageEntryById(id); + + se.setName(storageEntry.getName()); + se.setPath(storageEntry.getPath()); + se.setExtension(storageEntry.getExtension()); + se.setSize(storageEntry.getSize()); + repo.save(se); + return new ResponseEntity<>(repo.findStorageEntryById(id), HttpStatus.CREATED); + } + + @DeleteMapping("/storage-entry/delete/{id}") + public ResponseEntity deleteStorageEntry(@PathVariable Long id){ + StorageEntry se = repo.findStorageEntryById(id); + repo.delete(se); + return new ResponseEntity<>("Запись id#" + id + " удалена ... ", HttpStatus.OK); + } +} diff --git a/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/entities/StorageEntry.java b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/entities/StorageEntry.java new file mode 100644 index 0000000..4190c55 --- /dev/null +++ b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/entities/StorageEntry.java @@ -0,0 +1,37 @@ +package ru.molokoin.resourceserviceapi.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Data +public class StorageEntry { + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + private long id; + private String name;//наименование файла в файловой системе ({id}.{extension}) + private String path;//путь в файловой системе (root/{id}.{extension}) + private String extension;//расширение файла + private Long size;//размер файла + + /** + * Конструктор без id + * @param name + * @param path + * @param extension + * @param size + */ + public StorageEntry(String name, String path, String extension, Long size) { + this.name = name; + this.path = path; + this.extension = extension; + this.size = size; + } +} diff --git a/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/repositories/StorageEntryFace.java b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/repositories/StorageEntryFace.java new file mode 100644 index 0000000..21de8ae --- /dev/null +++ b/resource-service-api/src/main/java/ru/molokoin/resourceserviceapi/repositories/StorageEntryFace.java @@ -0,0 +1,12 @@ +package ru.molokoin.resourceserviceapi.repositories; + +import java.util.List; + +import org.springframework.data.repository.ListCrudRepository; + +import ru.molokoin.resourceserviceapi.entities.StorageEntry; + +public interface StorageEntryFace extends ListCrudRepository{ + List findAll(); + StorageEntry findStorageEntryById(long id); +} diff --git a/storage-rs/.env b/storage-rs/.env new file mode 100644 index 0000000..7edb5ad --- /dev/null +++ b/storage-rs/.env @@ -0,0 +1 @@ +DATA='/app/storage-rs/uploads' \ No newline at end of file diff --git a/storage-rs/.gitignore b/storage-rs/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/storage-rs/.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/storage-rs/.mvn/wrapper/maven-wrapper.properties b/storage-rs/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..aeccdfd --- /dev/null +++ b/storage-rs/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# 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. +wrapperVersion=3.3.1 +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip diff --git a/storage-rs/docker-compose.yaml b/storage-rs/docker-compose.yaml new file mode 100644 index 0000000..742afb4 --- /dev/null +++ b/storage-rs/docker-compose.yaml @@ -0,0 +1,25 @@ +version: "3.7" +services: + storage-rs: + container_name: storage-rs + hostname: storage-rs + build: + context: ../storage-rs + dockerfile: dockerfile + image: "storage-rs" + command: ["java","-jar","/app/storage-rs/storage-rs-0.0.1.jar"] + ports: + - 82:8282 + restart: unless-stopped + volumes: + - tech_storage_rs:${DATA} + networks: + - tech_network +volumes: + tech_storage_rs: + external: true +networks: + tech_network: + name: tech_network + external: true + driver: bridge diff --git a/storage-rs/dockerfile b/storage-rs/dockerfile new file mode 100644 index 0000000..d4a80b1 --- /dev/null +++ b/storage-rs/dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:17-jdk-alpine +RUN apk update +RUN apk upgrade +COPY target/storage-rs-0.0.1.jar /app/storage-rs/storage-rs-0.0.1.jar +WORKDIR /app/storage-rs diff --git a/storage-rs/mvnw b/storage-rs/mvnw new file mode 100644 index 0000000..ba9212a --- /dev/null +++ b/storage-rs/mvnw @@ -0,0 +1,250 @@ +#!/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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.1 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl="${value-}" ;; + distributionSha256Sum) distributionSha256Sum="${value-}" ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_HOME="$HOME/.m2/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/storage-rs/mvnw.cmd b/storage-rs/mvnw.cmd new file mode 100644 index 0000000..406932d --- /dev/null +++ b/storage-rs/mvnw.cmd @@ -0,0 +1,146 @@ +<# : batch portion +@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 Apache Maven Wrapper startup batch script, version 3.3.1 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/storage_rs/pom.xml b/storage-rs/pom.xml similarity index 92% rename from storage_rs/pom.xml rename to storage-rs/pom.xml index a51aa99..af55657 100644 --- a/storage_rs/pom.xml +++ b/storage-rs/pom.xml @@ -9,19 +9,19 @@ ru.molokoin - storage_rs + storage-rs 0.0.1 - storage_rs + storage-rs file-explorer api 17 - + org.apache.poi poi @@ -32,11 +32,11 @@ poi-ooxml 5.2.0 - + org.springframework.boot spring-boot-starter-thymeleaf @@ -45,7 +45,7 @@ org.springframework.boot spring-boot-starter-web - + org.springframework.boot diff --git a/storage_rs/src/main/docs/puml/erd-explorer-data.puml b/storage-rs/src/main/docs/puml/erd-explorer-data.puml similarity index 100% rename from storage_rs/src/main/docs/puml/erd-explorer-data.puml rename to storage-rs/src/main/docs/puml/erd-explorer-data.puml diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/StorageRsApplication.java b/storage-rs/src/main/java/ru/molokoin/storagers/StorageRsApplication.java similarity index 82% rename from storage_rs/src/main/java/ru/molokoin/storage_rs/StorageRsApplication.java rename to storage-rs/src/main/java/ru/molokoin/storagers/StorageRsApplication.java index febb44d..95c1dbe 100644 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/StorageRsApplication.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/StorageRsApplication.java @@ -1,10 +1,10 @@ -package ru.molokoin.storage_rs; +package ru.molokoin.storagers; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import ru.molokoin.storage_rs.config.StorageConfiguration; +import ru.molokoin.storagers.config.StorageConfiguration; @SpringBootApplication @EnableConfigurationProperties(StorageConfiguration.class) @@ -13,5 +13,4 @@ public class StorageRsApplication { public static void main(String[] args) { SpringApplication.run(StorageRsApplication.class, args); } - } diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/config/StorageConfiguration.java b/storage-rs/src/main/java/ru/molokoin/storagers/config/StorageConfiguration.java similarity index 90% rename from storage_rs/src/main/java/ru/molokoin/storage_rs/config/StorageConfiguration.java rename to storage-rs/src/main/java/ru/molokoin/storagers/config/StorageConfiguration.java index 325b886..0c6b75d 100644 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/config/StorageConfiguration.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/config/StorageConfiguration.java @@ -1,4 +1,4 @@ -package ru.molokoin.storage_rs.config; +package ru.molokoin.storagers.config; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/HelloController.java b/storage-rs/src/main/java/ru/molokoin/storagers/controller/HelloController.java similarity index 73% rename from storage_rs/src/main/java/ru/molokoin/storage_rs/controller/HelloController.java rename to storage-rs/src/main/java/ru/molokoin/storagers/controller/HelloController.java index 1d86526..c92f7aa 100644 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/HelloController.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/controller/HelloController.java @@ -1,10 +1,10 @@ -package ru.molokoin.storage_rs.controller; +package ru.molokoin.storagers.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; -import ru.molokoin.storage_rs.model.Document; -import ru.molokoin.storage_rs.service.StorageServiceFace; +import ru.molokoin.storagers.model.DocumentModel; +import ru.molokoin.storagers.service.StorageServiceFace; /** * контроллер, для отрабтки тестов, @@ -30,12 +30,12 @@ public class HelloController { @GetMapping("/hello") public String hello(){ - System.out.println("storage_rs/hello-controller# " + "передача пользователю шаблона hello.html"); - System.out.println("storage_rs/hello-controller#(из config): " + storage.root()); + System.out.println("storageRS/hello-controller# " + "передача пользователю шаблона hello.html"); + System.out.println("storageRS/hello-controller#(из config): " + storage.root()); System.out.println("Загружено документов: " + storage.list().size()); System.out.println("Перечень загруженных документов:"); int i = 1; - for (Document doc : storage.list()) { + for (DocumentModel doc : storage.list()) { System.out.println("Document#" + i + ": " + doc.getPath() + "(size#" + doc.getSize() + ")"); i++; } diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java b/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java new file mode 100644 index 0000000..bba8343 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java @@ -0,0 +1,198 @@ +package ru.molokoin.storagers.controller; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import ru.molokoin.storagers.model.DocumentModel; +import ru.molokoin.storagers.model.XlsxDocument; +import ru.molokoin.storagers.service.StorageServiceFace; + +/** + * Контроллер для работы с файловой системой контейнера + * - получение + * - хранение + * - передача + * файлов пользователя/сторонего сервиса + */ +@Controller +@RequestMapping(path = "/", consumes = {"*/*"}) +public class StorageController { + /** + * Подключаем сервис доступа к базе даных + */ + // private DocumentFace database; + + /** + * получаем в переменную root + * значение свойства storage.location + * из файла application.yaml + */ + private StorageServiceFace storage; + + /** + * Конструктор контроллера, дня инициализации объекта хранилища + * - передается интерфейс + * @param storage + */ + public StorageController(StorageServiceFace storage){ + this.storage = storage; + } + + /** + * Загружаем файл пользователя и возвращаем список файлов на сервере + * + * @return + */ + @PostMapping("/upload") + public String upload(@RequestParam("file") MultipartFile file){ + if (file.isEmpty() != true){ + //добавляем перед именем файла идентификатор + String filename = storage.list().size() + "." + file.getOriginalFilename() + ""; + storage.store(file, filename); + }else { + System.out.println("Попытка загрузить пустой файл!!!"); + } + return "redirect:/uploads"; + } + + public String prefix(String input){ + String[] tokens = input.split("\\."); + List list = Arrays.asList(tokens); + return list.get(0); + } + + public String ext(String filename){ + String[] tokens = filename.split("\\."); + List list = Arrays.asList(tokens); + int i = list.size(); + return list.get(i - 1); + } + + /** + * Возвращаем пользователю список файлов с сервера + * @param model + * @return + */ + @GetMapping("/uploads") + public String list(Model model){ + model.addAttribute("documents", storage.list()); + return "documents"; + } + + /** + * Удаление файла по имени из хранилища + * @param name + * @return + */ + @GetMapping("/delete/{name}") + public String deleteByName(@PathVariable String name) { + storage.delete(name); + return "redirect:/uploads"; + } + + /** + * id содержится в имени файла + * - по id найти имя файла и вызвать метод удаления по имени + * @param id + * @return + */ + // @GetMapping("/delete/by-id/{id}") + // public String deleteById(@PathVariable Long id) { + // storage.delete(id); + // return "redirect:/uploads"; + // } + + /** + * Просмотр содержимого xlsx-файла + * @param name + * @return + */ + @GetMapping("/view/{name}") + public String view(Model model, @PathVariable String name) { + DocumentModel doc = storage.find(name); + XlsxDocument xlsx = new XlsxDocument(doc); + model.addAttribute("filename", xlsx.getDocument().getName()); + model.addAttribute("xlsx", xlsx.getData()); + model.addAttribute("headers", xlsx.getHeaders()); + return "view"; + } + + /** + * Экспорт данных из xlsx файла в базу данных + * - получение данных из xlsx + * - формирование запросов к сервису ресурсов, для публикации данных в базе + * + * @param name + * @return + */ + @GetMapping("/export-as-educations/{name}") + public String exportAsEducations(@PathVariable String name){ + + return "redirect:/uploads"; + } + + /** + * API + */ + + /** + * Получение списка загруженных на сервер файлов в json формате + * @return + */ + @GetMapping("/api/list-uploads") + public ResponseEntity> getUploads(){ + return new ResponseEntity<>(storage.list(), HttpStatus.OK); + } + + /** + * Получение метаданных о файле + * @param filename + * @return + */ + @GetMapping("/api/document/{filename}") + public ResponseEntity getDocumentByName(@PathVariable String filename){ + return new ResponseEntity<>(storage.find(filename), HttpStatus.OK); + } + + /** + * Получение содержимого файла в json формате + * @param filename + * @return + */ + @GetMapping("/api/document/content/{filename}") + public ResponseEntity getDocumentContentByName(@PathVariable String filename){ + DocumentModel doc = storage.find(filename); + XlsxDocument xlsx = new XlsxDocument(doc); + return new ResponseEntity<>(xlsx, HttpStatus.OK); + } + + /** + * Удаление файла по имени + */ + @DeleteMapping("/api/document/delete/{filename}") + public ResponseEntity deleteProgram(@PathVariable String filename){ + return new ResponseEntity<>(storage.delete(filename), HttpStatus.OK); + } + + /** + * Загрузка файла на сервер + * @param file + * @return + */ + @PostMapping("/api/document/store") + public ResponseEntity store(@RequestParam("file") MultipartFile file){ + return new ResponseEntity<>(storage.store(file, file.getOriginalFilename()), HttpStatus.OK); + } +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/DocumentModel.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/DocumentModel.java new file mode 100644 index 0000000..4182337 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/DocumentModel.java @@ -0,0 +1,157 @@ +package ru.molokoin.storagers.model; + +// import lombok.AllArgsConstructor; +// import lombok.Data; +// import lombok.Getter; +// import lombok.NoArgsConstructor; +// import lombok.Setter; + +// @Getter +// @Setter +// @AllArgsConstructor +// @NoArgsConstructor +public class DocumentModel { + private Long id; + private String name;//наименование файла в файловой системе ({id}.{extension}) + private String path;//путь в файловой системе (root/{id}.{extension}) + private String extension;//расширение файла + private Long size;//размер файла + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + /** + * @return the path + */ + public String getPath() { + return path; + } + /** + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; + } + /** + * @return the extension + */ + public String getExtension() { + return extension; + } + /** + * @param extension the extension to set + */ + public void setExtension(String extension) { + this.extension = extension; + } + /** + * @return the size + */ + public Long getSize() { + return size; + } + /** + * @param size the size to set + */ + public void setSize(Long size) { + this.size = size; + } + /** + * + */ + public DocumentModel() { + } + /** + * @param name + * @param path + * @param extension + * @param size + */ + public DocumentModel(String name, String path, String extension, Long size) { + this.name = name; + this.path = path; + this.extension = extension; + this.size = size; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((extension == null) ? 0 : extension.hashCode()); + result = prime * result + ((size == null) ? 0 : size.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DocumentModel other = (DocumentModel) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + if (extension == null) { + if (other.extension != null) + return false; + } else if (!extension.equals(other.extension)) + return false; + if (size == null) { + if (other.size != null) + return false; + } else if (!size.equals(other.size)) + return false; + return true; + } + + /** + * @return the id + */ + public Long getId() { + return id; + } + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + /** + * @param id + * @param name + * @param path + * @param extension + * @param size + */ + public DocumentModel(Long id, String name, String path, String extension, Long size) { + this.id = id; + this.name = name; + this.path = path; + this.extension = extension; + this.size = size; + } + @Override + public String toString() { + return "DocumentModel [id=" + id + ", name=" + name + ", path=" + path + ", extension=" + extension + ", size=" + + size + "]"; + } +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java new file mode 100644 index 0000000..7201c8e --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java @@ -0,0 +1,186 @@ +package ru.molokoin.storagers.model; + +// import lombok.AllArgsConstructor; +// import lombok.Data; +// import lombok.NoArgsConstructor; + +// @Data +// @AllArgsConstructor +// @NoArgsConstructor +public class XlsxCell { + private String content; //содержимое ячейки + private String textColor; //цвет шрифта + private String bgColor; // цвет заливки ячейки + private String textSize; //8-12-14-24 размеры шрифта + private int textWeight; //жирность: bold (900), normal(500), + private String type;// STRING, NUMERIC, BOOLEAN, FORMULA + + public XlsxCell(String content){ + this.content = content; + } + + /** + * @return the content + */ + public String getContent() { + return content; + } + + /** + * @param content the content to set + */ + public void setContent(String content) { + this.content = content; + } + + /** + * @return the textColor + */ + public String getTextColor() { + return textColor; + } + + /** + * @param textColor the textColor to set + */ + public void setTextColor(String textColor) { + this.textColor = textColor; + } + + /** + * @return the bgColor + */ + public String getBgColor() { + return bgColor; + } + + /** + * @param bgColor the bgColor to set + */ + public void setBgColor(String bgColor) { + this.bgColor = bgColor; + } + + /** + * @return the textSize + */ + public String getTextSize() { + return textSize; + } + + /** + * @param textSize the textSize to set + */ + public void setTextSize(String textSize) { + this.textSize = textSize; + } + + /** + * @return the textWeight + */ + public int getTextWeight() { + return textWeight; + } + + /** + * @param textWeight the textWeight to set + */ + public void setTextWeight(int textWeight) { + this.textWeight = textWeight; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((content == null) ? 0 : content.hashCode()); + result = prime * result + ((textColor == null) ? 0 : textColor.hashCode()); + result = prime * result + ((bgColor == null) ? 0 : bgColor.hashCode()); + result = prime * result + ((textSize == null) ? 0 : textSize.hashCode()); + result = prime * result + textWeight; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + XlsxCell other = (XlsxCell) obj; + if (content == null) { + if (other.content != null) + return false; + } else if (!content.equals(other.content)) + return false; + if (textColor == null) { + if (other.textColor != null) + return false; + } else if (!textColor.equals(other.textColor)) + return false; + if (bgColor == null) { + if (other.bgColor != null) + return false; + } else if (!bgColor.equals(other.bgColor)) + return false; + if (textSize == null) { + if (other.textSize != null) + return false; + } else if (!textSize.equals(other.textSize)) + return false; + if (textWeight != other.textWeight) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + @Override + public String toString() { + return "XlsxCell [content=" + content + ", textColor=" + textColor + ", bgColor=" + bgColor + ", textSize=" + + textSize + ", textWeight=" + textWeight + ", type=" + type + "]"; + } + + /** + * + */ + public XlsxCell() { + } + + /** + * @param content + * @param textColor + * @param bgColor + * @param textSize + * @param textWeight + * @param type + */ + public XlsxCell(String content, String textColor, String bgColor, String textSize, int textWeight, String type) { + this.content = content; + this.textColor = textColor; + this.bgColor = bgColor; + this.textSize = textSize; + this.textWeight = textWeight; + this.type = type; + } +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxDocument.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxDocument.java new file mode 100644 index 0000000..be01628 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxDocument.java @@ -0,0 +1,209 @@ +package ru.molokoin.storagers.model; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +// import lombok.AllArgsConstructor; +// import lombok.Data; +// import lombok.NoArgsConstructor; + +// @Data +// @AllArgsConstructor +// @NoArgsConstructor +public class XlsxDocument implements Serializable{ + private Map> data; + private DocumentModel document; + private List headers;//верхняя строка формы + + public XlsxDocument(DocumentModel document){ + this.document = document; + this.data = init(document); + this.headers = data.get(0); + } + + private Map> init(DocumentModel document) { + FileInputStream file; + Workbook workbook; + try { + file = new FileInputStream(new File(document.getPath())); + workbook = new XSSFWorkbook(file); + + Sheet sheet = workbook.getSheetAt(0); + data = new HashMap<>(); + Integer i = 0; + + //перебор строк + int rowStart = sheet.getFirstRowNum(); + int rowEnd = sheet.getLastRowNum(); + for (int rowNum = rowStart; rowNum < rowEnd; rowNum++){ + Row r = sheet.getRow(rowNum); + if (r != null) { + //перебор ячеек в строке + List xlsxCells = new ArrayList<>(); + XlsxCell xlsxCell = null; + int lastColumn = r.getLastCellNum(); + for (int cn = 0; cn < lastColumn; cn++){ + Cell cell = r.getCell(cn); + if (cell == null) { + //обработка нулевой ячейки + xlsxCell = new XlsxCell(""); + xlsxCell.setType("NULL"); + } else { + //обработка ячейки + switch (cell.getCellType()) { + case STRING: { + xlsxCell = new XlsxCell(cell.getStringCellValue() + ""); + xlsxCell.setType("STRING"); + } break; + case NUMERIC: { + xlsxCell = new XlsxCell(cell.getNumericCellValue() + ""); + xlsxCell.setType("NUMERIC"); + } break; + case BOOLEAN: { + xlsxCell = new XlsxCell(cell.getBooleanCellValue() + ""); + xlsxCell.setType("BOOLEAN"); + } break; + case FORMULA: { + xlsxCell = new XlsxCell(cell.getCellFormula() + ""); + xlsxCell = new XlsxCell("FORMULA"); + xlsxCell.setType("FORMULA"); + } break; + case BLANK: { + xlsxCell = new XlsxCell(""); + xlsxCell.setType("BLANK"); + } break; + case ERROR: { + xlsxCell = new XlsxCell(""); + xlsxCell.setType("ERROR"); + } break; + case _NONE: { + xlsxCell = new XlsxCell(""); + xlsxCell.setType("_NONE"); + } break; + } + } + xlsxCells.add(xlsxCell); + } + data.put(rowNum, xlsxCells); + } + } + }catch (IOException e) { + System.out.println("Не читается файл: " + e.getMessage()); + } + return data; + } + + /** + * @return the data + */ + public Map> getData() { + return data; + } + + /** + * @param data the data to set + */ + public void setData(Map> data) { + this.data = data; + } + + /** + * @return the document + */ + public DocumentModel getDocument() { + return document; + } + + /** + * @param document the document to set + */ + public void setDocument(DocumentModel document) { + this.document = document; + } + + /** + * @return the headers + */ + public List getHeaders() { + return headers; + } + + /** + * @param headers the headers to set + */ + public void setHeaders(List headers) { + this.headers = headers; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((data == null) ? 0 : data.hashCode()); + result = prime * result + ((document == null) ? 0 : document.hashCode()); + result = prime * result + ((headers == null) ? 0 : headers.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + XlsxDocument other = (XlsxDocument) obj; + if (data == null) { + if (other.data != null) + return false; + } else if (!data.equals(other.data)) + return false; + if (document == null) { + if (other.document != null) + return false; + } else if (!document.equals(other.document)) + return false; + if (headers == null) { + if (other.headers != null) + return false; + } else if (!headers.equals(other.headers)) + return false; + return true; + } + + @Override + public String toString() { + return "XlsxDocument [data=" + data + ", document=" + document + ", headers=" + headers + "]"; + } + + /** + * @param data + * @param document + * @param headers + */ + public XlsxDocument(Map> data, DocumentModel document, List headers) { + this.data = data; + this.document = document; + this.headers = headers; + } + + /** + * + */ + public XlsxDocument() { + } + +} diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageService.java b/storage-rs/src/main/java/ru/molokoin/storagers/service/StorageService.java similarity index 81% rename from storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageService.java rename to storage-rs/src/main/java/ru/molokoin/storagers/service/StorageService.java index 31143b1..809a87d 100644 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageService.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/service/StorageService.java @@ -1,4 +1,4 @@ -package ru.molokoin.storage_rs.service; +package ru.molokoin.storagers.service; import java.io.File; import java.io.IOException; @@ -17,9 +17,9 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import jakarta.annotation.PostConstruct; +import ru.molokoin.storagers.config.StorageConfiguration; +import ru.molokoin.storagers.model.DocumentModel; -import ru.molokoin.storage_rs.config.StorageConfiguration; -import ru.molokoin.storage_rs.model.Document; @Service public class StorageService implements StorageServiceFace{ @@ -57,8 +57,8 @@ public class StorageService implements StorageServiceFace{ } @Override - public List list() { - List docs = new ArrayList<>(); + public List list() { + List docs = new ArrayList<>(); /** * Получаем список файлов в директории root */ @@ -68,7 +68,7 @@ public class StorageService implements StorageServiceFace{ * извлекаем сведения о каждом файле для формирвоания сущности document */ for (String file : new ArrayList<>(Arrays.asList(files))) { - Document doc = new Document(); + DocumentModel doc = new DocumentModel(); doc.setPath(root() + "/" + file); @@ -89,10 +89,17 @@ public class StorageService implements StorageServiceFace{ /** * Получаем расширение файла */ - Optional ext = Optional.ofNullable(file) + try { + Optional ext = Optional.ofNullable(file) .filter(f -> f.contains(".")) .map(f -> f.substring(file.lastIndexOf(".") + 1)); - doc.setExtension(ext.get()); + doc.setExtension(ext.get()); + + } catch (Exception e) { + System.out.println("У файла отсутствует расширение: " + e.getMessage()); + } + + // doc.setId(null); docs.add(doc); } return docs; @@ -101,7 +108,7 @@ public class StorageService implements StorageServiceFace{ /** * Найти документ по имени */ - public Document find(String name){ + public DocumentModel find(String name){ return list().stream().filter(doc -> name.equals(doc.getName())) .findAny() .orElse(null); @@ -140,9 +147,10 @@ public class StorageService implements StorageServiceFace{ } @Override - public void store(MultipartFile file) { + public Boolean store(MultipartFile file, String name_new) { try { - Files.copy(file.getInputStream(), root().resolve(file.getOriginalFilename())); + Files.copy(file.getInputStream(), root().resolve(name_new)); + return true; } catch (Exception e) { if (e instanceof FileAlreadyExistsException) { throw new RuntimeException("A file of that name already exists."); @@ -156,5 +164,4 @@ public class StorageService implements StorageServiceFace{ // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'store'"); } - } diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageServiceFace.java b/storage-rs/src/main/java/ru/molokoin/storagers/service/StorageServiceFace.java similarity index 86% rename from storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageServiceFace.java rename to storage-rs/src/main/java/ru/molokoin/storagers/service/StorageServiceFace.java index 9784dc2..140fc42 100644 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/service/StorageServiceFace.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/service/StorageServiceFace.java @@ -1,4 +1,4 @@ -package ru.molokoin.storage_rs.service; +package ru.molokoin.storagers.service; import java.io.IOException; import java.nio.file.Path; @@ -7,7 +7,7 @@ import java.util.List; import org.springframework.core.io.Resource; import org.springframework.web.multipart.MultipartFile; -import ru.molokoin.storage_rs.model.Document; +import ru.molokoin.storagers.model.DocumentModel; public interface StorageServiceFace { /** @@ -31,14 +31,14 @@ public interface StorageServiceFace { * получить список размещенных на хосте и не зарегистрированных в базе файлов * @return */ - public List list(); + public List list(); /** * Поиск документа из списка по имени * @param name * @return */ - public Document find(String name); + public DocumentModel find(String name); /** * Удаление всех файлов, очистка хранилища @@ -62,8 +62,9 @@ public interface StorageServiceFace { /** * Сохранение файла в хранилище * @param resource + * @return */ - public void store(MultipartFile file); + public Boolean store(MultipartFile file, String name_new); /** * Сохранение группы ресурсов в хранилище @@ -71,5 +72,4 @@ public interface StorageServiceFace { * @return */ public boolean store(List resources); - } diff --git a/storage_rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/storage-rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json similarity index 100% rename from storage_rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json rename to storage-rs/src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/storage_rs/src/main/resources/application.yaml b/storage-rs/src/main/resources/application.yaml similarity index 94% rename from storage_rs/src/main/resources/application.yaml rename to storage-rs/src/main/resources/application.yaml index 4e26019..5f531d8 100644 --- a/storage_rs/src/main/resources/application.yaml +++ b/storage-rs/src/main/resources/application.yaml @@ -1,6 +1,6 @@ spring: application: - name: storage_rs + name: storage-rs jpa: hibernate: ddl-auto: update diff --git a/storage_rs/src/main/resources/static/content/md/hello.md b/storage-rs/src/main/resources/static/content/md/hello.md similarity index 91% rename from storage_rs/src/main/resources/static/content/md/hello.md rename to storage-rs/src/main/resources/static/content/md/hello.md index 1eb6690..d0c0b71 100644 --- a/storage_rs/src/main/resources/static/content/md/hello.md +++ b/storage-rs/src/main/resources/static/content/md/hello.md @@ -1,4 +1,4 @@ -# storage_rs +# storageRS Сервис работы с файлами: - загрузка файлов на сервер - скачивание файлов с сервера diff --git a/storage_rs/src/main/resources/templates/documents.html b/storage-rs/src/main/resources/templates/documents.html similarity index 87% rename from storage_rs/src/main/resources/templates/documents.html rename to storage-rs/src/main/resources/templates/documents.html index cfe6e0f..550e6ee 100644 --- a/storage_rs/src/main/resources/templates/documents.html +++ b/storage-rs/src/main/resources/templates/documents.html @@ -61,6 +61,12 @@ xmlns:th="http://www.thymeleaf.org"> + +
+ +
+ + diff --git a/storage_rs/src/main/resources/templates/hello.html b/storage-rs/src/main/resources/templates/hello.html similarity index 100% rename from storage_rs/src/main/resources/templates/hello.html rename to storage-rs/src/main/resources/templates/hello.html diff --git a/storage-rs/src/main/resources/templates/view.html b/storage-rs/src/main/resources/templates/view.html new file mode 100644 index 0000000..226ded1 --- /dev/null +++ b/storage-rs/src/main/resources/templates/view.html @@ -0,0 +1,44 @@ + + + + + Uploads + + + + + +
+

View

+ menu : auth : View +
+
+
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+
+
+ + \ No newline at end of file diff --git a/storage_rs/src/test/java/ru/molokoin/storage_rs/StorageRsApplicationTests.java b/storage-rs/src/test/java/ru/molokoin/storagers/StorageRsApplicationTests.java similarity index 85% rename from storage_rs/src/test/java/ru/molokoin/storage_rs/StorageRsApplicationTests.java rename to storage-rs/src/test/java/ru/molokoin/storagers/StorageRsApplicationTests.java index 6b16047..9d25581 100644 --- a/storage_rs/src/test/java/ru/molokoin/storage_rs/StorageRsApplicationTests.java +++ b/storage-rs/src/test/java/ru/molokoin/storagers/StorageRsApplicationTests.java @@ -1,4 +1,4 @@ -package ru.molokoin.storage_rs; +package ru.molokoin.storagers; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/storage_rs/uploads/1_ДИ.xlsx b/storage-rs/uploads/1_ДИ.xlsx similarity index 100% rename from storage_rs/uploads/1_ДИ.xlsx rename to storage-rs/uploads/1_ДИ.xlsx diff --git a/storage_rs/uploads/2_ДОПОГ.xlsx b/storage-rs/uploads/2_ДОПОГ.xlsx similarity index 100% rename from storage_rs/uploads/2_ДОПОГ.xlsx rename to storage-rs/uploads/2_ДОПОГ.xlsx diff --git a/storage_rs/uploads/3_Трудовые отношения.xlsx b/storage-rs/uploads/3_Трудовые отношения.xlsx similarity index 100% rename from storage_rs/uploads/3_Трудовые отношения.xlsx rename to storage-rs/uploads/3_Трудовые отношения.xlsx diff --git a/storage_rs/uploads/4_Правила и нормы охраны труда.xlsx b/storage-rs/uploads/4_Правила и нормы охраны труда.xlsx similarity index 100% rename from storage_rs/uploads/4_Правила и нормы охраны труда.xlsx rename to storage-rs/uploads/4_Правила и нормы охраны труда.xlsx diff --git a/storage_rs/uploads/5_Общие нормативы и правила.xlsx b/storage-rs/uploads/5_Общие нормативы и правила.xlsx similarity index 100% rename from storage_rs/uploads/5_Общие нормативы и правила.xlsx rename to storage-rs/uploads/5_Общие нормативы и правила.xlsx diff --git a/storage_rs/uploads/6_Ремонт и диагностика.xlsx b/storage-rs/uploads/6_Ремонт и диагностика.xlsx similarity index 100% rename from storage_rs/uploads/6_Ремонт и диагностика.xlsx rename to storage-rs/uploads/6_Ремонт и диагностика.xlsx diff --git a/storage_rs/uploads/use_docker.pdf b/storage-rs/uploads/use_docker.pdf similarity index 100% rename from storage_rs/uploads/use_docker.pdf rename to storage-rs/uploads/use_docker.pdf diff --git a/storage_rs/uploads/Заявление для МП.docx b/storage-rs/uploads/Заявление для МП.docx similarity index 100% rename from storage_rs/uploads/Заявление для МП.docx rename to storage-rs/uploads/Заявление для МП.docx diff --git a/storage_rs/uploads/тесты.zip b/storage-rs/uploads/тесты.zip similarity index 100% rename from storage_rs/uploads/тесты.zip rename to storage-rs/uploads/тесты.zip diff --git a/storage_rs/.env b/storage_rs/.env deleted file mode 100644 index 87685c0..0000000 --- a/storage_rs/.env +++ /dev/null @@ -1 +0,0 @@ -DATA='/app/storage_rs/uploads' \ No newline at end of file diff --git a/storage_rs/docker-compose.yaml b/storage_rs/docker-compose.yaml deleted file mode 100644 index fb79a89..0000000 --- a/storage_rs/docker-compose.yaml +++ /dev/null @@ -1,21 +0,0 @@ -version: "3.7" -services: - storage_rs: - build: - context: ../storage_rs - dockerfile: dockerfile - image: "storage_rs" - command: ["java","-jar","/app/storage_rs/storage_rs-0.0.1.jar"] - ports: - - 82:8282 - restart: unless-stopped - volumes: - - tech_storage_rs:${DATA} -volumes: - tech_storage_rs: - external: true -networks: - default: - external: - name: tech_network - driver: bridge \ No newline at end of file diff --git a/storage_rs/dockerfile b/storage_rs/dockerfile deleted file mode 100644 index d4a6dd1..0000000 --- a/storage_rs/dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM openjdk:17-jdk-alpine -RUN apk update -RUN apk upgrade -COPY target/storage_rs-0.0.1.jar /app/storage_rs/storage_rs-0.0.1.jar -WORKDIR /app/storage_rs diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/ChohortController.java b/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/ChohortController.java deleted file mode 100644 index 6ab3080..0000000 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/ChohortController.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.molokoin.storage_rs.controller; - -public class ChohortController { - -} diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/StorageController.java b/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/StorageController.java deleted file mode 100644 index 1fc134b..0000000 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/controller/StorageController.java +++ /dev/null @@ -1,95 +0,0 @@ -package ru.molokoin.storage_rs.controller; - -import java.util.List; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -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.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; - -import ru.molokoin.storage_rs.model.Document; -import ru.molokoin.storage_rs.model.XlsxCell; -import ru.molokoin.storage_rs.model.XlsxDocument; -import ru.molokoin.storage_rs.service.StorageServiceFace; - -/** - * Контроллер для работы с файловой системой контейнера - * - получение - * - хранение - * - передача - * файлов пользователя/сторонего сервиса - */ -@Controller -@RequestMapping(path = "/", consumes = {"*/*"}) -public class StorageController { - /** - * получаем в переменную root - * значение свойства storage.location - * из файла application.yaml - */ - private StorageServiceFace storage; - - /** - * Конструктор контроллера, дня инициализации объекта хранилища - * - передается интерфейс - * @param storage - */ - public StorageController(StorageServiceFace storage){ - this.storage = storage; - } - - /** - * Загружаем файл пользователя и возвращаем список файлов на сервере - * @return - */ - @PostMapping("/upload") - public String upload(@RequestParam("file") MultipartFile file){ - storage.store(file); - return "redirect:/uploads"; - } - - /** - * Возвращаем пользователю список файлов с сервера - * @param model - * @return - */ - @GetMapping("/uploads") - public String list(Model model){ - model.addAttribute("documents", storage.list()); - return "documents"; - } - - /** - * Удаление файла из хранилища - * @param name - * @return - */ - @GetMapping("/delete/{name}") - public String delete(@PathVariable String name) { - storage.delete(name); - return "redirect:/uploads"; - } - - /** - * Удаление файла из хранилища - * @param name - * @return - */ - @GetMapping("/view/{name}") - public String view(@PathVariable String name) { - Document doc = storage.find(name); - XlsxDocument xlsx = new XlsxDocument(doc); - for (List row : xlsx.getData().values()) { - for (XlsxCell xlsxCell : row) { - System.out.println(xlsxCell.getContent()); - } - } - return "redirect:/uploads"; - } - - -} diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/Document.java b/storage_rs/src/main/java/ru/molokoin/storage_rs/model/Document.java deleted file mode 100644 index c0d9c96..0000000 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/Document.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.molokoin.storage_rs.model; - -public class Document { - private String name;//наименование файла в файловой системе ({id}.{extension}) - private String path;//путь в файловой системе (root/{id}.{extension}) - private String extension;//расширение файла - private Long size;//размер файла - - - /** - * - */ - public Document() { - } - - - /** - * @param name - * @param path - * @param extension - * @param size - */ - public Document(String name, String path, String extension, long size) { - this.name = name; - this.path = path; - this.extension = extension; - this.size = size; - } - /** - * @return the name - */ - public String getName() { - return name; - } - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - /** - * @return the path - */ - public String getPath() { - return path; - } - /** - * @param path the path to set - */ - public void setPath(String path) { - this.path = path; - } - /** - * @return the extension - */ - public String getExtension() { - return extension; - } - /** - * @param extension the extension to set - */ - public void setExtension(String extension) { - this.extension = extension; - } - /** - * @return the size - */ - public long getSize() { - return size; - } - /** - * @param size the size to set - */ - public void setSize(Long size) { - this.size = size; - } - - -} diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxCell.java b/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxCell.java deleted file mode 100644 index 23d799a..0000000 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxCell.java +++ /dev/null @@ -1,104 +0,0 @@ -package ru.molokoin.storage_rs.model; - -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@NoArgsConstructor -public class XlsxCell { - private String content; //содержимое ячейки - private String textColor; //цвет шрифта - private String bgColor; // цвет заливки ячейки - private String textSize; //8-12-14-24 размеры шрифта - private int textWeight; //жирность: bold (900), normal(500), - private String type;// STRING, NUMERIC, BOOLEAN, FORMULA - - public XlsxCell(String content){ - this.content = content; - } - - /** - * @return the content - */ - public String getContent() { - return content; - } - - /** - * @param content the content to set - */ - public void setContent(String content) { - this.content = content; - } - - /** - * @return the textColor - */ - public String getTextColor() { - return textColor; - } - - /** - * @param textColor the textColor to set - */ - public void setTextColor(String textColor) { - this.textColor = textColor; - } - - /** - * @return the bgColor - */ - public String getBgColor() { - return bgColor; - } - - /** - * @param bgColor the bgColor to set - */ - public void setBgColor(String bgColor) { - this.bgColor = bgColor; - } - - /** - * @return the textSize - */ - public String getTextSize() { - return textSize; - } - - /** - * @param textSize the textSize to set - */ - public void setTextSize(String textSize) { - this.textSize = textSize; - } - - /** - * @return the textWeight - */ - public int getTextWeight() { - return textWeight; - } - - /** - * @param textWeight the textWeight to set - */ - public void setTextWeight(int textWeight) { - this.textWeight = textWeight; - } - - /** - * @return the type - */ - public String getType() { - return type; - } - - /** - * @param type the type to set - */ - public void setType(String type) { - this.type = type; - } - -} diff --git a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxDocument.java b/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxDocument.java deleted file mode 100644 index 3dcf4a0..0000000 --- a/storage_rs/src/main/java/ru/molokoin/storage_rs/model/XlsxDocument.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.molokoin.storage_rs.model; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@NoArgsConstructor -public class XlsxDocument { - private Map> data; - private Document document; - - public XlsxDocument(Document document){ - this.document = document; - this.data = init(document); - } - - private Map> init(Document document) { - FileInputStream file; - Workbook workbook; - try { - file = new FileInputStream(new File(document.getPath())); - workbook = new XSSFWorkbook(file); - - Sheet sheet = workbook.getSheetAt(0); - data = new HashMap<>(); - Integer i = 0; - for (Row row : sheet) { - List xlsxCells = null; - XlsxCell xlsxCell = null; - for (Cell cell : row) { - xlsxCells = new ArrayList<>(); - switch (cell.getCellType()) { - case STRING: { - xlsxCell = new XlsxCell(cell.getStringCellValue() + ""); - } break; - case NUMERIC: { - xlsxCell = new XlsxCell(cell.getNumericCellValue() + ""); - } break; - case BOOLEAN: { - xlsxCell = new XlsxCell(cell.getBooleanCellValue() + ""); - } break; - case FORMULA: { - xlsxCell = new XlsxCell(cell.getCellFormula() + ""); - } break; - default: - } - xlsxCells.add(xlsxCell); - } - data.put(i, xlsxCells); - i++; - } - }catch (IOException e) { - System.out.println("Не читается файл: " + e.getMessage()); - } - return data; - } - - /** - * @return the data - */ - public Map> getData() { - return data; - } - - /** - * @param data the data to set - */ - public void setData(Map> data) { - this.data = data; - } - - /** - * @return the document - */ - public Document getDocument() { - return document; - } - - /** - * @param document the document to set - */ - public void setDocument(Document document) { - this.document = document; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((data == null) ? 0 : data.hashCode()); - result = prime * result + ((document == null) ? 0 : document.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - XlsxDocument other = (XlsxDocument) obj; - if (data == null) { - if (other.data != null) - return false; - } else if (!data.equals(other.data)) - return false; - if (document == null) { - if (other.document != null) - return false; - } else if (!document.equals(other.document)) - return false; - return true; - } - - - - - - -}