From 95aff9b84dc78f05087d28a373a1a9004b5b84ca Mon Sep 17 00:00:00 2001 From: beiselmn Date: Fri, 21 Feb 2020 16:23:36 +0100 Subject: [PATCH 01/23] Adding Mathjax option and fixing KaTeX --- src/main/resources/{data_do_not_run.sql => data.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/{data_do_not_run.sql => data.sql} (100%) diff --git a/src/main/resources/data_do_not_run.sql b/src/main/resources/data.sql similarity index 100% rename from src/main/resources/data_do_not_run.sql rename to src/main/resources/data.sql From f4aa1d6a62b42d5251e6c7aee847a9797691c3e6 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 10 Mar 2020 14:39:20 +0100 Subject: [PATCH 02/23] Adding 1st version of latex rendering for quantum algorithms --- pom.xml | 9 ++ .../com/patternpedia/api/PatternPediaAPI.java | 3 + .../patternpedia/api/entities/Pattern.java | 4 + .../api/filestorage/FileController.java | 70 ++++++++++ .../api/filestorage/FileStorageException.java | 11 ++ .../filestorage/FileStorageProperties.java | 16 +++ .../api/filestorage/FileStorageService.java | 68 ++++++++++ .../filestorage/MyFileNotFoundException.java | 15 +++ .../rest/controller/PatternController.java | 64 ++++++++- .../api/rest/model/AlgorithmType.java | 7 + .../model/PatternRenderedContentModel.java | 10 ++ .../api/service/PatternRenderService.java | 20 +++ .../api/service/PatternRenderServiceImpl.java | 124 ++++++++++++++++++ src/main/resources/application.properties | 16 ++- src/main/resources/data.sql | 2 +- src/main/resources/db/migration/V1__ddl.sql | 2 + src/test/resources/application.properties | 16 ++- 17 files changed, 447 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/patternpedia/api/filestorage/FileController.java create mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageException.java create mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java create mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageService.java create mode 100644 src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java create mode 100644 src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java create mode 100644 src/main/java/com/patternpedia/api/rest/model/PatternRenderedContentModel.java create mode 100644 src/main/java/com/patternpedia/api/service/PatternRenderService.java create mode 100644 src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java diff --git a/pom.xml b/pom.xml index aa109d2..83c5f90 100644 --- a/pom.xml +++ b/pom.xml @@ -85,6 +85,15 @@ 1.10.7 test + + org.springframework + spring-test + + + com.fasterxml.jackson.core + jackson-databind + 2.10.0 + diff --git a/src/main/java/com/patternpedia/api/PatternPediaAPI.java b/src/main/java/com/patternpedia/api/PatternPediaAPI.java index 7ffdcd7..658e961 100644 --- a/src/main/java/com/patternpedia/api/PatternPediaAPI.java +++ b/src/main/java/com/patternpedia/api/PatternPediaAPI.java @@ -1,10 +1,12 @@ package com.patternpedia.api; +import com.patternpedia.api.filestorage.FileStorageProperties; import com.vladmihalcea.hibernate.type.util.Configuration; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -12,6 +14,7 @@ @EnableTransactionManagement @EnableWebMvc @Slf4j +@EnableConfigurationProperties({FileStorageProperties.class}) public class PatternPediaAPI implements CommandLineRunner { public static void main(String[] args) { diff --git a/src/main/java/com/patternpedia/api/entities/Pattern.java b/src/main/java/com/patternpedia/api/entities/Pattern.java index 2398935..19c34be 100644 --- a/src/main/java/com/patternpedia/api/entities/Pattern.java +++ b/src/main/java/com/patternpedia/api/entities/Pattern.java @@ -37,4 +37,8 @@ public class Pattern extends EntityWithURI { @Column(columnDefinition = "jsonb") @NotNull private Object content; + + @Type(type = "jsonb") + @Column(columnDefinition = "jsonb") + private Object renderedContent; } diff --git a/src/main/java/com/patternpedia/api/filestorage/FileController.java b/src/main/java/com/patternpedia/api/filestorage/FileController.java new file mode 100644 index 0000000..177b938 --- /dev/null +++ b/src/main/java/com/patternpedia/api/filestorage/FileController.java @@ -0,0 +1,70 @@ +package com.patternpedia.api.filestorage; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@RestController +public class FileController { + + + @Autowired + private FileStorageService fileStorageService; + +// @PostMapping("/uploadFile") +// public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) { +// String fileName = fileStorageService.storeFile(file); +// +// String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() +// .path("/downloadFile/") +// .path(fileName) +// .toUriString(); +// +// return new UploadFileResponse(fileName, fileDownloadUri, +// file.getContentType(), file.getSize()); +// } +// +// @PostMapping("/uploadMultipleFiles") +// public List uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { +// return Arrays.asList(files) +// .stream() +// .map(file -> uploadFile(file)) +// .collect(Collectors.toList()); +// } + + //get saved picture + @GetMapping("/downloadFile/{fileName:.+}") + public ResponseEntity downloadFile(@PathVariable String fileName, HttpServletRequest request) { + // Load file as Resource + Resource resource = fileStorageService.loadFileAsResource(fileName); + + // Try to determine file's content type + String contentType = null; + try { + contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); + } catch (IOException ex) { + System.out.println("Could not determine file type."); + } + + // Fallback to the default content type if type could not be determined + if(contentType == null) { + contentType = "application/octet-stream"; + } + + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType(contentType)) + .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"") + .body(resource); + } +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java new file mode 100644 index 0000000..c326b30 --- /dev/null +++ b/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java @@ -0,0 +1,11 @@ +package com.patternpedia.api.filestorage; + +public class FileStorageException extends RuntimeException { + public FileStorageException(String message) { + super(message); + } + + public FileStorageException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java new file mode 100644 index 0000000..d90f332 --- /dev/null +++ b/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java @@ -0,0 +1,16 @@ +package com.patternpedia.api.filestorage; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "file") +public class FileStorageProperties { + private String uploadDir; + + public String getUploadDir() { + return uploadDir; + } + + public void setUploadDir(String uploadDir) { + this.uploadDir = uploadDir; + } +} diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java new file mode 100644 index 0000000..5e4338b --- /dev/null +++ b/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java @@ -0,0 +1,68 @@ +package com.patternpedia.api.filestorage; + +import com.patternpedia.api.filestorage.FileStorageProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.UUID; + +@Service +public class FileStorageService { + + private final Path fileStorageLocation; + + @Autowired + public FileStorageService(FileStorageProperties fileStorageProperties) { + this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir()) + .toAbsolutePath().normalize(); + + try { + Files.createDirectories(this.fileStorageLocation); + } catch (Exception ex) { + throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex); + } + } + + public String storeFile(MultipartFile file) { + // Normalize file name + String fileName = StringUtils.cleanPath( UUID.randomUUID()+file.getOriginalFilename()); + System.out.println("test" + fileName); + + try { + // Check if the file's name contains invalid characters + if (fileName.contains("..")) { + throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName); + } + + // Copy file to the target location (Replacing existing file with the same name) + Path targetLocation = this.fileStorageLocation.resolve(fileName); + Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING); + + return fileName; + } catch (IOException ex) { + throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex); + } + } + public Resource loadFileAsResource(String fileName) { + try { + Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); + Resource resource = new UrlResource(filePath.toUri()); + if(resource.exists()) { + return resource; + } else { + throw new MyFileNotFoundException("File not found " + fileName); + } + } catch (MalformedURLException ex) { + throw new MyFileNotFoundException("File not found " + fileName, ex); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java b/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java new file mode 100644 index 0000000..7534ff5 --- /dev/null +++ b/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java @@ -0,0 +1,15 @@ +package com.patternpedia.api.filestorage; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +public class MyFileNotFoundException extends RuntimeException { + public MyFileNotFoundException(String message) { + super(message); + } + + public MyFileNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java index 6d07e78..45936b6 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java @@ -1,11 +1,15 @@ package com.patternpedia.api.rest.controller; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.patternpedia.api.entities.DirectedEdge; import com.patternpedia.api.entities.Pattern; import com.patternpedia.api.entities.PatternLanguage; @@ -14,15 +18,13 @@ import com.patternpedia.api.exception.DirectedEdgeNotFoundException; import com.patternpedia.api.exception.UndirectedEdgeNotFoundException; import com.patternpedia.api.rest.model.PatternContentModel; +import com.patternpedia.api.rest.model.PatternRenderedContentModel; import com.patternpedia.api.rest.model.PatternModel; -import com.patternpedia.api.service.PatternLanguageService; -import com.patternpedia.api.service.PatternRelationDescriptorService; -import com.patternpedia.api.service.PatternService; -import com.patternpedia.api.service.PatternViewService; - +import com.patternpedia.api.service.*; import com.fasterxml.jackson.databind.ObjectMapper; import javax.validation.Valid; import org.apache.commons.text.CaseUtils; +import org.apache.tomcat.util.json.JSONParser; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -43,6 +45,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; + @RestController @CrossOrigin(allowedHeaders = "*", origins = "*") @RequestMapping(produces = "application/hal+json") @@ -53,17 +56,20 @@ public class PatternController { private PatternViewService patternViewService; private PatternRelationDescriptorService patternRelationDescriptorService; private ObjectMapper objectMapper; + private PatternRenderService patternRenderService; public PatternController(PatternService patternService, PatternLanguageService patternLanguageService, PatternViewService patternViewService, PatternRelationDescriptorService patternRelationDescriptorService, + PatternRenderService patternRenderService, ObjectMapper objectMapper) { this.patternService = patternService; this.patternLanguageService = patternLanguageService; this.patternViewService = patternViewService; this.patternRelationDescriptorService = patternRelationDescriptorService; this.objectMapper = objectMapper; + this.patternRenderService = patternRenderService; } static List getPatternLanguagePatternCollectionLinks(UUID patternLanguageId) { @@ -93,6 +99,7 @@ List getPatternLinks(Pattern pattern) { .andAffordance(afford(methodOn(PatternController.class).updatePatternViaPut(pattern.getPatternLanguage().getId(), pattern.getId(), null))) .andAffordance(afford(methodOn(PatternController.class).deletePatternOfPatternLanguage(pattern.getPatternLanguage().getId(), pattern.getId())))); links.add(linkTo(methodOn(PatternController.class).getPatternContentOfPattern(pattern.getPatternLanguage().getId(), pattern.getId())).withRel("content")); + links.add(linkTo(methodOn(PatternController.class).getPatternRenderedContentOfPattern(pattern.getPatternLanguage().getId(), pattern.getId())).withRel("renderedContent")); links.add(linkTo(methodOn(PatternLanguageController.class).getPatternLanguageById(pattern.getPatternLanguage().getId())).withRel("patternLanguage")); if (null != pattern.getPatternViews()) { @@ -274,6 +281,7 @@ List getPatternLinksForPatternViewRoute(Pattern pattern, UUID patternViewI @GetMapping(value = "/patternLanguages/{patternLanguageId}/patterns") CollectionModel> getPatternsOfPatternLanguage(@PathVariable UUID patternLanguageId) { + List> patterns = this.patternLanguageService.getPatternsOfPatternLanguage(patternLanguageId).stream() .map(PatternModel::from) .map(patternModel -> new EntityModel<>(patternModel, @@ -295,7 +303,14 @@ CollectionModel> getPatternsOfPatternView(@PathVariabl @PostMapping(value = "/patternViews/{patternViewId}/patterns") @CrossOrigin(exposedHeaders = "Location") @ResponseStatus(HttpStatus.CREATED) - public ResponseEntity addPatternToPatternView(@PathVariable UUID patternViewId, @RequestBody Pattern pattern) { + public ResponseEntity addPatternToPatternView(@PathVariable UUID patternViewId, @RequestBody Pattern pattern) { + try(FileWriter fileWriter = new FileWriter("src/test/resources/renderFile.tex")) { + fileWriter.write("test1"); + } catch (IOException e){ + System.out.println(e.toString()); + e.printStackTrace(); + } + this.patternRenderService.renderContent(pattern); this.patternViewService.addPatternToPatternView(patternViewId, pattern.getId()); return ResponseEntity.created(linkTo(methodOn(PatternController.class) .getPatternOfPatternViewById(patternViewId, pattern.getId())).toUri()).build(); @@ -318,11 +333,17 @@ ResponseEntity removePatternFromView(@PathVariable UUID patternViewId, @PathV @CrossOrigin(exposedHeaders = "Location") @ResponseStatus(HttpStatus.CREATED) ResponseEntity addPatternToPatternLanguage(@PathVariable UUID patternLanguageId, @Valid @RequestBody Pattern pattern) { + try(FileWriter fileWriter = new FileWriter("src/test/resources/renderFile.tex")) { + fileWriter.write("tes2t"); + } catch (IOException e){ + System.out.println(e.toString()); + e.printStackTrace(); + } PatternLanguage patternLanguage = this.patternLanguageService.getPatternLanguageById(patternLanguageId); if (null == pattern.getUri()) { pattern.setUri(patternLanguage.getUri() + '/' + CaseUtils.toCamelCase(pattern.getName(), false)); } - + this.patternRenderService.renderContent(pattern); pattern = this.patternLanguageService.createPatternAndAddToPatternLanguage(patternLanguageId, pattern); return ResponseEntity.created(linkTo(methodOn(PatternController.class) @@ -342,11 +363,20 @@ EntityModel updatePatternViaPut(@PathVariable UUID patternLanguageId, @ // Remark: At the moment we do not support changing name, uri of a pattern persistedVersion.setIconUrl(pattern.getIconUrl()); persistedVersion.setContent(pattern.getContent()); + persistedVersion.setRenderedContent(pattern.getContent()); + String renderedContent = patternRenderService.renderContent(pattern); + if (renderedContent != null){ + persistedVersion.setRenderedContent(renderedContent); + } else { + persistedVersion.setRenderedContent(pattern.getContent()); + } + pattern = this.patternService.updatePattern(persistedVersion); return new EntityModel<>(pattern, linkTo(methodOn(PatternController.class).getPatternOfPatternLanguageById(patternLanguageId, patternId)).withSelfRel(), linkTo(methodOn(PatternController.class).getPatternContentOfPattern(patternLanguageId, patternId)).withRel("content"), + linkTo(methodOn(PatternController.class).getPatternRenderedContentOfPattern(patternLanguageId, patternId)).withRel("renderedContent"), linkTo(methodOn(PatternLanguageController.class).getPatternLanguageById(patternLanguageId)).withRel("patternLanguage")); } @@ -371,6 +401,26 @@ EntityModel getPatternContentOfPattern(@PathVariable UUID patternLanguag return new EntityModel<>(model, linkTo(methodOn(PatternController.class).getPatternContentOfPattern(patternLanguageId, patternId)).withSelfRel(), linkTo(methodOn(PatternController.class).getPatternOfPatternLanguageById(patternLanguageId, patternId)).withRel("pattern"), + linkTo(methodOn(PatternController.class).getPatternRenderedContentOfPattern(patternLanguageId, patternId)).withRel("renderedContent"), + linkTo(methodOn(PatternLanguageController.class).getPatternLanguageById(patternLanguageId)).withRel("patternLanguage")); + } + + @GetMapping(value = "/patternLanguages/{patternLanguageId}/patterns/{patternId}/renderedContent") + EntityModel getPatternRenderedContentOfPattern(@PathVariable UUID patternLanguageId, @PathVariable UUID patternId) { + + Pattern pattern = this.patternLanguageService.getPatternOfPatternLanguageById(patternLanguageId, patternId); + PatternRenderedContentModel model = new PatternRenderedContentModel(); + + if (null == pattern.getRenderedContent()) { + model.setRenderedContent(this.objectMapper.createObjectNode()); + } else { + model.setRenderedContent(pattern.getRenderedContent()); + } + + return new EntityModel<>(model, + linkTo(methodOn(PatternController.class).getPatternContentOfPattern(patternLanguageId, patternId)).withSelfRel(), + linkTo(methodOn(PatternController.class).getPatternOfPatternLanguageById(patternLanguageId, patternId)).withRel("pattern"), + linkTo(methodOn(PatternController.class).getPatternRenderedContentOfPattern(patternLanguageId, patternId)).withRel("content"), linkTo(methodOn(PatternLanguageController.class).getPatternLanguageById(patternLanguageId)).withRel("patternLanguage")); } } diff --git a/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java b/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java new file mode 100644 index 0000000..df300ab --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java @@ -0,0 +1,7 @@ +package com.patternpedia.api.rest.model; + +public enum AlgorithmType { + QUANTIKZ, + QCIRCUIT, + NONE +} diff --git a/src/main/java/com/patternpedia/api/rest/model/PatternRenderedContentModel.java b/src/main/java/com/patternpedia/api/rest/model/PatternRenderedContentModel.java new file mode 100644 index 0000000..3172fb4 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/PatternRenderedContentModel.java @@ -0,0 +1,10 @@ +package com.patternpedia.api.rest.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Data +public class PatternRenderedContentModel { + private Object renderedContent; +} diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java new file mode 100644 index 0000000..f8bb279 --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -0,0 +1,20 @@ +package com.patternpedia.api.service; + +import com.patternpedia.api.entities.Pattern; +import com.patternpedia.api.rest.model.AlgorithmType; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; + +public interface PatternRenderService { + + @Transactional (readOnly = false) + String renderContent (Pattern pattern); + + @Transactional (readOnly = false) + AlgorithmType checkForAlgorithmInput (String content); + + @Transactional (readOnly = false) + String renderQuantikz (String content) throws IOException; + +} diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java new file mode 100644 index 0000000..acc9943 --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -0,0 +1,124 @@ +package com.patternpedia.api.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.patternpedia.api.entities.Pattern; +import com.patternpedia.api.filestorage.FileStorageProperties; +import com.patternpedia.api.filestorage.FileStorageService; +import com.patternpedia.api.rest.model.AlgorithmType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.springframework.core.io.Resource; + +import java.io.*; + +@Component +public class PatternRenderServiceImpl implements PatternRenderService { + + @Autowired + private FileStorageService fileStorageService; + + @Override + public String renderContent(Pattern pattern) { + String jsonString = null; + ObjectMapper mapper = new ObjectMapper(); + //Converting the Object to JSONString + try { + jsonString = mapper.writeValueAsString(pattern.getContent()); + System.out.println("JSONSTRING" + jsonString); + } catch (Exception e){ + + } + System.out.println("renderContent"); + AlgorithmType type = checkForAlgorithmInput(jsonString); + switch (type) { + case QUANTIKZ: + return renderQuantikz(jsonString); + case QCIRCUIT: + break; + case NONE: + return null; + } + + return null; + } + + @Override + public AlgorithmType checkForAlgorithmInput(String content) { + if (content != null) { + if (content.contains("\\begin{quantikz}")) { + System.out.println("Quantikz"); + return AlgorithmType.QUANTIKZ; + } + } + if (content.contains("\\Qcircuit")) { + return AlgorithmType.QCIRCUIT; + } + return AlgorithmType.NONE; + } + + @Override + public String renderQuantikz(String content) { + if (content.contains("\\begin{quantikz}")) { + String quantikzContent; + String originalContent = content; + String fileDownloadUri = null; + quantikzContent = content.substring(content.indexOf("\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); + String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; + String latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; + String docStart = "\\begin{document} \n"; + String docEnd = "\\end{document} \n"; + + try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { + fileWriter.write(latexDocClass + latexPackages + docStart + quantikzContent + docEnd); + } catch (IOException e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + try { + Runtime rt = Runtime.getRuntime(); + // On Windows put "cmd /c" + Process pr = rt.exec("cmd /c pdflatex -shell-escape renderFile.tex"); + } catch (Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ + String fileName = null; + try { + //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile + Path path = Paths.get("./renderFile.png"); + String name = "renderFile.png"; + String originalFileName = "renderFile.png"; + String contentType = "image/png"; + byte[] pictureContent = null; + try { + pictureContent = Files.readAllBytes(path); + } catch (final IOException e) { + } + MultipartFile multipartFile = new MockMultipartFile(name, + originalFileName, contentType, pictureContent); + fileName = fileStorageService.storeFile(multipartFile); + fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() + .path("/downloadFile/") + .path(fileName) + .toUriString(); + System.out.println(fileDownloadUri); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(fileDownloadUri); + String showimage = " ![](" + fileDownloadUri +")"; + System.out.println(content.replace(quantikzContent , showimage)); + return content.replace(quantikzContent , showimage).replaceAll("\\\\" , "\\\\\\\\" ); + } + return null; + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 78d2048..fe7e7da 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,4 +7,18 @@ spring.jpa.hibernate.ddl-auto=create spring.datasource.initialization-mode=always spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true #okta.oauth2.issuer=https://dev-918271.okta.com/oauth2/default -#okta.oauth2.clientId=0oa1eflyl1wZDVLLg357 \ No newline at end of file +#okta.oauth2.clientId=0oa1eflyl1wZDVLLg357 + +## MULTIPART (MultipartProperties) +# Enable multipart uploads +spring.servlet.multipart.enabled=true +# Threshold after which files are written to disk. +spring.servlet.multipart.file-size-threshold=2KB +# Max file size. +spring.servlet.multipart.max-file-size=200MB +# Max Request Size +spring.servlet.multipart.max-request-size=215MB + +## File Storage Properties +# All files uploaded through the REST API will be stored in this directory +file.upload-dir=./src/main/resources/images diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index d4ae5f2..e384755 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -15,7 +15,7 @@ INSERT INTO public.pattern_section_schema (id, label, name, position, type, patt INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7665', 'TestPattern1', 'http://patternpedia.org/TestPattern1', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7666', 'TestPattern2', 'http://patternpedia.org/TestPattern2', '{"c": "d"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('67d9b3fa-f6d6-4c0d-a239-695c2998c71e', 'Uniform Superposition', 'https://patternpedia.org/patternLanguages/qcPatternsUniform%20Superposition', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('1321dd9c-52c7-4b76-a1f3-3b567c3c7780', 'PatternA', 'https://patternpedia.org/patternLanguages/qcPatternsPatternA', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('1321dd9c-52c7-4b76-a1f3-3b567c3c7780', 'PatternA', 'https://patternpedia.org/patternLanguages/qcPatternsPatternA', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here. #renderedcontent"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('b6a4503a-5385-4bd4-879e-b9c7998820bd', 'PatternB', 'https://patternpedia.org/patternLanguages/qcPatternsPatternB', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('13b1fbfe-369d-4e0c-8273-68d5fc1bedbe', 'Pattern4', 'https://patternpedia.org/patternLanguages/qcPatternsPattern4', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('10c55d72-b870-4a65-9c08-b5b38f0a17c8', 'PatternCD', 'https://patternpedia.org/patternLanguages/qcPatternsPatternCD', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); diff --git a/src/main/resources/db/migration/V1__ddl.sql b/src/main/resources/db/migration/V1__ddl.sql index 6342dfa..d032cf5 100644 --- a/src/main/resources/db/migration/V1__ddl.sql +++ b/src/main/resources/db/migration/V1__ddl.sql @@ -6,6 +6,7 @@ CREATE TABLE pattern uri varchar(255), name varchar(255), content jsonb, + renderedContent jsonb, PRIMARY KEY (id) ); @@ -15,5 +16,6 @@ CREATE TABLE pattern_language uri varchar(255), name varchar(255), content jsonb, + renderedContent jsonb, PRIMARY KEY (id) ); \ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 3650a00..46ef1f5 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -14,4 +14,18 @@ spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.use_sql_comments=true -spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true \ No newline at end of file +spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true + +## MULTIPART (MultipartProperties) +# Enable multipart uploads +spring.servlet.multipart.enabled=true +# Threshold after which files are written to disk. +spring.servlet.multipart.file-size-threshold=2KB +# Max file size. +spring.servlet.multipart.max-file-size=200MB +# Max Request Size +spring.servlet.multipart.max-request-size=215MB + +## File Storage Properties +# All files uploaded through the REST API will be stored in this directory +file.upload-dir=/resources/images From 6b79fcd0e480d8140689d20fb7f9d7833755c3de Mon Sep 17 00:00:00 2001 From: beiselmn Date: Fri, 13 Mar 2020 16:09:42 +0100 Subject: [PATCH 03/23] Optimized latex rendering - view autoupdate, renderedContent format adjusted, saveoption adjusted, contentrendering adjusted --- .../rest/controller/PatternController.java | 28 +++++++++---------- .../api/service/PatternRenderService.java | 2 +- .../api/service/PatternRenderServiceImpl.java | 18 ++++++++---- src/main/resources/data.sql | 22 +++++++-------- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java index 45936b6..7c8c00f 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java @@ -304,13 +304,12 @@ CollectionModel> getPatternsOfPatternView(@PathVariabl @CrossOrigin(exposedHeaders = "Location") @ResponseStatus(HttpStatus.CREATED) public ResponseEntity addPatternToPatternView(@PathVariable UUID patternViewId, @RequestBody Pattern pattern) { - try(FileWriter fileWriter = new FileWriter("src/test/resources/renderFile.tex")) { - fileWriter.write("test1"); - } catch (IOException e){ - System.out.println(e.toString()); - e.printStackTrace(); + Object renderedContent = patternRenderService.renderContent(pattern); + if (renderedContent != null){ + pattern.setRenderedContent(renderedContent); + } else { + pattern.setRenderedContent(pattern.getContent()); } - this.patternRenderService.renderContent(pattern); this.patternViewService.addPatternToPatternView(patternViewId, pattern.getId()); return ResponseEntity.created(linkTo(methodOn(PatternController.class) .getPatternOfPatternViewById(patternViewId, pattern.getId())).toUri()).build(); @@ -333,17 +332,16 @@ ResponseEntity removePatternFromView(@PathVariable UUID patternViewId, @PathV @CrossOrigin(exposedHeaders = "Location") @ResponseStatus(HttpStatus.CREATED) ResponseEntity addPatternToPatternLanguage(@PathVariable UUID patternLanguageId, @Valid @RequestBody Pattern pattern) { - try(FileWriter fileWriter = new FileWriter("src/test/resources/renderFile.tex")) { - fileWriter.write("tes2t"); - } catch (IOException e){ - System.out.println(e.toString()); - e.printStackTrace(); - } PatternLanguage patternLanguage = this.patternLanguageService.getPatternLanguageById(patternLanguageId); if (null == pattern.getUri()) { pattern.setUri(patternLanguage.getUri() + '/' + CaseUtils.toCamelCase(pattern.getName(), false)); } - this.patternRenderService.renderContent(pattern); + Object renderedContent = patternRenderService.renderContent(pattern); + if (renderedContent != null){ + pattern.setRenderedContent(renderedContent); + } else { + pattern.setRenderedContent(pattern.getContent()); + } pattern = this.patternLanguageService.createPatternAndAddToPatternLanguage(patternLanguageId, pattern); return ResponseEntity.created(linkTo(methodOn(PatternController.class) @@ -363,8 +361,8 @@ EntityModel updatePatternViaPut(@PathVariable UUID patternLanguageId, @ // Remark: At the moment we do not support changing name, uri of a pattern persistedVersion.setIconUrl(pattern.getIconUrl()); persistedVersion.setContent(pattern.getContent()); - persistedVersion.setRenderedContent(pattern.getContent()); - String renderedContent = patternRenderService.renderContent(pattern); + Object renderedContent = patternRenderService.renderContent(pattern); + System.out.print(renderedContent); if (renderedContent != null){ persistedVersion.setRenderedContent(renderedContent); } else { diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index f8bb279..501e9a8 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -9,7 +9,7 @@ public interface PatternRenderService { @Transactional (readOnly = false) - String renderContent (Pattern pattern); + Object renderContent (Pattern pattern); @Transactional (readOnly = false) AlgorithmType checkForAlgorithmInput (String content); diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index acc9943..722a045 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -17,6 +17,7 @@ import org.springframework.core.io.Resource; import java.io.*; +import java.util.Map; @Component public class PatternRenderServiceImpl implements PatternRenderService { @@ -25,7 +26,7 @@ public class PatternRenderServiceImpl implements PatternRenderService { private FileStorageService fileStorageService; @Override - public String renderContent(Pattern pattern) { + public Object renderContent(Pattern pattern) { String jsonString = null; ObjectMapper mapper = new ObjectMapper(); //Converting the Object to JSONString @@ -39,7 +40,15 @@ public String renderContent(Pattern pattern) { AlgorithmType type = checkForAlgorithmInput(jsonString); switch (type) { case QUANTIKZ: - return renderQuantikz(jsonString); + Map map = null; + try { + String returnJson = renderQuantikz(jsonString); + System.out.println(returnJson); + map = mapper.readValue(returnJson, Map.class); + } catch (Exception e){ + e.printStackTrace(); + } + return map; case QCIRCUIT: break; case NONE: @@ -69,7 +78,7 @@ public String renderQuantikz(String content) { String quantikzContent; String originalContent = content; String fileDownloadUri = null; - quantikzContent = content.substring(content.indexOf("\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); + quantikzContent = content.substring(content.indexOf("\\\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; String latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; String docStart = "\\begin{document} \n"; @@ -114,8 +123,7 @@ public String renderQuantikz(String content) { e.printStackTrace(); } System.out.println(fileDownloadUri); - String showimage = " ![](" + fileDownloadUri +")"; - System.out.println(content.replace(quantikzContent , showimage)); + String showimage = "![](" + fileDownloadUri +")"; return content.replace(quantikzContent , showimage).replaceAll("\\\\" , "\\\\\\\\" ); } return null; diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index e384755..59ab4ac 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -12,18 +12,18 @@ INSERT INTO public.pattern_section_schema (id, label, name, position, type, patt INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (6, 'Known uses', 'Known uses', 5, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (7, 'Next', 'Next', 6, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7665', 'TestPattern1', 'http://patternpedia.org/TestPattern1', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7666', 'TestPattern2', 'http://patternpedia.org/TestPattern2', '{"c": "d"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('67d9b3fa-f6d6-4c0d-a239-695c2998c71e', 'Uniform Superposition', 'https://patternpedia.org/patternLanguages/qcPatternsUniform%20Superposition', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7665', 'TestPattern1', 'http://patternpedia.org/TestPattern1', '{"a": "b"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7666', 'TestPattern2', 'http://patternpedia.org/TestPattern2', '{"c": "d"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('67d9b3fa-f6d6-4c0d-a239-695c2998c71e', 'Uniform Superposition', 'https://patternpedia.org/patternLanguages/qcPatternsUniform%20Superposition', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('1321dd9c-52c7-4b76-a1f3-3b567c3c7780', 'PatternA', 'https://patternpedia.org/patternLanguages/qcPatternsPatternA', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here. #renderedcontent"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('b6a4503a-5385-4bd4-879e-b9c7998820bd', 'PatternB', 'https://patternpedia.org/patternLanguages/qcPatternsPatternB', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('13b1fbfe-369d-4e0c-8273-68d5fc1bedbe', 'Pattern4', 'https://patternpedia.org/patternLanguages/qcPatternsPattern4', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('10c55d72-b870-4a65-9c08-b5b38f0a17c8', 'PatternCD', 'https://patternpedia.org/patternLanguages/qcPatternsPatternCD', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('5243010e-82fe-4e02-a963-f736ab93c31f', 'Pattern5', 'https://patternpedia.org/patternLanguages/qcPatternsPattern5', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('43f2d8b5-467c-4ba5-afee-9340617f4c63', 'Pattern6', 'https://patternpedia.org/patternLanguages/qcPatternsPattern6', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('dbcdc0d1-e870-4858-924f-7789083827cf', 'Pattern name with a very very long title', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20name%20with%20a%20very%20very%20long%20title', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('84bc7222-cc07-4c93-b40d-41e7870d16e6', 'PatternE', 'https://patternpedia.org/patternLanguages/qcPatternsPatternE', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, pattern_language_id) VALUES ('e633a551-e033-4c23-b3c3-2cffda4b3cd5', 'Pattern DF', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20DF', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('b6a4503a-5385-4bd4-879e-b9c7998820bd', 'PatternB', 'https://patternpedia.org/patternLanguages/qcPatternsPatternB', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('13b1fbfe-369d-4e0c-8273-68d5fc1bedbe', 'Pattern4', 'https://patternpedia.org/patternLanguages/qcPatternsPattern4', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('10c55d72-b870-4a65-9c08-b5b38f0a17c8', 'PatternCD', 'https://patternpedia.org/patternLanguages/qcPatternsPatternCD', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('5243010e-82fe-4e02-a963-f736ab93c31f', 'Pattern5', 'https://patternpedia.org/patternLanguages/qcPatternsPattern5', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('43f2d8b5-467c-4ba5-afee-9340617f4c63', 'Pattern6', 'https://patternpedia.org/patternLanguages/qcPatternsPattern6', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('dbcdc0d1-e870-4858-924f-7789083827cf', 'Pattern name with a very very long title', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20name%20with%20a%20very%20very%20long%20title', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('84bc7222-cc07-4c93-b40d-41e7870d16e6', 'PatternE', 'https://patternpedia.org/patternLanguages/qcPatternsPatternE', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('e633a551-e033-4c23-b3c3-2cffda4b3cd5', 'Pattern DF', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20DF', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern_view (id, name, uri) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7690', 'TestView', 'https://patternpedia.org/patternViews/TestView'); INSERT INTO public.pattern_view (id, name, uri) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7691', 'TestView2', 'https://patternpedia.org/patternViews/TestView2'); From a5eb66c4de7ab5df8fc2d3f99d6ace0ec418e3f0 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 19 Mar 2020 19:09:17 +0100 Subject: [PATCH 04/23] Added Latex rendering function for multiple renders in one section. Fixed pdflatex execute, fully reworked latexenvironment detection, reworked JSONmapping --- .gitignore | 7 + .../api/service/PatternRenderService.java | 6 + .../api/service/PatternRenderServiceImpl.java | 308 ++++++++++++++---- 3 files changed, 252 insertions(+), 69 deletions(-) diff --git a/.gitignore b/.gitignore index a2a3040..6c4f85f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,10 @@ build/ ### VS Code ### .vscode/ + +### TexRendering ### +*.png +*.tex +*.pdf +*.log +*.aux \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index 501e9a8..9c71778 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -5,6 +5,7 @@ import org.springframework.transaction.annotation.Transactional; import java.io.IOException; +import java.util.Map; public interface PatternRenderService { @@ -17,4 +18,9 @@ public interface PatternRenderService { @Transactional (readOnly = false) String renderQuantikz (String content) throws IOException; +// @Transactional (readOnly = false) +// Map getBeginAndEndIndexes(String content, String begin, String end); + + @Transactional (readOnly = false) + String renderLatex(String content, int begin, int end, AlgorithmType type); } diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 722a045..2c446a6 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -1,23 +1,25 @@ package com.patternpedia.api.service; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.patternpedia.api.entities.Pattern; -import com.patternpedia.api.filestorage.FileStorageProperties; import com.patternpedia.api.filestorage.FileStorageService; import com.patternpedia.api.rest.model.AlgorithmType; +import javafx.util.Pair; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.configurationprocessor.json.JSONArray; +import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.springframework.core.io.Resource; import java.io.*; -import java.util.Map; +import java.util.*; @Component public class PatternRenderServiceImpl implements PatternRenderService { @@ -29,35 +31,113 @@ public class PatternRenderServiceImpl implements PatternRenderService { public Object renderContent(Pattern pattern) { String jsonString = null; ObjectMapper mapper = new ObjectMapper(); + //Converting the Object to JSONString try { jsonString = mapper.writeValueAsString(pattern.getContent()); + // TODO: fix no newline issue. Optimize that only current section gets rendered on update + jsonString = jsonString.replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); + System.out.println("notasstring" + pattern.getContent()); System.out.println("JSONSTRING" + jsonString); - } catch (Exception e){ + } catch (Exception e) { + e.printStackTrace(); + } + + if (jsonString == null) + return null; + + //get all quantikz occurences + boolean quantikz = true; + while (quantikz) { + Pair occuranceStartEnd = getNextOccurance(jsonString, "\\begin{quantikz}", "\\end{quantikz}"); + if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { + jsonString = renderLatex(jsonString, occuranceStartEnd.getKey(), occuranceStartEnd.getValue(),AlgorithmType.QUANTIKZ); + }else { + break; + } } - System.out.println("renderContent"); - AlgorithmType type = checkForAlgorithmInput(jsonString); - switch (type) { - case QUANTIKZ: - Map map = null; - try { - String returnJson = renderQuantikz(jsonString); - System.out.println(returnJson); - map = mapper.readValue(returnJson, Map.class); - } catch (Exception e){ - e.printStackTrace(); - } - return map; - case QCIRCUIT: + + //get all qcircuit occurences + boolean qcircuit = true; + while (qcircuit) { + Pair occuranceStartEnd = getNextOccurance(jsonString, "\\Qcircuit", "end}"); + if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { + jsonString = renderLatex(jsonString, occuranceStartEnd.getKey(), occuranceStartEnd.getValue(),AlgorithmType.QCIRCUIT); + }else { break; - case NONE: - return null; + } } - return null; + Map map = null; + try { + System.out.println(jsonString); + map = mapper.readValue(jsonString.replaceAll("\\\\", "\\\\\\\\"), Map.class); + } catch (Exception e) { + e.printStackTrace(); + } + if (map == null) + return null; + return map; + +// AlgorithmType type = checkForAlgorithmInput(jsonString); +// switch (type) { +// case QUANTIKZ: +// Map map = null; +// try { +// String returnJson = renderQuantikz(jsonString); +// System.out.println(returnJson); +// map = mapper.readValue(returnJson, Map.class); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return map; +// case QCIRCUIT: +// break; +// case NONE: +// return null; +// } + + + } + + public Pair getNextOccurance(String content, String begin, String end) { + System.out.println("content" + content); + return new Pair<>(content.indexOf(begin, 0), content.indexOf(end, 0)); } +// @Override +// public Map getBeginAndEndIndexes(String content, String begin, String end) { +// int lastIndexBegin = 0; +// List beginList = new ArrayList<>(); +// while (lastIndexBegin != -1) { +// lastIndexBegin = content.indexOf(begin, lastIndexBegin); +// if (lastIndexBegin != -1) { +// beginList.add(lastIndexBegin); +// lastIndexBegin += begin.length(); +// } +// } +// +// int lastIndexEnd = 0; +// List endList = new ArrayList<>(); +// while (lastIndexEnd != -1) { +// lastIndexEnd = content.indexOf(end, lastIndexEnd); +// if (lastIndexEnd != -1) { +// endList.add(lastIndexEnd); +// lastIndexEnd += end.length(); +// } +// } +// +// if (beginList.size() == endList.size()) { +// Map map = new HashMap(); +// for (int i = 0; i < beginList.size(); i++) { +// map.put(beginList.get(i), endList.get(i)); +// } +// return map; +// } +// return null; +// } + @Override public AlgorithmType checkForAlgorithmInput(String content) { if (content != null) { @@ -74,59 +154,149 @@ public AlgorithmType checkForAlgorithmInput(String content) { @Override public String renderQuantikz(String content) { - if (content.contains("\\begin{quantikz}")) { - String quantikzContent; - String originalContent = content; - String fileDownloadUri = null; - quantikzContent = content.substring(content.indexOf("\\\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); - String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; - String latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; - String docStart = "\\begin{document} \n"; - String docEnd = "\\end{document} \n"; - - try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { - fileWriter.write(latexDocClass + latexPackages + docStart + quantikzContent + docEnd); - } catch (IOException e) { - System.out.println(e.toString()); - e.printStackTrace(); +// if (content.contains("\\begin{quantikz}")) { +// String quantikzContent; +// String fileDownloadUri = null; +// quantikzContent = content.substring(content.indexOf("\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); +// String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; +// String latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; +// String docStart = "\\begin{document} \n"; +// String docEnd = " \\end{document} \n"; +// +// try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { +// fileWriter.write(latexDocClass + latexPackages + docStart + quantikzContent + docEnd); +// } catch (IOException e) { +// System.out.println(e.toString()); +// e.printStackTrace(); +// } +// try { +// Runtime rt = Runtime.getRuntime(); +// // On Windows put "cmd /c" +// Process pr = rt.exec("cmd /c pdflatex -shell-escape renderFile.tex"); +// pr.waitFor(); +// +// } catch (Exception e) { +// System.out.println(e.toString()); +// e.printStackTrace(); +// } +// //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ +// String fileName = null; +// try { +// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile +// Path path = Paths.get("./renderFile.png"); +// String name = "renderFile.png"; +// String originalFileName = "renderFile.png"; +// String contentType = "image/png"; +// byte[] pictureContent = null; +// try { +// pictureContent = Files.readAllBytes(path); +// } catch (final IOException e) { +// } +// MultipartFile multipartFile = new MockMultipartFile(name, +// originalFileName, contentType, pictureContent); +// fileName = fileStorageService.storeFile(multipartFile); +// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() +// .path("/downloadFile/") +// .path(fileName) +// .toUriString(); +// System.out.println(fileDownloadUri); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// String showimage = "![](" + fileDownloadUri + ")"; +// return content.replace(quantikzContent, showimage).replaceAll("\\\\", "\\\\\\\\"); +// } + return null; + } + + + @Override + public String renderLatex(String content, int begin, int end, AlgorithmType type) { + String renderContent = ""; + String latexPackages = ""; + String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; + String docStart = "\\begin{document} \n"; + String docEnd = " \\end{document} \n"; + String fileDownloadUri = null; + + if (type.equals(AlgorithmType.QUANTIKZ)) { + System.out.println(content + " " + begin + " "+ end); + renderContent = content.substring(begin, end + 14); + latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; + } else if(type.equals(AlgorithmType.QCIRCUIT)) { + renderContent = content.substring(begin, end + 4); + latexPackages = "\\usepackage[braket, qm]{qcircuit} \n" + "\\usepackage{amsmath} \n" + "\\usepackage{listings} \n" + "\\renewcommand{\\arraystretch}{1.5} \n"; + } + + try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { + fileWriter.write(latexDocClass + latexPackages + docStart + renderContent + docEnd); + } catch (IOException e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + try { +// Runtime rt = Runtime.getRuntime(); +// // On Windows put "cmd /c" +// Process pr = rt.exec("cmd /c pdflatex renderFile.tex"); + + ProcessBuilder processBuilder = new ProcessBuilder(); + processBuilder.command("cmd.exe", "/c", "pdflatex -shell-escape renderFile.tex"); + Process process = processBuilder.start(); + + StringBuilder output = new StringBuilder(); + + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line + "\n"); } - try { - Runtime rt = Runtime.getRuntime(); - // On Windows put "cmd /c" - Process pr = rt.exec("cmd /c pdflatex -shell-escape renderFile.tex"); - } catch (Exception e) { - System.out.println(e.toString()); - e.printStackTrace(); + + int exitVal = process.waitFor(); + if (exitVal == 0) { + System.out.println("Success!"); + System.out.println(output); + } else { + //abnormal... } - //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ - String fileName = null; + +// pr.waitFor(); + System.out.println("executing render"); + } catch (Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ + String fileName = null; + try { + //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile + Path path = Paths.get("./renderFile.png"); + String name = "renderFile.png"; + String originalFileName = "renderFile.png"; + String contentType = "image/png"; + byte[] pictureContent = null; try { - //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile - Path path = Paths.get("./renderFile.png"); - String name = "renderFile.png"; - String originalFileName = "renderFile.png"; - String contentType = "image/png"; - byte[] pictureContent = null; - try { - pictureContent = Files.readAllBytes(path); - } catch (final IOException e) { - } - MultipartFile multipartFile = new MockMultipartFile(name, - originalFileName, contentType, pictureContent); - fileName = fileStorageService.storeFile(multipartFile); - fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() - .path("/downloadFile/") - .path(fileName) - .toUriString(); - System.out.println(fileDownloadUri); - } catch (Exception e) { - e.printStackTrace(); + pictureContent = Files.readAllBytes(path); + } catch (final IOException e) { } + MultipartFile multipartFile = new MockMultipartFile(name, + originalFileName, contentType, pictureContent); + fileName = fileStorageService.storeFile(multipartFile); + fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() + .path("/downloadFile/") + .path(fileName) + .toUriString(); System.out.println(fileDownloadUri); - String showimage = "![](" + fileDownloadUri +")"; - return content.replace(quantikzContent , showimage).replaceAll("\\\\" , "\\\\\\\\" ); + } catch (Exception e) { + e.printStackTrace(); } - return null; + System.out.println(fileDownloadUri); + String showimage = "![](" + fileDownloadUri + ") "; + return content.replace(renderContent, showimage); + + } + } From d8ee671f332760bd505f14794b0262f5275829d8 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 5 May 2020 16:18:43 +0200 Subject: [PATCH 05/23] Adding images to Database instead of Filesystem. Integration of LatexRenderer --- .gitignore | 3 +- .../com/patternpedia/api/entities/Image.java | 29 ++ .../api/repositories/ImageRepository.java | 10 + .../api/rest/controller/ImageController.java | 42 +++ .../api/rest/model/AlgorithmType.java | 7 - .../api/rest/model/LatexContent.java | 25 ++ .../api/service/ImageService.java | 21 ++ .../api/service/ImageServiceImpl.java | 58 +++ .../api/service/PatternRenderService.java | 16 +- .../api/service/PatternRenderServiceImpl.java | 339 ++++++------------ 10 files changed, 309 insertions(+), 241 deletions(-) create mode 100644 src/main/java/com/patternpedia/api/entities/Image.java create mode 100644 src/main/java/com/patternpedia/api/repositories/ImageRepository.java create mode 100644 src/main/java/com/patternpedia/api/rest/controller/ImageController.java delete mode 100644 src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java create mode 100644 src/main/java/com/patternpedia/api/rest/model/LatexContent.java create mode 100644 src/main/java/com/patternpedia/api/service/ImageService.java create mode 100644 src/main/java/com/patternpedia/api/service/ImageServiceImpl.java diff --git a/.gitignore b/.gitignore index 6c4f85f..173b6aa 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ build/ *.tex *.pdf *.log -*.aux \ No newline at end of file +*.aux +*.svg \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/entities/Image.java b/src/main/java/com/patternpedia/api/entities/Image.java new file mode 100644 index 0000000..f0fc2cd --- /dev/null +++ b/src/main/java/com/patternpedia/api/entities/Image.java @@ -0,0 +1,29 @@ +package com.patternpedia.api.entities; + +import lombok.*; + +import org.hibernate.annotations.GenericGenerator; + + +import javax.persistence.*; +import java.util.UUID; + +@Entity +@Data +@NoArgsConstructor +@Getter +@Setter +public class Image { + + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + private UUID id; + + private String fileName; + + private String fileType; + + @Lob + private byte[] data; +} diff --git a/src/main/java/com/patternpedia/api/repositories/ImageRepository.java b/src/main/java/com/patternpedia/api/repositories/ImageRepository.java new file mode 100644 index 0000000..b6c9cbe --- /dev/null +++ b/src/main/java/com/patternpedia/api/repositories/ImageRepository.java @@ -0,0 +1,10 @@ +package com.patternpedia.api.repositories; + +import com.patternpedia.api.entities.Image; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import java.util.UUID; + +@RepositoryRestResource(exported = false) +public interface ImageRepository extends CrudRepository { +} diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java new file mode 100644 index 0000000..b62bca6 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -0,0 +1,42 @@ +package com.patternpedia.api.rest.controller; + + + +import com.fasterxml.jackson.databind.ObjectMapper; + +import com.patternpedia.api.service.ImageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; + + +@RestController +@CrossOrigin(allowedHeaders = "*", origins = "*") +public class ImageController { + + private ImageService imageService; + + @Autowired + public ImageController(ImageService imageService) { + this.imageService = imageService; + } + + @GetMapping( + value = "/getImageById/{imageId}", + produces = "image/svg+xml" + ) + public @ResponseBody + byte[] renderLatexAsPng(@PathVariable String imageId) throws IOException { + UUID uuid = UUID.fromString(imageId); + return this.imageService.getImageById(uuid).getData(); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java b/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java deleted file mode 100644 index df300ab..0000000 --- a/src/main/java/com/patternpedia/api/rest/model/AlgorithmType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.patternpedia.api.rest.model; - -public enum AlgorithmType { - QUANTIKZ, - QCIRCUIT, - NONE -} diff --git a/src/main/java/com/patternpedia/api/rest/model/LatexContent.java b/src/main/java/com/patternpedia/api/rest/model/LatexContent.java new file mode 100644 index 0000000..6427a82 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/LatexContent.java @@ -0,0 +1,25 @@ +package com.patternpedia.api.rest.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + + +@Getter +@Setter +@NoArgsConstructor +public class LatexContent { + private String content; + private List latexPackages; + private String output; + + public LatexContent(String content, List latexPackages, String output){ + this.content = content; + this.latexPackages = latexPackages; + this.output = output; + } + + +} diff --git a/src/main/java/com/patternpedia/api/service/ImageService.java b/src/main/java/com/patternpedia/api/service/ImageService.java new file mode 100644 index 0000000..f3850b1 --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/ImageService.java @@ -0,0 +1,21 @@ +package com.patternpedia.api.service; +import com.patternpedia.api.entities.Image; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; +import java.util.UUID; + +public interface ImageService { + + @Transactional + Image createImage(Image image); + + @Transactional(readOnly = true) + Image getImageById(UUID imageId); + + @Transactional + Image updateImage(Image image); + + @Transactional + void deleteImage(Image image); +} diff --git a/src/main/java/com/patternpedia/api/service/ImageServiceImpl.java b/src/main/java/com/patternpedia/api/service/ImageServiceImpl.java new file mode 100644 index 0000000..17cbeab --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/ImageServiceImpl.java @@ -0,0 +1,58 @@ +package com.patternpedia.api.service; + +import com.patternpedia.api.entities.Image; +import com.patternpedia.api.repositories.ImageRepository; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + + +import java.util.UUID; + +@Service +@Validated +@Transactional +public class ImageServiceImpl implements ImageService{ + + private ImageRepository imageRepository; + + public ImageServiceImpl(ImageRepository imageRepository){ + this.imageRepository = imageRepository; + } + + @Override + public Image createImage(Image image) { + if (null == image) { + throw new NullPointerException(); + } + + return this.imageRepository.save(image); + } + + @Override + @Transactional(readOnly = true) + public Image getImageById(UUID imageId) { + return this.imageRepository.findById(imageId).orElseThrow(() -> new ResourceNotFoundException("not found")); + } + + @Override + @Transactional + public Image updateImage(Image image) { + if (null == image) { + throw new NullPointerException(); + } + + return this.imageRepository.save(image); + } + + @Override + @Transactional + public void deleteImage(Image image) { + if (null == image) { + throw new NullPointerException(); + } + this.imageRepository.save(image); + this.imageRepository.deleteById(image.getId()); + } +} diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index 9c71778..ea50d49 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -1,26 +1,22 @@ package com.patternpedia.api.service; import com.patternpedia.api.entities.Pattern; -import com.patternpedia.api.rest.model.AlgorithmType; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; -import java.util.Map; - public interface PatternRenderService { @Transactional (readOnly = false) Object renderContent (Pattern pattern); - @Transactional (readOnly = false) - AlgorithmType checkForAlgorithmInput (String content); +// @Transactional (readOnly = false) +// AlgorithmType checkForAlgorithmInput (String content); - @Transactional (readOnly = false) - String renderQuantikz (String content) throws IOException; +// @Transactional (readOnly = false) +// String renderQuantikz (String content) throws IOException; // @Transactional (readOnly = false) // Map getBeginAndEndIndexes(String content, String begin, String end); - @Transactional (readOnly = false) - String renderLatex(String content, int begin, int end, AlgorithmType type); +// @Transactional (readOnly = false) +// String renderLatex(String content, int begin, int end, AlgorithmType type); } diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 2c446a6..3c85460 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -1,24 +1,22 @@ package com.patternpedia.api.service; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; +import com.patternpedia.api.entities.Image; import com.patternpedia.api.entities.Pattern; import com.patternpedia.api.filestorage.FileStorageService; -import com.patternpedia.api.rest.model.AlgorithmType; +import com.patternpedia.api.rest.model.LatexContent; import javafx.util.Pair; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.configurationprocessor.json.JSONArray; -import org.springframework.boot.configurationprocessor.json.JSONObject; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; -import java.io.*; +import java.net.URI; +import java.time.Instant; import java.util.*; @Component @@ -27,6 +25,9 @@ public class PatternRenderServiceImpl implements PatternRenderService { @Autowired private FileStorageService fileStorageService; + @Autowired + private ImageService imageService; + @Override public Object renderContent(Pattern pattern) { String jsonString = null; @@ -36,7 +37,6 @@ public Object renderContent(Pattern pattern) { try { jsonString = mapper.writeValueAsString(pattern.getContent()); // TODO: fix no newline issue. Optimize that only current section gets rendered on update - jsonString = jsonString.replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); System.out.println("notasstring" + pattern.getContent()); System.out.println("JSONSTRING" + jsonString); } catch (Exception e) { @@ -50,29 +50,48 @@ public Object renderContent(Pattern pattern) { //get all quantikz occurences boolean quantikz = true; while (quantikz) { - Pair occuranceStartEnd = getNextOccurance(jsonString, "\\begin{quantikz}", "\\end{quantikz}"); + Pair occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { - jsonString = renderLatex(jsonString, occuranceStartEnd.getKey(), occuranceStartEnd.getValue(),AlgorithmType.QUANTIKZ); + String renderContent = jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14) + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); + List settings = new ArrayList<>(); + settings.add("\\usepackage{tikz} \n"); + settings.add("\\usetikzlibrary{quantikz} \n"); + byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); + //filesystem version +// jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14), " ![](" + saveAndUploadFile(renderedFile, "svg") + ")"); }else { break; } } - //get all qcircuit occurences boolean qcircuit = true; while (qcircuit) { - Pair occuranceStartEnd = getNextOccurance(jsonString, "\\Qcircuit", "end}"); + Pair occuranceStartEnd = getNextOccurance(jsonString, "\\\\Qcircuit", "end}"); if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { - jsonString = renderLatex(jsonString, occuranceStartEnd.getKey(), occuranceStartEnd.getValue(),AlgorithmType.QCIRCUIT); + String renderContent = jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4) + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); + renderContent.replace("end}", "}"); + List settings = new ArrayList<>(); + settings.add("\\usepackage[braket, qm]{qcircuit} \n"); + settings.add("\\usepackage{amsmath} \n"); + settings.add("\\usepackage{listings} \n"); + settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); + byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4), " " + saveAndUploadFile(renderedFile, "svg") + " "); + //filesystem version +// jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4), " ![](" + saveAndUploadFile(renderedFile, "svg") + ")"); }else { break; } } + Map map = null; try { System.out.println(jsonString); - map = mapper.readValue(jsonString.replaceAll("\\\\", "\\\\\\\\"), Map.class); + map = mapper.readValue(jsonString, Map.class); } catch (Exception e) { e.printStackTrace(); } @@ -80,25 +99,6 @@ public Object renderContent(Pattern pattern) { return null; return map; -// AlgorithmType type = checkForAlgorithmInput(jsonString); -// switch (type) { -// case QUANTIKZ: -// Map map = null; -// try { -// String returnJson = renderQuantikz(jsonString); -// System.out.println(returnJson); -// map = mapper.readValue(returnJson, Map.class); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// return map; -// case QCIRCUIT: -// break; -// case NONE: -// return null; -// } - - } public Pair getNextOccurance(String content, String begin, String end) { @@ -106,197 +106,90 @@ public Pair getNextOccurance(String content, String begin, Str return new Pair<>(content.indexOf(begin, 0), content.indexOf(end, 0)); } -// @Override -// public Map getBeginAndEndIndexes(String content, String begin, String end) { -// int lastIndexBegin = 0; -// List beginList = new ArrayList<>(); -// while (lastIndexBegin != -1) { -// lastIndexBegin = content.indexOf(begin, lastIndexBegin); -// if (lastIndexBegin != -1) { -// beginList.add(lastIndexBegin); -// lastIndexBegin += begin.length(); -// } -// } -// -// int lastIndexEnd = 0; -// List endList = new ArrayList<>(); -// while (lastIndexEnd != -1) { -// lastIndexEnd = content.indexOf(end, lastIndexEnd); -// if (lastIndexEnd != -1) { -// endList.add(lastIndexEnd); -// lastIndexEnd += end.length(); -// } -// } -// -// if (beginList.size() == endList.size()) { -// Map map = new HashMap(); -// for (int i = 0; i < beginList.size(); i++) { -// map.put(beginList.get(i), endList.get(i)); -// } -// return map; -// } -// return null; -// } - @Override - public AlgorithmType checkForAlgorithmInput(String content) { - if (content != null) { - if (content.contains("\\begin{quantikz}")) { - System.out.println("Quantikz"); - return AlgorithmType.QUANTIKZ; - } - } - if (content.contains("\\Qcircuit")) { - return AlgorithmType.QCIRCUIT; + byte[] renderContentViaAPI(String content, List packages, String output){ + LatexContent latexContent = new LatexContent(content,packages,output); + byte[] file = null; + try{ + + RestTemplate restTemplate = new RestTemplate(); + final String baseUrl = "http://localhost:"+8081+"/renderLatex/"; + + URI uri = new URI(baseUrl); + HttpHeaders headers = new HttpHeaders(); + // set `content-type` header + headers.setContentType(MediaType.APPLICATION_JSON); + System.out.println("presend"); + HttpEntity entity = new HttpEntity<>(latexContent, headers); + ResponseEntity result = restTemplate.postForEntity(uri, entity, byte[].class); + file = result.getBody(); + } catch (Exception e){ + e.printStackTrace(); } - return AlgorithmType.NONE; +// System.out.println("filecontent" + new String(file, StandardCharsets.UTF_8)); + System.out.println("returnFileFromAPI"); + return file; } - @Override - public String renderQuantikz(String content) { -// if (content.contains("\\begin{quantikz}")) { -// String quantikzContent; -// String fileDownloadUri = null; -// quantikzContent = content.substring(content.indexOf("\\begin{quantikz}"), content.indexOf("\\end{quantikz}") + 14); -// String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; -// String latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; -// String docStart = "\\begin{document} \n"; -// String docEnd = " \\end{document} \n"; +// String saveAndUploadFile(byte[] file, String output){ +// System.out.println("save"); +// String fileName = null; +// String fileDownloadUri = null; +// try { +// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile +// String name = "renderFile."+output; +// String originalFileName = "renderFile."+output; +// String contentType = "image/svg+xml"; // -// try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { -// fileWriter.write(latexDocClass + latexPackages + docStart + quantikzContent + docEnd); -// } catch (IOException e) { -// System.out.println(e.toString()); -// e.printStackTrace(); -// } -// try { -// Runtime rt = Runtime.getRuntime(); -// // On Windows put "cmd /c" -// Process pr = rt.exec("cmd /c pdflatex -shell-escape renderFile.tex"); -// pr.waitFor(); // -// } catch (Exception e) { -// System.out.println(e.toString()); -// e.printStackTrace(); -// } -// //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ -// String fileName = null; -// try { -// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile -// Path path = Paths.get("./renderFile.png"); -// String name = "renderFile.png"; -// String originalFileName = "renderFile.png"; -// String contentType = "image/png"; -// byte[] pictureContent = null; -// try { -// pictureContent = Files.readAllBytes(path); -// } catch (final IOException e) { -// } -// MultipartFile multipartFile = new MockMultipartFile(name, -// originalFileName, contentType, pictureContent); -// fileName = fileStorageService.storeFile(multipartFile); -// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() -// .path("/downloadFile/") -// .path(fileName) -// .toUriString(); -// System.out.println(fileDownloadUri); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// String showimage = "![](" + fileDownloadUri + ")"; -// return content.replace(quantikzContent, showimage).replaceAll("\\\\", "\\\\\\\\"); +// MultipartFile multipartFile = new MockMultipartFile(name, +// originalFileName, contentType, file); +// fileName = fileStorageService.storeFile(multipartFile); +// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() +// .path("/downloadFile/") +// .path(fileName) +// .toUriString(); +// System.out.println(fileDownloadUri); +// return fileDownloadUri; +// } catch (Exception e) { +// e.printStackTrace(); // } - return null; - } - - - @Override - public String renderLatex(String content, int begin, int end, AlgorithmType type) { - String renderContent = ""; - String latexPackages = ""; - String latexDocClass = "\\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone} \n"; - String docStart = "\\begin{document} \n"; - String docEnd = " \\end{document} \n"; - String fileDownloadUri = null; - - if (type.equals(AlgorithmType.QUANTIKZ)) { - System.out.println(content + " " + begin + " "+ end); - renderContent = content.substring(begin, end + 14); - latexPackages = "\\usepackage{tikz} \n" + "\\usetikzlibrary{quantikz} \n"; - } else if(type.equals(AlgorithmType.QCIRCUIT)) { - renderContent = content.substring(begin, end + 4); - latexPackages = "\\usepackage[braket, qm]{qcircuit} \n" + "\\usepackage{amsmath} \n" + "\\usepackage{listings} \n" + "\\renewcommand{\\arraystretch}{1.5} \n"; - } - - try (FileWriter fileWriter = new FileWriter(new File("renderFile.tex"))) { - fileWriter.write(latexDocClass + latexPackages + docStart + renderContent + docEnd); - } catch (IOException e) { - System.out.println(e.toString()); - e.printStackTrace(); - } - try { -// Runtime rt = Runtime.getRuntime(); -// // On Windows put "cmd /c" -// Process pr = rt.exec("cmd /c pdflatex renderFile.tex"); - - ProcessBuilder processBuilder = new ProcessBuilder(); - processBuilder.command("cmd.exe", "/c", "pdflatex -shell-escape renderFile.tex"); - Process process = processBuilder.start(); - - StringBuilder output = new StringBuilder(); - - BufferedReader reader = new BufferedReader( - new InputStreamReader(process.getInputStream())); - - String line; - while ((line = reader.readLine()) != null) { - output.append(line + "\n"); - } - - int exitVal = process.waitFor(); - if (exitVal == 0) { - System.out.println("Success!"); - System.out.println(output); - } else { - //abnormal... - } - -// pr.waitFor(); - System.out.println("executing render"); - } catch (Exception e) { - System.out.println(e.toString()); - e.printStackTrace(); - } - //https://www.callicoder.com/spring-boot-file-upload-download-rest-api-example/ - String fileName = null; - try { - //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile - Path path = Paths.get("./renderFile.png"); - String name = "renderFile.png"; - String originalFileName = "renderFile.png"; - String contentType = "image/png"; - byte[] pictureContent = null; - try { - pictureContent = Files.readAllBytes(path); - } catch (final IOException e) { - } - MultipartFile multipartFile = new MockMultipartFile(name, - originalFileName, contentType, pictureContent); - fileName = fileStorageService.storeFile(multipartFile); - fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() - .path("/downloadFile/") - .path(fileName) - .toUriString(); - System.out.println(fileDownloadUri); - } catch (Exception e) { - e.printStackTrace(); - } - System.out.println(fileDownloadUri); - String showimage = "![](" + fileDownloadUri + ") "; - return content.replace(renderContent, showimage); - - +// return null; +// }; + + String saveAndUploadFile(byte[] file, String output) { + System.out.println("save"); + Image image = new Image(); + image.setData(file); + image.setFileName("latexRender" + Instant.now().getEpochSecond()); + image.setFileType("svg"); + Image uploadedImage = imageService.createImage(image); + return "" + uploadedImage.getId().toString() + ""; + +// String fileName = null; +// String fileDownloadUri = null; +// try { +// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile +// String name = "renderFile."+output; +// String originalFileName = "renderFile."+output; +// String contentType = "image/svg+xml"; +// +// +// MultipartFile multipartFile = new MockMultipartFile(name, +// originalFileName, contentType, file); +// fileName = fileStorageService.storeFile(multipartFile); +// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() +// .path("/downloadFile/") +// .path(fileName) +// .toUriString(); +// System.out.println(fileDownloadUri); +//// System.out.print(new String(imageService.getImageById(uploadedImage.getId()).getData(), StandardCharsets.UTF_8).replaceAll("\"", "\\\"")); +// return "" + uploadedImage.getId().toString() +""; +//// return fileDownloadUri; +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// }; } - - } From 753fea30e28a648f2ed21355dcb4323c287fe810 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 7 May 2020 16:36:52 +0200 Subject: [PATCH 06/23] Cleaning up Code --- .../com/patternpedia/api/PatternPediaAPI.java | 3 - .../api/filestorage/FileController.java | 70 ------------------ .../api/filestorage/FileStorageException.java | 11 --- .../filestorage/FileStorageProperties.java | 16 ---- .../api/filestorage/FileStorageService.java | 68 ----------------- .../filestorage/MyFileNotFoundException.java | 15 ---- .../api/rest/controller/ImageController.java | 9 --- .../rest/controller/PatternController.java | 1 - .../api/service/PatternRenderServiceImpl.java | 74 ------------------- 9 files changed, 267 deletions(-) delete mode 100644 src/main/java/com/patternpedia/api/filestorage/FileController.java delete mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageException.java delete mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java delete mode 100644 src/main/java/com/patternpedia/api/filestorage/FileStorageService.java delete mode 100644 src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java diff --git a/src/main/java/com/patternpedia/api/PatternPediaAPI.java b/src/main/java/com/patternpedia/api/PatternPediaAPI.java index 658e961..7ffdcd7 100644 --- a/src/main/java/com/patternpedia/api/PatternPediaAPI.java +++ b/src/main/java/com/patternpedia/api/PatternPediaAPI.java @@ -1,12 +1,10 @@ package com.patternpedia.api; -import com.patternpedia.api.filestorage.FileStorageProperties; import com.vladmihalcea.hibernate.type.util.Configuration; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -14,7 +12,6 @@ @EnableTransactionManagement @EnableWebMvc @Slf4j -@EnableConfigurationProperties({FileStorageProperties.class}) public class PatternPediaAPI implements CommandLineRunner { public static void main(String[] args) { diff --git a/src/main/java/com/patternpedia/api/filestorage/FileController.java b/src/main/java/com/patternpedia/api/filestorage/FileController.java deleted file mode 100644 index 177b938..0000000 --- a/src/main/java/com/patternpedia/api/filestorage/FileController.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.patternpedia.api.filestorage; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -@RestController -public class FileController { - - - @Autowired - private FileStorageService fileStorageService; - -// @PostMapping("/uploadFile") -// public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) { -// String fileName = fileStorageService.storeFile(file); -// -// String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() -// .path("/downloadFile/") -// .path(fileName) -// .toUriString(); -// -// return new UploadFileResponse(fileName, fileDownloadUri, -// file.getContentType(), file.getSize()); -// } -// -// @PostMapping("/uploadMultipleFiles") -// public List uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { -// return Arrays.asList(files) -// .stream() -// .map(file -> uploadFile(file)) -// .collect(Collectors.toList()); -// } - - //get saved picture - @GetMapping("/downloadFile/{fileName:.+}") - public ResponseEntity downloadFile(@PathVariable String fileName, HttpServletRequest request) { - // Load file as Resource - Resource resource = fileStorageService.loadFileAsResource(fileName); - - // Try to determine file's content type - String contentType = null; - try { - contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); - } catch (IOException ex) { - System.out.println("Could not determine file type."); - } - - // Fallback to the default content type if type could not be determined - if(contentType == null) { - contentType = "application/octet-stream"; - } - - return ResponseEntity.ok() - .contentType(MediaType.parseMediaType(contentType)) - .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"") - .body(resource); - } -} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java deleted file mode 100644 index c326b30..0000000 --- a/src/main/java/com/patternpedia/api/filestorage/FileStorageException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.patternpedia.api.filestorage; - -public class FileStorageException extends RuntimeException { - public FileStorageException(String message) { - super(message); - } - - public FileStorageException(String message, Throwable cause) { - super(message, cause); - } -} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java deleted file mode 100644 index d90f332..0000000 --- a/src/main/java/com/patternpedia/api/filestorage/FileStorageProperties.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.patternpedia.api.filestorage; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties(prefix = "file") -public class FileStorageProperties { - private String uploadDir; - - public String getUploadDir() { - return uploadDir; - } - - public void setUploadDir(String uploadDir) { - this.uploadDir = uploadDir; - } -} diff --git a/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java b/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java deleted file mode 100644 index 5e4338b..0000000 --- a/src/main/java/com/patternpedia/api/filestorage/FileStorageService.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.patternpedia.api.filestorage; - -import com.patternpedia.api.filestorage.FileStorageProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.Resource; -import org.springframework.core.io.UrlResource; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; -import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.net.MalformedURLException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.UUID; - -@Service -public class FileStorageService { - - private final Path fileStorageLocation; - - @Autowired - public FileStorageService(FileStorageProperties fileStorageProperties) { - this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir()) - .toAbsolutePath().normalize(); - - try { - Files.createDirectories(this.fileStorageLocation); - } catch (Exception ex) { - throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex); - } - } - - public String storeFile(MultipartFile file) { - // Normalize file name - String fileName = StringUtils.cleanPath( UUID.randomUUID()+file.getOriginalFilename()); - System.out.println("test" + fileName); - - try { - // Check if the file's name contains invalid characters - if (fileName.contains("..")) { - throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName); - } - - // Copy file to the target location (Replacing existing file with the same name) - Path targetLocation = this.fileStorageLocation.resolve(fileName); - Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING); - - return fileName; - } catch (IOException ex) { - throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex); - } - } - public Resource loadFileAsResource(String fileName) { - try { - Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); - Resource resource = new UrlResource(filePath.toUri()); - if(resource.exists()) { - return resource; - } else { - throw new MyFileNotFoundException("File not found " + fileName); - } - } catch (MalformedURLException ex) { - throw new MyFileNotFoundException("File not found " + fileName, ex); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java b/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java deleted file mode 100644 index 7534ff5..0000000 --- a/src/main/java/com/patternpedia/api/filestorage/MyFileNotFoundException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.patternpedia.api.filestorage; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(HttpStatus.NOT_FOUND) -public class MyFileNotFoundException extends RuntimeException { - public MyFileNotFoundException(String message) { - super(message); - } - - public MyFileNotFoundException(String message, Throwable cause) { - super(message, cause); - } -} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index b62bca6..750bbc5 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -1,19 +1,10 @@ package com.patternpedia.api.rest.controller; - - -import com.fasterxml.jackson.databind.ObjectMapper; - import com.patternpedia.api.service.ImageService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; - import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.UUID; diff --git a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java index 7c8c00f..2495385 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java @@ -362,7 +362,6 @@ EntityModel updatePatternViaPut(@PathVariable UUID patternLanguageId, @ persistedVersion.setIconUrl(pattern.getIconUrl()); persistedVersion.setContent(pattern.getContent()); Object renderedContent = patternRenderService.renderContent(pattern); - System.out.print(renderedContent); if (renderedContent != null){ persistedVersion.setRenderedContent(renderedContent); } else { diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 3c85460..ba398c9 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.patternpedia.api.entities.Image; import com.patternpedia.api.entities.Pattern; -import com.patternpedia.api.filestorage.FileStorageService; import com.patternpedia.api.rest.model.LatexContent; import javafx.util.Pair; import org.springframework.beans.factory.annotation.Autowired; @@ -21,10 +20,6 @@ @Component public class PatternRenderServiceImpl implements PatternRenderService { - - @Autowired - private FileStorageService fileStorageService; - @Autowired private ImageService imageService; @@ -32,13 +27,8 @@ public class PatternRenderServiceImpl implements PatternRenderService { public Object renderContent(Pattern pattern) { String jsonString = null; ObjectMapper mapper = new ObjectMapper(); - - //Converting the Object to JSONString try { jsonString = mapper.writeValueAsString(pattern.getContent()); - // TODO: fix no newline issue. Optimize that only current section gets rendered on update - System.out.println("notasstring" + pattern.getContent()); - System.out.println("JSONSTRING" + jsonString); } catch (Exception e) { e.printStackTrace(); } @@ -59,8 +49,6 @@ public Object renderContent(Pattern pattern) { settings.add("\\usetikzlibrary{quantikz} \n"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); - //filesystem version -// jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14), " ![](" + saveAndUploadFile(renderedFile, "svg") + ")"); }else { break; } @@ -80,8 +68,6 @@ public Object renderContent(Pattern pattern) { settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4), " " + saveAndUploadFile(renderedFile, "svg") + " "); - //filesystem version -// jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4), " ![](" + saveAndUploadFile(renderedFile, "svg") + ")"); }else { break; } @@ -90,7 +76,6 @@ public Object renderContent(Pattern pattern) { Map map = null; try { - System.out.println(jsonString); map = mapper.readValue(jsonString, Map.class); } catch (Exception e) { e.printStackTrace(); @@ -102,7 +87,6 @@ public Object renderContent(Pattern pattern) { } public Pair getNextOccurance(String content, String begin, String end) { - System.out.println("content" + content); return new Pair<>(content.indexOf(begin, 0), content.indexOf(end, 0)); } @@ -111,85 +95,27 @@ byte[] renderContentViaAPI(String content, List packages, String output) LatexContent latexContent = new LatexContent(content,packages,output); byte[] file = null; try{ - RestTemplate restTemplate = new RestTemplate(); final String baseUrl = "http://localhost:"+8081+"/renderLatex/"; - URI uri = new URI(baseUrl); HttpHeaders headers = new HttpHeaders(); - // set `content-type` header headers.setContentType(MediaType.APPLICATION_JSON); - System.out.println("presend"); HttpEntity entity = new HttpEntity<>(latexContent, headers); ResponseEntity result = restTemplate.postForEntity(uri, entity, byte[].class); file = result.getBody(); } catch (Exception e){ e.printStackTrace(); } -// System.out.println("filecontent" + new String(file, StandardCharsets.UTF_8)); - System.out.println("returnFileFromAPI"); return file; } -// String saveAndUploadFile(byte[] file, String output){ -// System.out.println("save"); -// String fileName = null; -// String fileDownloadUri = null; -// try { -// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile -// String name = "renderFile."+output; -// String originalFileName = "renderFile."+output; -// String contentType = "image/svg+xml"; -// -// -// MultipartFile multipartFile = new MockMultipartFile(name, -// originalFileName, contentType, file); -// fileName = fileStorageService.storeFile(multipartFile); -// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() -// .path("/downloadFile/") -// .path(fileName) -// .toUriString(); -// System.out.println(fileDownloadUri); -// return fileDownloadUri; -// } catch (Exception e) { -// e.printStackTrace(); -// } -// return null; -// }; String saveAndUploadFile(byte[] file, String output) { - System.out.println("save"); Image image = new Image(); image.setData(file); image.setFileName("latexRender" + Instant.now().getEpochSecond()); image.setFileType("svg"); Image uploadedImage = imageService.createImage(image); return "" + uploadedImage.getId().toString() + ""; - -// String fileName = null; -// String fileDownloadUri = null; -// try { -// //https://stackoverflow.com/questions/16648549/converting-file-to-multipartfile -// String name = "renderFile."+output; -// String originalFileName = "renderFile."+output; -// String contentType = "image/svg+xml"; -// -// -// MultipartFile multipartFile = new MockMultipartFile(name, -// originalFileName, contentType, file); -// fileName = fileStorageService.storeFile(multipartFile); -// fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() -// .path("/downloadFile/") -// .path(fileName) -// .toUriString(); -// System.out.println(fileDownloadUri); -//// System.out.print(new String(imageService.getImageById(uploadedImage.getId()).getData(), StandardCharsets.UTF_8).replaceAll("\"", "\\\"")); -// return "" + uploadedImage.getId().toString() +""; -//// return fileDownloadUri; -// } catch (Exception e) { -// e.printStackTrace(); -// } -// return null; -// }; } } From f1f11da82f2d48fabf56c1bf126dd179468ff693 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 21 May 2020 14:36:56 +0200 Subject: [PATCH 07/23] Cleaning up code and fixing interface + changing data.sql id numbers into uuids --- .../api/rest/controller/ImageController.java | 3 +-- .../api/service/PatternRenderService.java | 17 ++++++++--------- .../api/service/PatternRenderServiceImpl.java | 4 ++-- src/main/resources/data.sql | 14 +++++++------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index 750bbc5..131cbb7 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -4,7 +4,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import java.io.IOException; import java.util.UUID; @@ -24,7 +23,7 @@ public ImageController(ImageService imageService) { produces = "image/svg+xml" ) public @ResponseBody - byte[] renderLatexAsPng(@PathVariable String imageId) throws IOException { + byte[] renderLatexAsPng(@PathVariable String imageId){ UUID uuid = UUID.fromString(imageId); return this.imageService.getImageById(uuid).getData(); } diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index ea50d49..29209cc 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -1,22 +1,21 @@ package com.patternpedia.api.service; import com.patternpedia.api.entities.Pattern; +import javafx.util.Pair; import org.springframework.transaction.annotation.Transactional; +import java.util.List; public interface PatternRenderService { @Transactional (readOnly = false) Object renderContent (Pattern pattern); -// @Transactional (readOnly = false) -// AlgorithmType checkForAlgorithmInput (String content); - -// @Transactional (readOnly = false) -// String renderQuantikz (String content) throws IOException; + @Transactional (readOnly = false) + Pair getNextOccurance(String content, String begin, String end); -// @Transactional (readOnly = false) -// Map getBeginAndEndIndexes(String content, String begin, String end); + @Transactional (readOnly = false) + byte [] renderContentViaAPI(String content, List packages, String output); -// @Transactional (readOnly = false) -// String renderLatex(String content, int begin, int end, AlgorithmType type); + @Transactional (readOnly = false) + String saveAndUploadFile(byte[] file, String output); } diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index ba398c9..e4a6733 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -91,7 +91,7 @@ public Pair getNextOccurance(String content, String begin, Str } - byte[] renderContentViaAPI(String content, List packages, String output){ + public byte[] renderContentViaAPI(String content, List packages, String output){ LatexContent latexContent = new LatexContent(content,packages,output); byte[] file = null; try{ @@ -110,7 +110,7 @@ byte[] renderContentViaAPI(String content, List packages, String output) } - String saveAndUploadFile(byte[] file, String output) { + public String saveAndUploadFile(byte[] file, String output) { Image image = new Image(); image.setData(file); image.setFileName("latexRender" + Instant.now().getEpochSecond()); diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 59ab4ac..e71eeb9 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -4,13 +4,13 @@ INSERT INTO public.pattern_language (id, name, uri, logo) VALUES ('82146836-1f69 INSERT INTO public.pattern_language (id, name, uri, logo) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', 'QC Patterns', 'https://patternpedia.org/patternLanguages/qcPatterns', null); INSERT INTO public.pattern_schema (pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (1, 'Intend', 'Intend', 0, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (2, 'Driving Question', 'Driving Question', 1, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (3, 'Icon', 'Icon', 2, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (4, 'Context', 'Context', 3, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (5, 'Solution', 'Solution', 4, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (6, 'Known uses', 'Known uses', 5, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES (7, 'Next', 'Next', 6, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e22b-4ab6-a98b-0e0738323ca9', 'Intend', 'Intend', 0, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e53b-4ab6-a98b-0e0738323ca9', 'Driving Question', 'Driving Question', 1, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ac6-a98b-0e0738323ca9', 'Icon', 'Icon', 2, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a28b-0e0738323ca9', 'Context', 'Context', 3, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e3738323ca9', 'Solution', 'Solution', 4, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0538323ca9', 'Known uses', 'Known uses', 5, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); +INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0538363ca9', 'Next', 'Next', 6, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7665', 'TestPattern1', 'http://patternpedia.org/TestPattern1', '{"a": "b"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7666', 'TestPattern2', 'http://patternpedia.org/TestPattern2', '{"c": "d"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); From 1eb5fbfd0bb936d31b0d4f5dea8af4bff20dda49 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 28 May 2020 14:46:07 +0200 Subject: [PATCH 08/23] Removing Data.sql files --- .../rest/controller/PatternController.java | 7 +--- src/main/resources/application.properties | 14 ------- src/main/resources/data.sql | 42 ------------------- src/main/resources/db/migration/V1__ddl.sql | 21 ---------- src/main/resources/db/migration/V2__data.sql | 14 ------- 5 files changed, 1 insertion(+), 97 deletions(-) delete mode 100644 src/main/resources/data.sql delete mode 100644 src/main/resources/db/migration/V1__ddl.sql delete mode 100644 src/main/resources/db/migration/V2__data.sql diff --git a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java index 9191a44..f3bcb3f 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java @@ -1,12 +1,9 @@ package com.patternpedia.api.rest.controller; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; + import java.util.*; import java.util.stream.Collectors; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.patternpedia.api.entities.DirectedEdge; import com.patternpedia.api.entities.Pattern; import com.patternpedia.api.entities.PatternLanguage; @@ -24,8 +21,6 @@ import org.apache.commons.text.CaseUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.data.util.Pair; -import org.apache.tomcat.util.json.JSONParser; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e21514f..3a15e27 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,17 +9,3 @@ spring.datasource.initialization-mode=always spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true #okta.oauth2.issuer=https://dev-918271.okta.com/oauth2/default #okta.oauth2.clientId=0oa1eflyl1wZDVLLg357 - -## MULTIPART (MultipartProperties) -# Enable multipart uploads -spring.servlet.multipart.enabled=true -# Threshold after which files are written to disk. -spring.servlet.multipart.file-size-threshold=2KB -# Max file size. -spring.servlet.multipart.max-file-size=200MB -# Max Request Size -spring.servlet.multipart.max-request-size=215MB - -## File Storage Properties -# All files uploaded through the REST API will be stored in this directory -file.upload-dir=./src/main/resources/images diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql deleted file mode 100644 index e71eeb9..0000000 --- a/src/main/resources/data.sql +++ /dev/null @@ -1,42 +0,0 @@ - -INSERT INTO public.pattern_language (id, name, uri, logo) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7663', 'Cloud Computing Patterns', 'https://patternpedia.org/patternlanguages/cloudcomputingpatterns', 'https://www.cloudcomputingpatterns.org/img/book.png'); -INSERT INTO public.pattern_language (id, name, uri, logo) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7664', 'Enterprise Integration Patterns', 'https://patternpedia.org/patternlanguages/enterpriseintegrationpatterns', 'https://www.enterpriseintegrationpatterns.com/img/0321200683.gif'); -INSERT INTO public.pattern_language (id, name, uri, logo) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', 'QC Patterns', 'https://patternpedia.org/patternLanguages/qcPatterns', null); -INSERT INTO public.pattern_schema (pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); - -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e22b-4ab6-a98b-0e0738323ca9', 'Intend', 'Intend', 0, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e53b-4ab6-a98b-0e0738323ca9', 'Driving Question', 'Driving Question', 1, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ac6-a98b-0e0738323ca9', 'Icon', 'Icon', 2, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a28b-0e0738323ca9', 'Context', 'Context', 3, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e3738323ca9', 'Solution', 'Solution', 4, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0538323ca9', 'Known uses', 'Known uses', 5, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern_section_schema (id, label, name, position, type, pattern_schema_pattern_language_id) VALUES ('54b5c9fa-e25b-4ab6-a98b-0e0538363ca9', 'Next', 'Next', 6, 'any', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); - -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7665', 'TestPattern1', 'http://patternpedia.org/TestPattern1', '{"a": "b"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7666', 'TestPattern2', 'http://patternpedia.org/TestPattern2', '{"c": "d"}', '{"a": "b"}', '82146836-1f69-4f8d-81c5-3d87a8db7663'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('67d9b3fa-f6d6-4c0d-a239-695c2998c71e', 'Uniform Superposition', 'https://patternpedia.org/patternLanguages/qcPatternsUniform%20Superposition', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '{"Icon": "![enter image description here](http://www.cloudcomputingpatterns.org/icons/static_workload_icon.png)", "Next": "Creating uniform superposition makes use of initialization. A register in uniform superposition may be entangled. A register in uniform superposition may be input to an oracle.", "Intend": "Typically, the individual qbits of a quantum register have to be in multiple states at the same time without preferring any at these states at the beginning of the computation.", "Context": "One origin of the power of quantum algorithms stems from quantum parallelism, i.e. the ability of a quantum register to represent multiple values at the same time. This is achieved by bringing (a subset of) the qbits of a quantum register into superposition. Many algorithms assume that at the beginning this superposition is uniform, i.e. the probability of measuring any of the qbits is the same.", "Solution": "Uniform superposition is achieved by initializing the quantum register as the unit vector $|0...0\\rangle$ and applying the Hadamard tranformation afterwards: \n$$H^{\\bigotimes n}(|0\\rangle^{n})=\\frac{1}{\\sqrt{2^n}}\\sum_ {x=0}^{2^n-1}|x\\rangle$$\nIn case the quantum register includes ancilla bits or workspace bits in addition to the computational basis, the computational basis is brought into superposition as described. The other bits may be brought into superposition themselves or not. This is achieved by using a tensor product $H^{\\bigotimes n}\\bigotimes U$, where $H^{\\bigotimes n}$ operates on the computational basis and $U$ operates on the other bits (e.g., $U=I$ in case the other bits are not brought into superposition).", "Known uses": "Most algorithms make use of uniform superposition", "Driving Question": "How can an equally weighted superposition of all possible states of the qbits of a quantum register be created?"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('1321dd9c-52c7-4b76-a1f3-3b567c3c7780', 'PatternA', 'https://patternpedia.org/patternLanguages/qcPatternsPatternA', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here. #renderedcontent"}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('b6a4503a-5385-4bd4-879e-b9c7998820bd', 'PatternB', 'https://patternpedia.org/patternLanguages/qcPatternsPatternB', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('13b1fbfe-369d-4e0c-8273-68d5fc1bedbe', 'Pattern4', 'https://patternpedia.org/patternLanguages/qcPatternsPattern4', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('10c55d72-b870-4a65-9c08-b5b38f0a17c8', 'PatternCD', 'https://patternpedia.org/patternLanguages/qcPatternsPatternCD', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('5243010e-82fe-4e02-a963-f736ab93c31f', 'Pattern5', 'https://patternpedia.org/patternLanguages/qcPatternsPattern5', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('43f2d8b5-467c-4ba5-afee-9340617f4c63', 'Pattern6', 'https://patternpedia.org/patternLanguages/qcPatternsPattern6', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('dbcdc0d1-e870-4858-924f-7789083827cf', 'Pattern name with a very very long title', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20name%20with%20a%20very%20very%20long%20title', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('84bc7222-cc07-4c93-b40d-41e7870d16e6', 'PatternE', 'https://patternpedia.org/patternLanguages/qcPatternsPatternE', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.pattern (id, name, uri, content, rendered_content, pattern_language_id) VALUES ('e633a551-e033-4c23-b3c3-2cffda4b3cd5', 'Pattern DF', 'https://patternpedia.org/patternLanguages/qcPatternsPattern%20DF', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '{"Icon": "Enter your input for this section here.", "Next": "Enter your input for this section here.", "Intend": "Enter your input for this section here.", "Context": "Enter your input for this section here.", "Solution": "Enter your input for this section here.", "Known uses": "Enter your input for this section here.", "Driving Question": "Enter your input for this section here."}', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); - -INSERT INTO public.pattern_view (id, name, uri) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7690', 'TestView', 'https://patternpedia.org/patternViews/TestView'); -INSERT INTO public.pattern_view (id, name, uri) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7691', 'TestView2', 'https://patternpedia.org/patternViews/TestView2'); -INSERT INTO public.pattern_view_pattern (pattern_view_id, pattern_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7690', '82146836-1f69-4f8d-81c5-3d87a8db7666'); -INSERT INTO public.pattern_view_pattern (pattern_view_id, pattern_id) VALUES ('82146836-1f69-4f8d-81c5-3d87a8db7691', '82146836-1f69-4f8d-81c5-3d87a8db7666'); - -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('ffb2e8a1-14f1-4e29-a6aa-284a5bff40f6', 'null', 'isUsedBefore', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '1321dd9c-52c7-4b76-a1f3-3b567c3c7780', 'b6a4503a-5385-4bd4-879e-b9c7998820bd'); -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('79f256f3-5de1-4b55-b692-872dd99d89e7', 'null', 'isUsedAfter', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '67d9b3fa-f6d6-4c0d-a239-695c2998c71e', '1321dd9c-52c7-4b76-a1f3-3b567c3c7780'); -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('38be2910-aa36-4310-8888-8079387754c2', 'null', 'isUsedAfter', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '10c55d72-b870-4a65-9c08-b5b38f0a17c8', 'b6a4503a-5385-4bd4-879e-b9c7998820bd'); -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('8d60f611-4fae-4d67-ae5a-3c90d7d8d301', 'null', 'isRelatedTo', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '13b1fbfe-369d-4e0c-8273-68d5fc1bedbe', '10c55d72-b870-4a65-9c08-b5b38f0a17c8'); -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('bbbb0014-c31a-443c-ae62-4a1b763fff14', 'null', 'isRelatedTo', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '84bc7222-cc07-4c93-b40d-41e7870d16e6', 'b6a4503a-5385-4bd4-879e-b9c7998820bd'); -INSERT INTO public.directed_edge (id, description, type, pattern_language_id, source_id, target_id) VALUES ('e5beb9f7-4452-43ab-bb0e-e09605bb9a5d', 'null', 'isRelatedTo', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9', '84bc7222-cc07-4c93-b40d-41e7870d16e6', 'e633a551-e033-4c23-b3c3-2cffda4b3cd5'); - -INSERT INTO public.undirected_edge (id, description, type, p1_id, p2_id, pattern_language_id) VALUES ('9b100c69-7d89-4f18-882d-1a74068a3301', 'null', 'isRelatedTo', 'b6a4503a-5385-4bd4-879e-b9c7998820bd', '67d9b3fa-f6d6-4c0d-a239-695c2998c71e', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); -INSERT INTO public.undirected_edge (id, description, type, p1_id, p2_id, pattern_language_id) VALUES ('3267abbf-1435-436f-865e-278cd200038e', 'null', 'isUsedAfter', '10c55d72-b870-4a65-9c08-b5b38f0a17c8', '84bc7222-cc07-4c93-b40d-41e7870d16e6', '54b5c9fa-e25b-4ab6-a98b-0e0738323ca9'); - diff --git a/src/main/resources/db/migration/V1__ddl.sql b/src/main/resources/db/migration/V1__ddl.sql deleted file mode 100644 index d032cf5..0000000 --- a/src/main/resources/db/migration/V1__ddl.sql +++ /dev/null @@ -1,21 +0,0 @@ -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; - -CREATE TABLE pattern -( - id UUID NOT NULL, - uri varchar(255), - name varchar(255), - content jsonb, - renderedContent jsonb, - PRIMARY KEY (id) -); - -CREATE TABLE pattern_language -( - id UUID NOT NULL, - uri varchar(255), - name varchar(255), - content jsonb, - renderedContent jsonb, - PRIMARY KEY (id) -); \ No newline at end of file diff --git a/src/main/resources/db/migration/V2__data.sql b/src/main/resources/db/migration/V2__data.sql deleted file mode 100644 index 01f4e8f..0000000 --- a/src/main/resources/db/migration/V2__data.sql +++ /dev/null @@ -1,14 +0,0 @@ -INSERT INTO pattern - ( - id, - content, - name, - uri - ) -VALUES - ( - '531e4cdd-bb78-4769-a0c7-cb948a9f1238', - '{"name":"test pattern","problem":"XXX","context":"YYY","solution":"ZZZ"}', - 'test pattern', - 'http://purl.org/patternpedia/testpattern' - ); \ No newline at end of file From c84ee641ce199b7c9f79bcada93a36742c513075 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 28 May 2020 17:22:51 +0200 Subject: [PATCH 09/23] Replacing all Pair references --- .../api/service/PatternRenderService.java | 4 ++-- .../api/service/PatternRenderServiceImpl.java | 22 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index 29209cc..9a53d8e 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -1,17 +1,17 @@ package com.patternpedia.api.service; import com.patternpedia.api.entities.Pattern; -import javafx.util.Pair; import org.springframework.transaction.annotation.Transactional; import java.util.List; + public interface PatternRenderService { @Transactional (readOnly = false) Object renderContent (Pattern pattern); @Transactional (readOnly = false) - Pair getNextOccurance(String content, String begin, String end); + Integer[] getNextOccurance(String content, String begin, String end); @Transactional (readOnly = false) byte [] renderContentViaAPI(String content, List packages, String output); diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index e4a6733..c0c9f30 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -4,13 +4,11 @@ import com.patternpedia.api.entities.Image; import com.patternpedia.api.entities.Pattern; import com.patternpedia.api.rest.model.LatexContent; -import javafx.util.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; - import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @@ -40,15 +38,15 @@ public Object renderContent(Pattern pattern) { //get all quantikz occurences boolean quantikz = true; while (quantikz) { - Pair occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); - if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { - String renderContent = jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14) + Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); + if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { + String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); List settings = new ArrayList<>(); settings.add("\\usepackage{tikz} \n"); settings.add("\\usetikzlibrary{quantikz} \n"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); - jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); }else { break; } @@ -56,9 +54,9 @@ public Object renderContent(Pattern pattern) { boolean qcircuit = true; while (qcircuit) { - Pair occuranceStartEnd = getNextOccurance(jsonString, "\\\\Qcircuit", "end}"); - if (occuranceStartEnd.getKey() != -1 && occuranceStartEnd.getValue() != -1) { - String renderContent = jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4) + Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\Qcircuit", "end}"); + if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { + String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); renderContent.replace("end}", "}"); List settings = new ArrayList<>(); @@ -67,7 +65,7 @@ public Object renderContent(Pattern pattern) { settings.add("\\usepackage{listings} \n"); settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); - jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd.getKey(), occuranceStartEnd.getValue() + 4), " " + saveAndUploadFile(renderedFile, "svg") + " "); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + saveAndUploadFile(renderedFile, "svg") + " "); }else { break; } @@ -86,8 +84,8 @@ public Object renderContent(Pattern pattern) { } - public Pair getNextOccurance(String content, String begin, String end) { - return new Pair<>(content.indexOf(begin, 0), content.indexOf(end, 0)); + public Integer[] getNextOccurance(String content, String begin, String end) { + return new Integer[]{content.indexOf(begin, 0), content.indexOf(end, 0)}; } From 29d3f1c1b54b4adf2d5586aa1107d285f54747a5 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 2 Jun 2020 15:20:53 +0200 Subject: [PATCH 10/23] Adding update Image method and changing RenderService logic to detect already rendered latex code snippets --- .../api/rest/controller/ImageController.java | 20 ++++++- .../rest/controller/PatternController.java | 12 ++-- .../api/service/PatternRenderService.java | 2 +- .../api/service/PatternRenderServiceImpl.java | 56 +++++++++++++++---- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index 131cbb7..af02bd8 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -1,5 +1,6 @@ package com.patternpedia.api.rest.controller; +import com.patternpedia.api.entities.Image; import com.patternpedia.api.service.ImageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -23,10 +24,27 @@ public ImageController(ImageService imageService) { produces = "image/svg+xml" ) public @ResponseBody - byte[] renderLatexAsPng(@PathVariable String imageId){ + byte[] getImageById(@PathVariable String imageId){ UUID uuid = UUID.fromString(imageId); return this.imageService.getImageById(uuid).getData(); } + @PostMapping( + value = "/updateImage/{imageId}", + produces = "image/svg+xml" + ) + public @ResponseBody + byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ + UUID uuid = UUID.fromString(imageId); + System.out.println("image" + data); + System.out.println("id" + uuid); + Image image = new Image(); + image.setId(uuid); + image.setData(data); + image.setFileName(imageId); + image.setFileType("image/svg+xml"); + return this.imageService.updateImage(image).getData(); + } + } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java index f28869f..22d80ab 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/PatternController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/PatternController.java @@ -298,7 +298,7 @@ CollectionModel> getPatternsOfPatternView(@PathVariabl @CrossOrigin(exposedHeaders = "Location") @ResponseStatus(HttpStatus.CREATED) public ResponseEntity addPatternToPatternView(@PathVariable UUID patternViewId, @RequestBody Pattern pattern) { - Object renderedContent = patternRenderService.renderContent(pattern); + Object renderedContent = patternRenderService.renderContent(pattern, null); if (renderedContent != null){ pattern.setRenderedContent(renderedContent); } else { @@ -330,7 +330,7 @@ ResponseEntity addPatternToPatternLanguage(@PathVariable UUID patternLanguage if (null == pattern.getUri()) { pattern.setUri(patternLanguage.getUri() + '/' + CaseUtils.toCamelCase(pattern.getName(), false)); } - Object renderedContent = patternRenderService.renderContent(pattern); + Object renderedContent = patternRenderService.renderContent(pattern, null); if (renderedContent != null){ pattern.setRenderedContent(renderedContent); } else { @@ -355,15 +355,15 @@ EntityModel updatePatternViaPut(@PathVariable UUID patternLanguageId, @ PatternLanguage patternLanguage = this.patternLanguageService.getPatternLanguageById(patternLanguageId); Pattern persistedVersion = this.patternService.getPatternById(patternId); // Remark: At the moment we do not support changing name, uri of a pattern - persistedVersion.setIconUrl(pattern.getIconUrl()); - persistedVersion.setContent(pattern.getContent()); - Object renderedContent = patternRenderService.renderContent(pattern); + + Object renderedContent = patternRenderService.renderContent(pattern, persistedVersion); if (renderedContent != null){ persistedVersion.setRenderedContent(renderedContent); } else { persistedVersion.setRenderedContent(pattern.getContent()); } - + persistedVersion.setIconUrl(pattern.getIconUrl()); + persistedVersion.setContent(pattern.getContent()); pattern = this.patternService.updatePattern(persistedVersion); return new EntityModel<>(pattern, diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderService.java b/src/main/java/com/patternpedia/api/service/PatternRenderService.java index 9a53d8e..aa0379c 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderService.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderService.java @@ -8,7 +8,7 @@ public interface PatternRenderService { @Transactional (readOnly = false) - Object renderContent (Pattern pattern); + Object renderContent (Pattern pattern, Pattern oldVersion); @Transactional (readOnly = false) Integer[] getNextOccurance(String content, String begin, String end); diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index c0c9f30..c15180d 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -22,11 +22,15 @@ public class PatternRenderServiceImpl implements PatternRenderService { private ImageService imageService; @Override - public Object renderContent(Pattern pattern) { + public Object renderContent(Pattern pattern, Pattern oldVersion) { String jsonString = null; + String contentOld = ""; + String renderedContentOld = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonString = mapper.writeValueAsString(pattern.getContent()); + contentOld = mapper.writeValueAsString(oldVersion.getContent()); + renderedContentOld = mapper.writeValueAsString(oldVersion.getRenderedContent()); } catch (Exception e) { e.printStackTrace(); } @@ -36,24 +40,54 @@ public Object renderContent(Pattern pattern) { return null; //get all quantikz occurences - boolean quantikz = true; - while (quantikz) { + ArrayList oldContentOccurances = new ArrayList<>(); + ArrayList oldSVGOccurances = new ArrayList<>(); + while(true){ + Integer[] occuranceStartEndOld = getNextOccurance(contentOld, "\\\\begin{quantikz}", "\\end{quantikz}"); + Integer[] svgOccurencesOld = getNextOccurance(renderedContentOld, "", ""); + if (occuranceStartEndOld[0] != -1 && occuranceStartEndOld[1] != -1 && svgOccurencesOld[0] != -1 && svgOccurencesOld[1] != -1) { + oldContentOccurances.add(contentOld.substring(occuranceStartEndOld[0], occuranceStartEndOld[1] + 14) + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") + .replaceAll("\\\\\\\\","\\\\")); + oldSVGOccurances.add(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6)); + contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOld[0], occuranceStartEndOld[1] + 14), " "); + renderedContentOld = renderedContentOld.replace(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6), " "); + } + else { + break; + } + } + oldContentOccurances.forEach(s -> System.out.print("OLD CONTENT" + s)); + oldSVGOccurances.forEach(s -> System.out.println("OLD SVG" +s)); + + while (true) { Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14) - .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); - List settings = new ArrayList<>(); - settings.add("\\usepackage{tikz} \n"); - settings.add("\\usetikzlibrary{quantikz} \n"); - byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); - jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") + .replaceAll("\\\\\\\\","\\\\"); + boolean occured = false; + for (int i = 0; i < oldContentOccurances.size(); i++){ + if(oldContentOccurances.get(i).equals(renderContent)){ + occured = true; + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + oldSVGOccurances.get(i) + " "); + System.out.print("INSIDE OF EQUALS FOR " + i + " " + jsonString); + } + } + if(!occured){ + List settings = new ArrayList<>(); + settings.add("\\usepackage{tikz} \n"); + settings.add("\\usetikzlibrary{quantikz} \n"); + byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); + System.out.println("OUTSIDE OF EQUALS" + jsonString); + } }else { break; } } - boolean qcircuit = true; - while (qcircuit) { + while (true) { Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\Qcircuit", "end}"); if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4) From d2265713f5b8b3e3a9da87f4ed417f7206fb3af4 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Mon, 8 Jun 2020 16:04:12 +0200 Subject: [PATCH 11/23] Adding functionality to save and update DiscussionTopics and DiscussionComments in the Database --- .../api/entities/DiscussionComment.java | 34 ++++++++++ .../api/entities/DiscussionTopic.java | 45 +++++++++++++ .../DiscussionCommentRepository.java | 11 ++++ .../DiscussionTopicRepository.java | 12 ++++ .../rest/controller/DiscussionController.java | 55 ++++++++++++++++ .../api/rest/controller/ImageController.java | 5 +- .../patternpedia/api/rest/model/Status.java | 6 ++ .../api/service/DiscussionService.java | 29 +++++++++ .../api/service/DiscussionServiceImpl.java | 63 +++++++++++++++++++ 9 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/patternpedia/api/entities/DiscussionComment.java create mode 100644 src/main/java/com/patternpedia/api/entities/DiscussionTopic.java create mode 100644 src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java create mode 100644 src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java create mode 100644 src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java create mode 100644 src/main/java/com/patternpedia/api/rest/model/Status.java create mode 100644 src/main/java/com/patternpedia/api/service/DiscussionService.java create mode 100644 src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java diff --git a/src/main/java/com/patternpedia/api/entities/DiscussionComment.java b/src/main/java/com/patternpedia/api/entities/DiscussionComment.java new file mode 100644 index 0000000..ab7c945 --- /dev/null +++ b/src/main/java/com/patternpedia/api/entities/DiscussionComment.java @@ -0,0 +1,34 @@ +package com.patternpedia.api.entities; + + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.*; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import java.util.Date; +import java.util.UUID; + + + +@Entity +@Data +@NoArgsConstructor +@Getter +@Setter +public class DiscussionComment { + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + private UUID id; + private String text; + private UUID replyTo; + private Date date; + + @JsonIgnore + @ToString.Exclude + @ManyToOne + private DiscussionTopic discussionTopic; + + +} diff --git a/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java new file mode 100644 index 0000000..c35bd28 --- /dev/null +++ b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java @@ -0,0 +1,45 @@ +package com.patternpedia.api.entities; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.patternpedia.api.rest.model.Status; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Entity +@Data +@Getter +@Setter +@NoArgsConstructor +public class DiscussionTopic { + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + private UUID id; + + private String title; + + private String description; + + private Status status; + + private Date date; + + private Double x; + + private Double y; + + private UUID imageId; + + @JsonIgnore + @OneToMany(mappedBy = "discussionTopic", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + private List discussionComments; +} + diff --git a/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java b/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java new file mode 100644 index 0000000..21903e5 --- /dev/null +++ b/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java @@ -0,0 +1,11 @@ +package com.patternpedia.api.repositories; + +import com.patternpedia.api.entities.DiscussionComment; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import java.util.UUID; + +@RepositoryRestResource(exported = false) +public interface DiscussionCommentRepository extends CrudRepository { +} diff --git a/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java b/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java new file mode 100644 index 0000000..6f3b9f6 --- /dev/null +++ b/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java @@ -0,0 +1,12 @@ +package com.patternpedia.api.repositories; + +import com.patternpedia.api.entities.DiscussionTopic; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import java.util.UUID; + +@RepositoryRestResource(exported = false) +public interface DiscussionTopicRepository extends CrudRepository { +} + diff --git a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java new file mode 100644 index 0000000..c41c8b5 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java @@ -0,0 +1,55 @@ +package com.patternpedia.api.rest.controller; + +import com.patternpedia.api.entities.DiscussionComment; +import com.patternpedia.api.entities.DiscussionTopic; +import com.patternpedia.api.service.DiscussionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.UUID; + + +@RestController +@CrossOrigin(allowedHeaders = "*", origins = "*") +public class DiscussionController { + + private DiscussionService discussionService; + + @Autowired + public DiscussionController(DiscussionService discussionService) { + this.discussionService = discussionService; + } + + + @PostMapping( + value = "/add-topic" + ) + public @ResponseBody + DiscussionTopic addDiscussionTopic(@RequestBody DiscussionTopic topic){ + System.out.print(topic); + return this.discussionService.createTopic(topic); + } + + @DeleteMapping( + value = "/delete-topic/{id}" + ) + public @ResponseBody + ResponseEntity deleteDiscussionTopic(@PathVariable String id){ + UUID uuid = UUID.fromString(id); + this.discussionService.deleteTopicById(uuid); + return ResponseEntity.noContent().build(); + } + + @PostMapping( + value = "/add-comment/{topicId}" + ) + public @ResponseBody + DiscussionComment addDiscussionComment(@PathVariable String topicId, @RequestBody DiscussionComment comment){ + comment.setDiscussionTopic(this.discussionService.getTopicById(UUID.fromString(topicId))); + return this.discussionService.createComment(comment); + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index af02bd8..a40972f 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -1,6 +1,7 @@ package com.patternpedia.api.rest.controller; import com.patternpedia.api.entities.Image; +import com.patternpedia.api.entities.DiscussionTopic; import com.patternpedia.api.service.ImageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -36,8 +37,6 @@ byte[] getImageById(@PathVariable String imageId){ public @ResponseBody byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ UUID uuid = UUID.fromString(imageId); - System.out.println("image" + data); - System.out.println("id" + uuid); Image image = new Image(); image.setId(uuid); image.setData(data); @@ -45,6 +44,4 @@ byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ image.setFileType("image/svg+xml"); return this.imageService.updateImage(image).getData(); } - - } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/model/Status.java b/src/main/java/com/patternpedia/api/rest/model/Status.java new file mode 100644 index 0000000..a341a30 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/Status.java @@ -0,0 +1,6 @@ +package com.patternpedia.api.rest.model; + +public enum Status { + OPEN, + CLOSED; +} diff --git a/src/main/java/com/patternpedia/api/service/DiscussionService.java b/src/main/java/com/patternpedia/api/service/DiscussionService.java new file mode 100644 index 0000000..3b60909 --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/DiscussionService.java @@ -0,0 +1,29 @@ +package com.patternpedia.api.service; + +import com.patternpedia.api.entities.DiscussionComment; +import com.patternpedia.api.entities.DiscussionTopic; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +public interface DiscussionService { + + @Transactional + DiscussionTopic createTopic(DiscussionTopic topic); + + @Transactional(readOnly = true) + DiscussionTopic getTopicById(UUID topicId); + + @Transactional + void deleteTopicById(UUID id); + + @Transactional + DiscussionComment createComment(DiscussionComment topic); + + @Transactional(readOnly = true) + DiscussionComment getCommentById(UUID commentId); + + @Transactional + void deleteCommentById(UUID id); + +} diff --git a/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java b/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java new file mode 100644 index 0000000..8bf127a --- /dev/null +++ b/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java @@ -0,0 +1,63 @@ +package com.patternpedia.api.service; + +import com.patternpedia.api.repositories.DiscussionCommentRepository; +import com.patternpedia.api.repositories.DiscussionTopicRepository; +import com.patternpedia.api.entities.DiscussionComment; +import com.patternpedia.api.entities.DiscussionTopic; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.UUID; + + +@Service +@Validated +@Transactional +public class DiscussionServiceImpl implements DiscussionService{ + + private DiscussionTopicRepository discussionTopicRepository; + private DiscussionCommentRepository discussionCommentRepository; + + public DiscussionServiceImpl(DiscussionTopicRepository discussionTopicRepository, DiscussionCommentRepository discussionCommentRepository){ + this.discussionCommentRepository = discussionCommentRepository; + this.discussionTopicRepository = discussionTopicRepository; + } + + @Override + public DiscussionTopic createTopic(DiscussionTopic topic) { + return this.discussionTopicRepository.save(topic); + } + + @Override + public void deleteTopicById(UUID id) { + for (DiscussionComment discussionComment: this.getTopicById(id).getDiscussionComments()){ + this.discussionCommentRepository.deleteById(discussionComment.getId()); + } + this.discussionTopicRepository.deleteById(id); + } + + @Override + public DiscussionTopic getTopicById(UUID topicId) { + return this.discussionTopicRepository.findById(topicId).orElseThrow(() -> new ResourceNotFoundException("not found")); + } + + @Override + public DiscussionComment createComment(DiscussionComment topic) { + return this.discussionCommentRepository.save(topic); + } + + @Override + public DiscussionComment getCommentById(UUID commentId) { + return this.discussionCommentRepository.findById(commentId).orElseThrow(() -> new ResourceNotFoundException("not found")); + } + + @Override + public void deleteCommentById(UUID id) { + this.discussionCommentRepository.deleteById(id); + } + + +} From e2988df3fc9fee6b60d23e253c37f43edc4ce545 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 9 Jun 2020 20:58:34 +0200 Subject: [PATCH 12/23] Adding first version of discussion transfer from old to newly rendered picture --- .../api/entities/DiscussionTopic.java | 6 ++++ .../DiscussionCommentRepository.java | 3 ++ .../DiscussionTopicRepository.java | 2 ++ .../rest/controller/DiscussionController.java | 29 +++++++++++++++++ .../api/rest/controller/ImageController.java | 16 +++++++++- .../api/rest/model/DiscussionTopicModel.java | 22 +++++++++++++ .../api/rest/model/ImageModel.java | 20 ++++++++++++ .../api/service/DiscussionService.java | 13 ++++++++ .../api/service/DiscussionServiceImpl.java | 31 +++++++++++++++++++ .../api/service/PatternRenderServiceImpl.java | 24 ++++++++++++-- 10 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/patternpedia/api/rest/model/DiscussionTopicModel.java create mode 100644 src/main/java/com/patternpedia/api/rest/model/ImageModel.java diff --git a/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java index c35bd28..22cbc9e 100644 --- a/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java +++ b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java @@ -36,6 +36,12 @@ public class DiscussionTopic { private Double y; + private Double width; + + private Double height; + + private String fill; + private UUID imageId; @JsonIgnore diff --git a/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java b/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java index 21903e5..2b1671d 100644 --- a/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java +++ b/src/main/java/com/patternpedia/api/repositories/DiscussionCommentRepository.java @@ -1,11 +1,14 @@ package com.patternpedia.api.repositories; import com.patternpedia.api.entities.DiscussionComment; +import com.patternpedia.api.entities.DiscussionTopic; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import java.util.List; import java.util.UUID; @RepositoryRestResource(exported = false) public interface DiscussionCommentRepository extends CrudRepository { + List findDiscussionCommentByDiscussionTopic(DiscussionTopic discussionTopic); } diff --git a/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java b/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java index 6f3b9f6..89161a7 100644 --- a/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java +++ b/src/main/java/com/patternpedia/api/repositories/DiscussionTopicRepository.java @@ -4,9 +4,11 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import java.util.List; import java.util.UUID; @RepositoryRestResource(exported = false) public interface DiscussionTopicRepository extends CrudRepository { + List findDiscussionTopicsByImageId(UUID imageId); } diff --git a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java index c41c8b5..fc0da09 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java @@ -2,11 +2,13 @@ import com.patternpedia.api.entities.DiscussionComment; import com.patternpedia.api.entities.DiscussionTopic; +import com.patternpedia.api.rest.model.DiscussionTopicModel; import com.patternpedia.api.service.DiscussionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.UUID; @@ -50,6 +52,33 @@ DiscussionComment addDiscussionComment(@PathVariable String topicId, @RequestBod return this.discussionService.createComment(comment); } + @GetMapping( + value = "/get-comments-by-topic/{topicId}" + ) + public @ResponseBody + List getCommentsByTopic(@PathVariable String topicId){ + UUID uuid = UUID.fromString(topicId); + return this.discussionService.getCommentsByTopicId(uuid); + } + + + @GetMapping( + value = "/get-topic-by-image/{imageId}" + ) + public @ResponseBody + List getTopicsByImageId(@PathVariable String imageId){ + UUID uuid = UUID.fromString(imageId); + return this.discussionService.getTopicsByImageId(uuid); + } + + @GetMapping( + value = "/get-topics-and-comments-by-image/{imageId}" + ) + public @ResponseBody + List getTopicsAndCommentsByImageId(@PathVariable String imageId){ + UUID uuid = UUID.fromString(imageId); + return this.discussionService.getTopicsAndCommentsByImageId(uuid); + } } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index a40972f..2bcb4b6 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -2,6 +2,8 @@ import com.patternpedia.api.entities.Image; import com.patternpedia.api.entities.DiscussionTopic; +import com.patternpedia.api.rest.model.ImageModel; +import com.patternpedia.api.service.DiscussionService; import com.patternpedia.api.service.ImageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -14,12 +16,15 @@ public class ImageController { private ImageService imageService; + private DiscussionService discussionService; @Autowired - public ImageController(ImageService imageService) { + public ImageController(ImageService imageService, DiscussionService discussionService) { this.imageService = imageService; + this.discussionService = discussionService; } + @GetMapping( value = "/getImageById/{imageId}", produces = "image/svg+xml" @@ -44,4 +49,13 @@ byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ image.setFileType("image/svg+xml"); return this.imageService.updateImage(image).getData(); } + + @GetMapping( + value = "/getImageAndCommentsById/{imageId}" + ) + public @ResponseBody + ImageModel getImageAndCommentsById(@PathVariable String imageId){ + UUID uuid = UUID.fromString(imageId); + return new ImageModel(this.imageService.getImageById(uuid).getData(), this.discussionService.getTopicsAndCommentsByImageId(uuid)); + } } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/model/DiscussionTopicModel.java b/src/main/java/com/patternpedia/api/rest/model/DiscussionTopicModel.java new file mode 100644 index 0000000..69e4ac7 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/DiscussionTopicModel.java @@ -0,0 +1,22 @@ +package com.patternpedia.api.rest.model; + +import com.patternpedia.api.entities.DiscussionComment; +import com.patternpedia.api.entities.DiscussionTopic; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class DiscussionTopicModel { + private DiscussionTopic discussionTopic; + private List discussionComments; + + public DiscussionTopicModel (DiscussionTopic discussionTopic, List discussionComments){ + this.discussionTopic = discussionTopic; + this.discussionComments = discussionComments; + } +} diff --git a/src/main/java/com/patternpedia/api/rest/model/ImageModel.java b/src/main/java/com/patternpedia/api/rest/model/ImageModel.java new file mode 100644 index 0000000..614ec15 --- /dev/null +++ b/src/main/java/com/patternpedia/api/rest/model/ImageModel.java @@ -0,0 +1,20 @@ +package com.patternpedia.api.rest.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class ImageModel { + private byte[] image; + private List topicModels; + + public ImageModel(byte[] image, List topicModels){ + this.image = image; + this.topicModels = topicModels; + } +} diff --git a/src/main/java/com/patternpedia/api/service/DiscussionService.java b/src/main/java/com/patternpedia/api/service/DiscussionService.java index 3b60909..2928eb2 100644 --- a/src/main/java/com/patternpedia/api/service/DiscussionService.java +++ b/src/main/java/com/patternpedia/api/service/DiscussionService.java @@ -2,8 +2,10 @@ import com.patternpedia.api.entities.DiscussionComment; import com.patternpedia.api.entities.DiscussionTopic; +import com.patternpedia.api.rest.model.DiscussionTopicModel; import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.UUID; public interface DiscussionService { @@ -26,4 +28,15 @@ public interface DiscussionService { @Transactional void deleteCommentById(UUID id); + @Transactional + List getCommentsByTopicId(UUID topicId); + + @Transactional + List getTopicsByImageId(UUID imageId); + + @Transactional + List getTopicsAndCommentsByImageId(UUID imageId); + + @Transactional + List updateTopicsByImageId(UUID oldImageId, UUID newImageId); } diff --git a/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java b/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java index 8bf127a..c3f07a6 100644 --- a/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/DiscussionServiceImpl.java @@ -4,11 +4,13 @@ import com.patternpedia.api.repositories.DiscussionTopicRepository; import com.patternpedia.api.entities.DiscussionComment; import com.patternpedia.api.entities.DiscussionTopic; +import com.patternpedia.api.rest.model.DiscussionTopicModel; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -59,5 +61,34 @@ public void deleteCommentById(UUID id) { this.discussionCommentRepository.deleteById(id); } + @Override + public List getCommentsByTopicId(UUID topicId) { + return this.discussionCommentRepository.findDiscussionCommentByDiscussionTopic(this.getTopicById(topicId)); + } + + @Override + public List getTopicsByImageId(UUID imageId) { + return this.discussionTopicRepository.findDiscussionTopicsByImageId(imageId); + } + + @Override + public List getTopicsAndCommentsByImageId(UUID imageId) { + List topicModelList = new ArrayList<>(); + this.discussionTopicRepository.findDiscussionTopicsByImageId(imageId).forEach( topic -> { + DiscussionTopicModel topicModel = new DiscussionTopicModel(topic, this.discussionCommentRepository.findDiscussionCommentByDiscussionTopic(this.getTopicById(topic.getId()))); + topicModelList.add(topicModel); + }); + return topicModelList; + } + + @Override + public List updateTopicsByImageId(UUID oldImageId, UUID newImageId) { + this.discussionTopicRepository.findDiscussionTopicsByImageId(oldImageId).forEach(topic -> { + topic.setImageId(newImageId); + this.discussionTopicRepository.save(topic); + }); + return this.discussionTopicRepository.findDiscussionTopicsByImageId(newImageId); + } + } diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index c15180d..7ac6aca 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -1,9 +1,11 @@ package com.patternpedia.api.service; import com.fasterxml.jackson.databind.ObjectMapper; +import com.patternpedia.api.entities.DiscussionTopic; import com.patternpedia.api.entities.Image; import com.patternpedia.api.entities.Pattern; import com.patternpedia.api.rest.model.LatexContent; +import org.apache.commons.text.similarity.JaccardSimilarity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -21,6 +23,9 @@ public class PatternRenderServiceImpl implements PatternRenderService { @Autowired private ImageService imageService; + @Autowired + private DiscussionService discussionService; + @Override public Object renderContent(Pattern pattern, Pattern oldVersion) { String jsonString = null; @@ -44,6 +49,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { ArrayList oldSVGOccurances = new ArrayList<>(); while(true){ Integer[] occuranceStartEndOld = getNextOccurance(contentOld, "\\\\begin{quantikz}", "\\end{quantikz}"); + System.out.println("\\end{quantikz}".length()); Integer[] svgOccurencesOld = getNextOccurance(renderedContentOld, "", ""); if (occuranceStartEndOld[0] != -1 && occuranceStartEndOld[1] != -1 && svgOccurencesOld[0] != -1 && svgOccurencesOld[1] != -1) { oldContentOccurances.add(contentOld.substring(occuranceStartEndOld[0], occuranceStartEndOld[1] + 14) @@ -57,16 +63,19 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { break; } } - oldContentOccurances.forEach(s -> System.out.print("OLD CONTENT" + s)); + oldContentOccurances.forEach(s -> System.out.println("OLD CONTENT" + s)); oldSVGOccurances.forEach(s -> System.out.println("OLD SVG" +s)); - + int count = 0; + JaccardSimilarity jaccardSimilarity = new JaccardSimilarity(); while (true) { + Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") .replaceAll("\\\\\\\\","\\\\"); boolean occured = false; + for (int i = 0; i < oldContentOccurances.size(); i++){ if(oldContentOccurances.get(i).equals(renderContent)){ occured = true; @@ -74,14 +83,23 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { System.out.print("INSIDE OF EQUALS FOR " + i + " " + jsonString); } } + if(!occured){ List settings = new ArrayList<>(); settings.add("\\usepackage{tikz} \n"); settings.add("\\usetikzlibrary{quantikz} \n"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); - jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + saveAndUploadFile(renderedFile, "svg") + " "); + String id = saveAndUploadFile(renderedFile, "svg"); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + id + " "); + if(count < oldContentOccurances.size()){ + if(jaccardSimilarity.apply(oldContentOccurances.get(count), renderContent) > 0.9) { + System.out.println(id); + this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(count).substring(5, oldSVGOccurances.get(count).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); + } + } System.out.println("OUTSIDE OF EQUALS" + jsonString); } + count++ ; }else { break; } From 05a46ccde98fdcb8d434ba4c3a0f21ab48e441a8 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Mon, 15 Jun 2020 14:19:18 +0200 Subject: [PATCH 13/23] Adding logic about case specific rendering for qcircuit and adding comment transfer algorithm. Adjust api calls to kebab-case --- .../api/entities/DiscussionTopic.java | 10 --- .../api/rest/controller/ImageController.java | 6 +- .../api/service/PatternRenderServiceImpl.java | 83 +++++++++++++------ 3 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java index 22cbc9e..1896931 100644 --- a/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java +++ b/src/main/java/com/patternpedia/api/entities/DiscussionTopic.java @@ -23,25 +23,15 @@ public class DiscussionTopic { @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") private UUID id; - private String title; - private String description; - private Status status; - private Date date; - private Double x; - private Double y; - private Double width; - private Double height; - private String fill; - private UUID imageId; @JsonIgnore diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index 2bcb4b6..31dc859 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -26,7 +26,7 @@ public ImageController(ImageService imageService, DiscussionService discussionSe @GetMapping( - value = "/getImageById/{imageId}", + value = "/get-image-by-id/{imageId}", produces = "image/svg+xml" ) public @ResponseBody @@ -36,7 +36,7 @@ byte[] getImageById(@PathVariable String imageId){ } @PostMapping( - value = "/updateImage/{imageId}", + value = "/update-image/{imageId}", produces = "image/svg+xml" ) public @ResponseBody @@ -51,7 +51,7 @@ byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ } @GetMapping( - value = "/getImageAndCommentsById/{imageId}" + value = "/get-image-and-comments-by-id/{imageId}" ) public @ResponseBody ImageModel getImageAndCommentsById(@PathVariable String imageId){ diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 7ac6aca..c0c4800 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -44,19 +44,30 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { if (jsonString == null) return null; - //get all quantikz occurences + + //get old quantikz and qcircuit occurences ArrayList oldContentOccurances = new ArrayList<>(); ArrayList oldSVGOccurances = new ArrayList<>(); while(true){ - Integer[] occuranceStartEndOld = getNextOccurance(contentOld, "\\\\begin{quantikz}", "\\end{quantikz}"); - System.out.println("\\end{quantikz}".length()); + Integer[] occuranceStartEndOldQuantikz = getNextOccurance(contentOld, "\\\\begin{quantikz}", "\\end{quantikz}"); + Integer[] occuranceStartEndOldQcircuit = getNextOccurance(contentOld, "\\\\Qcircuit", "end}"); Integer[] svgOccurencesOld = getNextOccurance(renderedContentOld, "", ""); - if (occuranceStartEndOld[0] != -1 && occuranceStartEndOld[1] != -1 && svgOccurencesOld[0] != -1 && svgOccurencesOld[1] != -1) { - oldContentOccurances.add(contentOld.substring(occuranceStartEndOld[0], occuranceStartEndOld[1] + 14) - .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") - .replaceAll("\\\\\\\\","\\\\")); + if (((occuranceStartEndOldQcircuit[0] != -1 && occuranceStartEndOldQcircuit[1] != -1) || + (occuranceStartEndOldQuantikz[0] != -1 && occuranceStartEndOldQuantikz[1] != -1)) && svgOccurencesOld[0] != -1 && svgOccurencesOld[1] != -1) { + if(occuranceStartEndOldQuantikz[0] != -1 && ((occuranceStartEndOldQuantikz[0] < occuranceStartEndOldQcircuit[0]) || occuranceStartEndOldQcircuit[0] == -1 )){ + System.out.println("HAS OLD QUANTIKZ CONTENT"); + oldContentOccurances.add(contentOld.substring(occuranceStartEndOldQuantikz[0], occuranceStartEndOldQuantikz[1] + 14) + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") + .replaceAll("\\\\\\\\","\\\\")); + contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOldQuantikz[0], occuranceStartEndOldQuantikz[1] + 14), " "); + } else if(occuranceStartEndOldQcircuit[0] != -1 && ((occuranceStartEndOldQcircuit[0] < occuranceStartEndOldQuantikz[0]) || occuranceStartEndOldQuantikz[0] == -1 )){ + System.out.println("HAS OLD QCircuit CONTENT"); + oldContentOccurances.add(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 4) + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") + .replaceAll("\\\\\\\\","\\\\")); + contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 14), " ");} + oldSVGOccurances.add(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6)); - contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOld[0], occuranceStartEndOld[1] + 14), " "); renderedContentOld = renderedContentOld.replace(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6), " "); } else { @@ -65,10 +76,9 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { } oldContentOccurances.forEach(s -> System.out.println("OLD CONTENT" + s)); oldSVGOccurances.forEach(s -> System.out.println("OLD SVG" +s)); - int count = 0; + int countQuantikz = 0; JaccardSimilarity jaccardSimilarity = new JaccardSimilarity(); while (true) { - Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14) @@ -91,33 +101,58 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); String id = saveAndUploadFile(renderedFile, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + id + " "); - if(count < oldContentOccurances.size()){ - if(jaccardSimilarity.apply(oldContentOccurances.get(count), renderContent) > 0.9) { + if(countQuantikz < oldContentOccurances.size()){ + System.out.println("Jaccard: " + jaccardSimilarity.apply(oldContentOccurances.get(countQuantikz), renderContent)); + if(jaccardSimilarity.apply(oldContentOccurances.get(countQuantikz), renderContent) > 0.8) { System.out.println(id); - this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(count).substring(5, oldSVGOccurances.get(count).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); + this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(countQuantikz).substring(5, oldSVGOccurances.get(countQuantikz).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); } } System.out.println("OUTSIDE OF EQUALS" + jsonString); } - count++ ; + countQuantikz++ ; }else { break; } } + + int countQcircuit = 0; while (true) { Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\Qcircuit", "end}"); if (occuranceStartEnd[0] != -1 && occuranceStartEnd[1] != -1) { String renderContent = jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4) - .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ").replaceAll("\\\\\\\\","\\\\"); - renderContent.replace("end}", "}"); - List settings = new ArrayList<>(); - settings.add("\\usepackage[braket, qm]{qcircuit} \n"); - settings.add("\\usepackage{amsmath} \n"); - settings.add("\\usepackage{listings} \n"); - settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); - byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); - jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + saveAndUploadFile(renderedFile, "svg") + " "); + .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") + .replaceAll("\\\\\\\\","\\\\"); + boolean occured = false; + + for (int i = 0; i < oldContentOccurances.size(); i++){ + if(oldContentOccurances.get(i).equals(renderContent)){ + occured = true; + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + oldSVGOccurances.get(i) + " "); + System.out.print("INSIDE OF EQUALS FOR " + i + " " + jsonString); + } + } + + if(!occured){ + List settings = new ArrayList<>(); + settings.add("\\usepackage[braket, qm]{qcircuit} \n"); + settings.add("\\usepackage{amsmath} \n"); + settings.add("\\usepackage{listings} \n"); + settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); + byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); + String id = saveAndUploadFile(renderedFile, "svg"); + jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + id + " "); + if(countQcircuit < oldContentOccurances.size()){ + System.out.println("Jaccard: " + jaccardSimilarity.apply(oldContentOccurances.get(countQcircuit), renderContent)); + if(jaccardSimilarity.apply(oldContentOccurances.get(countQcircuit), renderContent) > 0.8) { + System.out.println(id); + this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(countQcircuit).substring(5, oldSVGOccurances.get(countQcircuit).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); + } + } + System.out.println("OUTSIDE OF EQUALS" + jsonString); + } + countQcircuit++ ; }else { break; } @@ -130,8 +165,6 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { } catch (Exception e) { e.printStackTrace(); } - if (map == null) - return null; return map; } From 0be10e65fb069bebc93dfcd7e53dee6f1dfa0b44 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 23 Jun 2020 11:22:53 +0200 Subject: [PATCH 14/23] fixing string.length error --- .../com/patternpedia/api/service/PatternRenderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index c0c4800..898c8c4 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -65,7 +65,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { oldContentOccurances.add(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 4) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") .replaceAll("\\\\\\\\","\\\\")); - contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 14), " ");} + contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 4), " ");} oldSVGOccurances.add(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6)); renderedContentOld = renderedContentOld.replace(renderedContentOld.substring(svgOccurencesOld[0], svgOccurencesOld[1] + 6), " "); From b8e9fc39b2d8d397f6f8aa0e74d5c2cb71d8baa7 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Fri, 3 Jul 2020 18:51:13 +0200 Subject: [PATCH 15/23] fixing string.length error --- .../com/patternpedia/api/service/PatternRenderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 898c8c4..2fac819 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -179,7 +179,7 @@ public byte[] renderContentViaAPI(String content, List packages, String byte[] file = null; try{ RestTemplate restTemplate = new RestTemplate(); - final String baseUrl = "http://localhost:"+8081+"/renderLatex/"; + final String baseUrl = "http://localhost:"+8082+"/renderLatex/"; URI uri = new URI(baseUrl); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); From 581b01f3cee6be913641ca8a5c26e4f48a2a1a64 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 9 Jul 2020 15:50:39 +0200 Subject: [PATCH 16/23] Fixing pattern-create exception --- .../api/service/PatternRenderServiceImpl.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 2fac819..374816c 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -34,8 +34,13 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { ObjectMapper mapper = new ObjectMapper(); try { jsonString = mapper.writeValueAsString(pattern.getContent()); - contentOld = mapper.writeValueAsString(oldVersion.getContent()); - renderedContentOld = mapper.writeValueAsString(oldVersion.getRenderedContent()); + if(oldVersion == null){ + contentOld = "null"; + renderedContentOld = "null"; + } else { + contentOld = mapper.writeValueAsString(oldVersion.getContent()); + renderedContentOld = mapper.writeValueAsString(oldVersion.getRenderedContent()); + } } catch (Exception e) { e.printStackTrace(); } From f78f080a2fc8bfa7b7fe76176cd800cab7ae06fa Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 9 Jul 2020 15:59:55 +0200 Subject: [PATCH 17/23] Removing printlns and changing api from String to UUID --- .../api/rest/controller/ImageController.java | 17 +++++++---------- .../api/service/PatternRenderServiceImpl.java | 14 +++----------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index 31dc859..2153c87 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -30,9 +30,8 @@ public ImageController(ImageService imageService, DiscussionService discussionSe produces = "image/svg+xml" ) public @ResponseBody - byte[] getImageById(@PathVariable String imageId){ - UUID uuid = UUID.fromString(imageId); - return this.imageService.getImageById(uuid).getData(); + byte[] getImageById(@PathVariable UUID imageId){ + return this.imageService.getImageById(imageId).getData(); } @PostMapping( @@ -40,12 +39,11 @@ byte[] getImageById(@PathVariable String imageId){ produces = "image/svg+xml" ) public @ResponseBody - byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ - UUID uuid = UUID.fromString(imageId); + byte[] updateImage(@PathVariable UUID imageId, @RequestBody byte[] data){ Image image = new Image(); - image.setId(uuid); + image.setId(imageId); image.setData(data); - image.setFileName(imageId); + image.setFileName(imageId.toString()); image.setFileType("image/svg+xml"); return this.imageService.updateImage(image).getData(); } @@ -54,8 +52,7 @@ byte[] updateImage(@PathVariable String imageId, @RequestBody byte[] data){ value = "/get-image-and-comments-by-id/{imageId}" ) public @ResponseBody - ImageModel getImageAndCommentsById(@PathVariable String imageId){ - UUID uuid = UUID.fromString(imageId); - return new ImageModel(this.imageService.getImageById(uuid).getData(), this.discussionService.getTopicsAndCommentsByImageId(uuid)); + ImageModel getImageAndCommentsById(@PathVariable UUID imageId){ + return new ImageModel(this.imageService.getImageById(imageId).getData(), this.discussionService.getTopicsAndCommentsByImageId(imageId)); } } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 374816c..2aec48d 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -60,13 +60,13 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { if (((occuranceStartEndOldQcircuit[0] != -1 && occuranceStartEndOldQcircuit[1] != -1) || (occuranceStartEndOldQuantikz[0] != -1 && occuranceStartEndOldQuantikz[1] != -1)) && svgOccurencesOld[0] != -1 && svgOccurencesOld[1] != -1) { if(occuranceStartEndOldQuantikz[0] != -1 && ((occuranceStartEndOldQuantikz[0] < occuranceStartEndOldQcircuit[0]) || occuranceStartEndOldQcircuit[0] == -1 )){ - System.out.println("HAS OLD QUANTIKZ CONTENT"); + //HAS OLD QUANTIKZ CONTENT oldContentOccurances.add(contentOld.substring(occuranceStartEndOldQuantikz[0], occuranceStartEndOldQuantikz[1] + 14) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") .replaceAll("\\\\\\\\","\\\\")); contentOld = contentOld.replace(contentOld.substring(occuranceStartEndOldQuantikz[0], occuranceStartEndOldQuantikz[1] + 14), " "); } else if(occuranceStartEndOldQcircuit[0] != -1 && ((occuranceStartEndOldQcircuit[0] < occuranceStartEndOldQuantikz[0]) || occuranceStartEndOldQuantikz[0] == -1 )){ - System.out.println("HAS OLD QCircuit CONTENT"); + //HAS OLD QCircuit CONTENT oldContentOccurances.add(contentOld.substring(occuranceStartEndOldQcircuit[0], occuranceStartEndOldQcircuit[1] + 4) .replaceAll("\\\\n", " ").replaceAll("(\\\\t)(?!a)"," ") .replaceAll("\\\\\\\\","\\\\")); @@ -79,8 +79,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { break; } } - oldContentOccurances.forEach(s -> System.out.println("OLD CONTENT" + s)); - oldSVGOccurances.forEach(s -> System.out.println("OLD SVG" +s)); + int countQuantikz = 0; JaccardSimilarity jaccardSimilarity = new JaccardSimilarity(); while (true) { @@ -107,13 +106,10 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { String id = saveAndUploadFile(renderedFile, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + id + " "); if(countQuantikz < oldContentOccurances.size()){ - System.out.println("Jaccard: " + jaccardSimilarity.apply(oldContentOccurances.get(countQuantikz), renderContent)); if(jaccardSimilarity.apply(oldContentOccurances.get(countQuantikz), renderContent) > 0.8) { - System.out.println(id); this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(countQuantikz).substring(5, oldSVGOccurances.get(countQuantikz).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); } } - System.out.println("OUTSIDE OF EQUALS" + jsonString); } countQuantikz++ ; }else { @@ -135,7 +131,6 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { if(oldContentOccurances.get(i).equals(renderContent)){ occured = true; jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + oldSVGOccurances.get(i) + " "); - System.out.print("INSIDE OF EQUALS FOR " + i + " " + jsonString); } } @@ -149,13 +144,10 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { String id = saveAndUploadFile(renderedFile, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + id + " "); if(countQcircuit < oldContentOccurances.size()){ - System.out.println("Jaccard: " + jaccardSimilarity.apply(oldContentOccurances.get(countQcircuit), renderContent)); if(jaccardSimilarity.apply(oldContentOccurances.get(countQcircuit), renderContent) > 0.8) { - System.out.println(id); this.discussionService.updateTopicsByImageId(UUID.fromString(oldSVGOccurances.get(countQcircuit).substring(5, oldSVGOccurances.get(countQcircuit).length() - 6)), UUID.fromString(id.substring(5, id.length() - 6))); } } - System.out.println("OUTSIDE OF EQUALS" + jsonString); } countQcircuit++ ; }else { From a21f9a251c2c1b80b8cc8851f58df8c5a46f2594 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Tue, 29 Sep 2020 03:05:03 +0200 Subject: [PATCH 18/23] Refactoring, Fixing small qcircuit bug, Adding Integrationtests for Discussion and Imagecontroller --- .../rest/controller/DiscussionController.java | 37 +++-- .../api/rest/controller/ImageController.java | 19 ++- .../api/service/PatternRenderServiceImpl.java | 28 +++- .../ImageAndDiscussionControllerTest.java | 140 ++++++++++++++++++ .../api/util/IntegrationTestHelper.java | 53 +++++-- 5 files changed, 245 insertions(+), 32 deletions(-) create mode 100644 src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java diff --git a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java index fc0da09..4a7abf1 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java @@ -5,6 +5,7 @@ import com.patternpedia.api.rest.model.DiscussionTopicModel; import com.patternpedia.api.service.DiscussionService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -23,13 +24,13 @@ public DiscussionController(DiscussionService discussionService) { this.discussionService = discussionService; } - + @ResponseStatus(HttpStatus.CREATED) @PostMapping( value = "/add-topic" ) public @ResponseBody DiscussionTopic addDiscussionTopic(@RequestBody DiscussionTopic topic){ - System.out.print(topic); + // deepcode ignore XSS: return this.discussionService.createTopic(topic); } @@ -37,18 +38,19 @@ DiscussionTopic addDiscussionTopic(@RequestBody DiscussionTopic topic){ value = "/delete-topic/{id}" ) public @ResponseBody - ResponseEntity deleteDiscussionTopic(@PathVariable String id){ - UUID uuid = UUID.fromString(id); - this.discussionService.deleteTopicById(uuid); + ResponseEntity deleteDiscussionTopic(@PathVariable UUID topicId){ + this.discussionService.deleteTopicById(topicId); return ResponseEntity.noContent().build(); } + @ResponseStatus(HttpStatus.CREATED) @PostMapping( value = "/add-comment/{topicId}" ) public @ResponseBody - DiscussionComment addDiscussionComment(@PathVariable String topicId, @RequestBody DiscussionComment comment){ - comment.setDiscussionTopic(this.discussionService.getTopicById(UUID.fromString(topicId))); + DiscussionComment addDiscussionComment(@PathVariable UUID topicId, @RequestBody DiscussionComment comment){ + comment.setDiscussionTopic(this.discussionService.getTopicById(topicId)); + // deepcode ignore XSS: return this.discussionService.createComment(comment); } @@ -56,29 +58,26 @@ DiscussionComment addDiscussionComment(@PathVariable String topicId, @RequestBod value = "/get-comments-by-topic/{topicId}" ) public @ResponseBody - List getCommentsByTopic(@PathVariable String topicId){ - UUID uuid = UUID.fromString(topicId); - return this.discussionService.getCommentsByTopicId(uuid); + List getCommentsByTopic(@PathVariable UUID topicId){ + // deepcode ignore XSS: + return this.discussionService.getCommentsByTopicId(topicId); } - @GetMapping( value = "/get-topic-by-image/{imageId}" ) public @ResponseBody - List getTopicsByImageId(@PathVariable String imageId){ - UUID uuid = UUID.fromString(imageId); - return this.discussionService.getTopicsByImageId(uuid); + List getTopicsByImageId(@PathVariable UUID imageId){ + // deepcode ignore XSS: + return this.discussionService.getTopicsByImageId(imageId); } @GetMapping( value = "/get-topics-and-comments-by-image/{imageId}" ) public @ResponseBody - List getTopicsAndCommentsByImageId(@PathVariable String imageId){ - UUID uuid = UUID.fromString(imageId); - return this.discussionService.getTopicsAndCommentsByImageId(uuid); + List getTopicsAndCommentsByImageId(@PathVariable UUID imageId){ + // deepcode ignore XSS: + return this.discussionService.getTopicsAndCommentsByImageId(imageId); } - - } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java index 2153c87..b78aae6 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/ImageController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/ImageController.java @@ -1,16 +1,18 @@ package com.patternpedia.api.rest.controller; import com.patternpedia.api.entities.Image; -import com.patternpedia.api.entities.DiscussionTopic; import com.patternpedia.api.rest.model.ImageModel; import com.patternpedia.api.service.DiscussionService; import com.patternpedia.api.service.ImageService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; + import java.util.UUID; + @RestController @CrossOrigin(allowedHeaders = "*", origins = "*") public class ImageController { @@ -31,6 +33,7 @@ public ImageController(ImageService imageService, DiscussionService discussionSe ) public @ResponseBody byte[] getImageById(@PathVariable UUID imageId){ + // deepcode ignore XSS: Returning by service created content via uuid return this.imageService.getImageById(imageId).getData(); } @@ -48,11 +51,25 @@ byte[] updateImage(@PathVariable UUID imageId, @RequestBody byte[] data){ return this.imageService.updateImage(image).getData(); } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping( + value = "/add-image", + produces = "application/json" + ) + public @ResponseBody + Image addImage(@RequestBody Image image){ + // deepcode ignore XSS: + return this.imageService.createImage(image); + + } + @GetMapping( value = "/get-image-and-comments-by-id/{imageId}" ) public @ResponseBody ImageModel getImageAndCommentsById(@PathVariable UUID imageId){ + // deepcode ignore XSS: Returning by service created content via uuid return new ImageModel(this.imageService.getImageById(imageId).getData(), this.discussionService.getTopicsAndCommentsByImageId(imageId)); } } \ No newline at end of file diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 2aec48d..362c680 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -26,6 +26,12 @@ public class PatternRenderServiceImpl implements PatternRenderService { @Autowired private DiscussionService discussionService; + /** + * + * @param pattern Pattern received from Frontend (not saved in DB yet) + * @param oldVersion Database version of the received Pattern + * @return content JSON that includes ids of the rendered LaTeX code instead of the LaTeX code + */ @Override public Object renderContent(Pattern pattern, Pattern oldVersion) { String jsonString = null; @@ -50,7 +56,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { return null; - //get old quantikz and qcircuit occurences + //get old quantikz and qcircuit occurences and match them with the related svg tags and imageids ArrayList oldContentOccurances = new ArrayList<>(); ArrayList oldSVGOccurances = new ArrayList<>(); while(true){ @@ -80,7 +86,9 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { } } + int countQuantikz = 0; + //JaccardSimilarity is ued to check if the Quantikz Occurance is similar to the previous one. If that is the case all comments of the old graphic get copied to the new one JaccardSimilarity jaccardSimilarity = new JaccardSimilarity(); while (true) { Integer[] occuranceStartEnd = getNextOccurance(jsonString, "\\\\begin{quantikz}", "\\end{quantikz}"); @@ -94,7 +102,6 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { if(oldContentOccurances.get(i).equals(renderContent)){ occured = true; jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 14), " " + oldSVGOccurances.get(i) + " "); - System.out.print("INSIDE OF EQUALS FOR " + i + " " + jsonString); } } @@ -140,6 +147,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { settings.add("\\usepackage{amsmath} \n"); settings.add("\\usepackage{listings} \n"); settings.add("\\renewcommand{\\arraystretch}{1.5} \n"); + renderContent = renderContent.replace(" end}"," }"); byte []renderedFile = renderContentViaAPI(renderContent, settings, "svg"); String id = saveAndUploadFile(renderedFile, "svg"); jsonString = jsonString.replace(jsonString.substring(occuranceStartEnd[0], occuranceStartEnd[1] + 4), " " + id + " "); @@ -166,11 +174,19 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { } + public Integer[] getNextOccurance(String content, String begin, String end) { return new Integer[]{content.indexOf(begin, 0), content.indexOf(end, 0)}; } + /** + * + * @param content LaTeX code + * @param packages LaTeX packages + * @param output Output Format for example "svg" + * @return Renderresult as byte array + */ public byte[] renderContentViaAPI(String content, List packages, String output){ LatexContent latexContent = new LatexContent(content,packages,output); byte[] file = null; @@ -190,11 +206,17 @@ public byte[] renderContentViaAPI(String content, List packages, String } + /** + * + * @param file File to upload as byte array + * @param output Filetype for example "svg" + * @return ImageId surrounded by Tags + */ public String saveAndUploadFile(byte[] file, String output) { Image image = new Image(); image.setData(file); image.setFileName("latexRender" + Instant.now().getEpochSecond()); - image.setFileType("svg"); + image.setFileType(output); Image uploadedImage = imageService.createImage(image); return "" + uploadedImage.getId().toString() + ""; } diff --git a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java new file mode 100644 index 0000000..6bf8b6c --- /dev/null +++ b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java @@ -0,0 +1,140 @@ +package com.patternpedia.api.integration; + +import com.patternpedia.api.entities.*; +import com.patternpedia.api.util.IntegrationTestHelper; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.URI; +import java.util.Base64; +import java.util.UUID; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class ImageAndDiscussionControllerTest extends IntegrationTest { + + @Autowired + private IntegrationTestHelper integrationTestHelper; + + @Before + public void cleanUpReposBefore() { + this.integrationTestHelper.cleanUpRepos(); + } + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + public void testImagesAndDiscussions() throws Exception { + //Test add-image + Image image = this.integrationTestHelper.getDefaultImage(); + final String baseUrlAddImage = "http://localhost:"+port+"/add-image/"; + URI uriAddImage = new URI(baseUrlAddImage); + HttpEntity requestAddImage = new HttpEntity<>(image); + ResponseEntity resultAddImage = this.restTemplate.postForEntity(uriAddImage, requestAddImage, String.class); + Assert.assertEquals(201, resultAddImage.getStatusCodeValue()); + JSONObject jsonObjectAddImage = new JSONObject(resultAddImage.getBody()); + String imageId = jsonObjectAddImage.get("id").toString(); + + //Test get-image-by-id + final String baseUrlGetImage = "http://localhost:"+port+"/get-image-by-id/"+imageId; + URI uriGetImage = new URI(baseUrlGetImage); + ResponseEntity resultGetImage = this.restTemplate.getForEntity(uriGetImage, String.class); + Assert.assertEquals(200, resultGetImage.getStatusCodeValue()); + Assert.assertEquals(resultGetImage.getBody(), new String(image.getData())); + + //Test update-image + Image updatedImage = image; + updatedImage.setId(UUID.fromString(imageId)); + updatedImage.setFileName("TestFilenameUpdate"); + final String baseUrlUpdateImage = "http://localhost:"+port+"/update-image/" +imageId; + URI uriUpdateImage = new URI(baseUrlUpdateImage); + HttpEntity requestUpdateImage = new HttpEntity<>(updatedImage); + ResponseEntity resultUpdateImage = this.restTemplate.postForEntity(uriUpdateImage, requestUpdateImage, String.class); + Assert.assertEquals(200, resultUpdateImage.getStatusCodeValue()); + JSONObject jsonObjectUpdateImage = new JSONObject(resultUpdateImage.getBody()); + Assert.assertEquals(jsonObjectUpdateImage.get("fileName"), image.getFileName()); + + //Test add-topic + DiscussionTopic discussionTopic = this.integrationTestHelper.getDefaultDiscussionTopic(); + discussionTopic.setImageId(UUID.fromString(imageId)); + final String baseUrlAddTopic = "http://localhost:"+port+"/add-topic/"; + URI uriAddTopic = new URI(baseUrlAddTopic); + HttpEntity requestAddTopic = new HttpEntity<>(discussionTopic); + ResponseEntity resultAddTopic = this.restTemplate.postForEntity(uriAddTopic, requestAddTopic, String.class); + Assert.assertEquals(201, resultAddTopic.getStatusCodeValue()); + JSONObject jsonObjectAddTopic = new JSONObject(resultAddTopic.getBody()); + String topicId = jsonObjectAddTopic.get("id").toString(); + + //Test add-comment + DiscussionComment discussionComment = this.integrationTestHelper.getDefaultDiscussionComment(); + discussionComment.setDiscussionTopic(discussionTopic); + final String baseUrlAddComment = "http://localhost:"+port+"/add-comment/"+topicId; + URI uriAddComment = new URI(baseUrlAddComment); + HttpEntity requestAddComment = new HttpEntity<>(discussionComment); + ResponseEntity resultAddComment = this.restTemplate.postForEntity(uriAddComment, requestAddComment, String.class); + Assert.assertEquals(201, resultAddComment.getStatusCodeValue()); + JSONObject jsonObjectAddComment = new JSONObject(resultAddComment.getBody()); + String commentId = jsonObjectAddComment.get("id").toString(); + + //Test get-comments-by-topic + final String baseUrlGetCommentsByTopic = "http://localhost:"+port+"/get-comments-by-topic/"+ topicId; + URI uriGetCommentsByTopic = new URI(baseUrlGetCommentsByTopic); + ResponseEntity resultGetCommentsByTopic = this.restTemplate.getForEntity(uriGetCommentsByTopic, String.class); + Assert.assertEquals(200, resultGetCommentsByTopic.getStatusCodeValue()); + JSONArray jsonObjectGetCommentByTopic= new JSONArray(resultGetCommentsByTopic.getBody()); + String getCommentText = jsonObjectGetCommentByTopic.getJSONObject(0).get("text").toString(); + Assert.assertEquals(getCommentText, discussionComment.getText()); + + //Test get-image-and-comments-by-id + final String baseUrlGetImageAndCommentsById= "http://localhost:"+port+"/get-image-and-comments-by-id/"+ imageId; + URI uriGetImageAndCommentsById = new URI(baseUrlGetImageAndCommentsById); + ResponseEntity resultGetImageAndCommentsById = this.restTemplate.getForEntity(uriGetImageAndCommentsById, String.class); + Assert.assertEquals(200, resultGetImageAndCommentsById.getStatusCodeValue()); + JSONObject jsonObjectGetImageAndCommentsById= new JSONObject(resultGetImageAndCommentsById.getBody()); + String getImage = new String(Base64.getDecoder().decode(jsonObjectGetImageAndCommentsById.get("image").toString())); + Assert.assertTrue(getImage.contains(image.getFileType())); + String topicDescription = jsonObjectGetImageAndCommentsById.getJSONArray("topicModels").getJSONObject(0).getJSONObject("discussionTopic").get("description").toString(); + Assert.assertEquals(topicDescription, discussionTopic.getDescription()); + String commentText = jsonObjectGetImageAndCommentsById.getJSONArray("topicModels").getJSONObject(0).getJSONArray("discussionComments").getJSONObject(0).get("text").toString(); + Assert.assertEquals(commentText, discussionComment.getText()); + + //Test get-topic-by-image + final String baseUrlGetTopicByImage = "http://localhost:"+port+"/get-topic-by-image/"+ imageId; + URI uriGetTopicByImage = new URI(baseUrlGetTopicByImage); + ResponseEntity resultGetTopicByImage = this.restTemplate.getForEntity(uriGetTopicByImage, String.class); + Assert.assertEquals(200, resultGetTopicByImage.getStatusCodeValue()); + JSONArray jsonObjectGetTopicByImage= new JSONArray(resultGetTopicByImage.getBody()); + String getDescription = jsonObjectGetTopicByImage.getJSONObject(0).get("description").toString(); + Assert.assertEquals(getDescription, discussionTopic.getDescription()); + + //Test get-topic-and-comments-by-image + final String baseUrlGetTopicsAndCommentsByImage = "http://localhost:"+port+"/get-topics-and-comments-by-image/"+ imageId; + URI uriGetTopicsAndCommentsByImage = new URI(baseUrlGetTopicsAndCommentsByImage); + ResponseEntity resultGetTopicsAndCommentsByImage = this.restTemplate.getForEntity(uriGetTopicsAndCommentsByImage, String.class); + Assert.assertEquals(200, resultGetTopicsAndCommentsByImage.getStatusCodeValue()); + JSONArray jsonObjectGetTopicsAndCommentsByImage= new JSONArray(resultGetTopicsAndCommentsByImage.getBody()); + String description = jsonObjectGetTopicsAndCommentsByImage.getJSONObject(0).getJSONObject("discussionTopic").get("description").toString(); + Assert.assertEquals(description, discussionTopic.getDescription()); + String commentText1 = jsonObjectGetTopicsAndCommentsByImage.getJSONObject(0).getJSONArray("discussionComments").getJSONObject(0).get("text").toString(); + Assert.assertEquals(commentText1, discussionComment.getText()); + } +} diff --git a/src/test/java/com/patternpedia/api/util/IntegrationTestHelper.java b/src/test/java/com/patternpedia/api/util/IntegrationTestHelper.java index 31f8ac9..96cf820 100644 --- a/src/test/java/com/patternpedia/api/util/IntegrationTestHelper.java +++ b/src/test/java/com/patternpedia/api/util/IntegrationTestHelper.java @@ -8,15 +8,7 @@ import java.util.UUID; import com.patternpedia.api.entities.*; -import com.patternpedia.api.repositories.DirectedEdgeRepository; -import com.patternpedia.api.repositories.PatternLanguageRepository; -import com.patternpedia.api.repositories.PatternRepository; -import com.patternpedia.api.repositories.PatternSchemaRepository; -import com.patternpedia.api.repositories.PatternSectionSchemaRepository; -import com.patternpedia.api.repositories.PatternViewDirectedEdgeRepository; -import com.patternpedia.api.repositories.PatternViewPatternRepository; -import com.patternpedia.api.repositories.PatternViewRepository; -import com.patternpedia.api.repositories.UndirectedEdgeReository; +import com.patternpedia.api.repositories.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -55,6 +47,13 @@ public class IntegrationTestHelper { private ObjectMapper objectMapper; @Autowired private MockMvc mockMvc; + @Autowired + private ImageRepository imageRepository; + @Autowired + private DiscussionCommentRepository discussionCommentRepository; + @Autowired + private DiscussionTopicRepository discussionTopicRepository; + public void cleanUpRepos() { System.out.println("Cleaning up..."); @@ -85,6 +84,15 @@ public void cleanUpRepos() { this.patternLanguageRepository.deleteAll(); System.out.println("Cleaned up patternLanguageRepository"); + + this.imageRepository.deleteAll(); + System.out.println("Cleaned up imageRepository"); + + this.discussionCommentRepository.deleteAll(); + System.out.println("Cleaned up discussionCommentRepository"); + + this.discussionTopicRepository.deleteAll(); + System.out.println("Cleaned up discussionTopicRepository"); } public ObjectNode getDefaultPatternContent() { @@ -217,4 +225,31 @@ public Pattern addPatternToLanguage(PatternLanguage patternLanguage) throws Exce return this.objectMapper.readValue(getPatternResponse.getResponse().getContentAsByteArray(), Pattern.class); } + + public Image getDefaultImage(){ + Image image = new Image(); + image.setId(UUID.randomUUID()); + image.setFileName("testImage"); + image.setFileType("testType"); + image.setData("testFile".getBytes()); + return image; + } + + public DiscussionTopic getDefaultDiscussionTopic(){ + DiscussionTopic discussionTopic = new DiscussionTopic(); + discussionTopic.setId(UUID.randomUUID()); + discussionTopic.setTitle("TestTopic"); + discussionTopic.setDescription("Testdescription"); + discussionTopic.setImageId(this.getDefaultImage().getId()); + return discussionTopic; + } + + public DiscussionComment getDefaultDiscussionComment(){ + DiscussionComment discussionComment = new DiscussionComment(); + discussionComment.setId(UUID.randomUUID()); + discussionComment.setText("TestText"); + discussionComment.setDiscussionTopic(this.getDefaultDiscussionTopic()); + return discussionComment; + } + } From 226824c0dbf79cc80e77ada8c3a05590d6d0529d Mon Sep 17 00:00:00 2001 From: manuwei <44226745+manuwei@users.noreply.github.com> Date: Thu, 1 Oct 2020 10:55:59 +0200 Subject: [PATCH 19/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7aa3add..2396391 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# pattern-pedia-views-backend +# pattern-atlas-backend From ea9e3460357e2a0d7af108f3ecf26bf9bb622b2c Mon Sep 17 00:00:00 2001 From: beiselmn Date: Thu, 1 Oct 2020 18:41:55 +0200 Subject: [PATCH 20/23] Fixing refactoring error in delete controller --- .../api/rest/controller/DiscussionController.java | 2 +- .../api/integration/ImageAndDiscussionControllerTest.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java index 4a7abf1..c321190 100644 --- a/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java +++ b/src/main/java/com/patternpedia/api/rest/controller/DiscussionController.java @@ -35,7 +35,7 @@ DiscussionTopic addDiscussionTopic(@RequestBody DiscussionTopic topic){ } @DeleteMapping( - value = "/delete-topic/{id}" + value = "/delete-topic/{topicId}" ) public @ResponseBody ResponseEntity deleteDiscussionTopic(@PathVariable UUID topicId){ diff --git a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java index 6bf8b6c..4205077 100644 --- a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java +++ b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java @@ -136,5 +136,12 @@ public void testImagesAndDiscussions() throws Exception { Assert.assertEquals(description, discussionTopic.getDescription()); String commentText1 = jsonObjectGetTopicsAndCommentsByImage.getJSONObject(0).getJSONArray("discussionComments").getJSONObject(0).get("text").toString(); Assert.assertEquals(commentText1, discussionComment.getText()); + + //Test delete-topic + final String baseUrlDeleteTopic = "http://localhost:"+port+"/delete-topic/"+ topicId; + URI uriDeleteTopic= new URI(baseUrlDeleteTopic); + this.restTemplate.delete(uriDeleteTopic); + ResponseEntity resultGetCommentsByTopicAfterDelete = this.restTemplate.getForEntity(uriGetCommentsByTopic, String.class); + Assert.assertEquals(404, resultGetCommentsByTopicAfterDelete.getStatusCodeValue()); } } From 31363417adaa6fcd19733800b938e47ba7e2a29c Mon Sep 17 00:00:00 2001 From: beiselmn Date: Mon, 12 Oct 2020 15:18:21 +0200 Subject: [PATCH 21/23] Fixing minor deepcode issues --- .../patternpedia/api/service/PatternRenderServiceImpl.java | 6 +++--- .../api/integration/ImageAndDiscussionControllerTest.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java index 362c680..ab51bb3 100644 --- a/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java +++ b/src/main/java/com/patternpedia/api/service/PatternRenderServiceImpl.java @@ -48,7 +48,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { renderedContentOld = mapper.writeValueAsString(oldVersion.getRenderedContent()); } } catch (Exception e) { - e.printStackTrace(); + return null; } @@ -168,7 +168,7 @@ public Object renderContent(Pattern pattern, Pattern oldVersion) { try { map = mapper.readValue(jsonString, Map.class); } catch (Exception e) { - e.printStackTrace(); + return null; } return map; @@ -200,7 +200,7 @@ public byte[] renderContentViaAPI(String content, List packages, String ResponseEntity result = restTemplate.postForEntity(uri, entity, byte[].class); file = result.getBody(); } catch (Exception e){ - e.printStackTrace(); + return null; } return file; } diff --git a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java index 4205077..f430070 100644 --- a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java +++ b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java @@ -71,7 +71,7 @@ public void testImagesAndDiscussions() throws Exception { ResponseEntity resultUpdateImage = this.restTemplate.postForEntity(uriUpdateImage, requestUpdateImage, String.class); Assert.assertEquals(200, resultUpdateImage.getStatusCodeValue()); JSONObject jsonObjectUpdateImage = new JSONObject(resultUpdateImage.getBody()); - Assert.assertEquals(jsonObjectUpdateImage.get("fileName"), image.getFileName()); + Assert.assertEquals(jsonObjectUpdateImage.get("fileName"), updatedImage.getFileName()); //Test add-topic DiscussionTopic discussionTopic = this.integrationTestHelper.getDefaultDiscussionTopic(); @@ -110,6 +110,7 @@ public void testImagesAndDiscussions() throws Exception { ResponseEntity resultGetImageAndCommentsById = this.restTemplate.getForEntity(uriGetImageAndCommentsById, String.class); Assert.assertEquals(200, resultGetImageAndCommentsById.getStatusCodeValue()); JSONObject jsonObjectGetImageAndCommentsById= new JSONObject(resultGetImageAndCommentsById.getBody()); + // deepcode ignore test: String.valueOf and toString() return Array as numbers not the included content as json String String getImage = new String(Base64.getDecoder().decode(jsonObjectGetImageAndCommentsById.get("image").toString())); Assert.assertTrue(getImage.contains(image.getFileType())); String topicDescription = jsonObjectGetImageAndCommentsById.getJSONArray("topicModels").getJSONObject(0).getJSONObject("discussionTopic").get("description").toString(); From 13fad45174b2915b257ed4af24d16e493e464cb5 Mon Sep 17 00:00:00 2001 From: beiselmn Date: Mon, 12 Oct 2020 16:59:30 +0200 Subject: [PATCH 22/23] Adjusting deepcode bytearray as String --- .../api/integration/ImageAndDiscussionControllerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java index f430070..7673219 100644 --- a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java +++ b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java @@ -59,6 +59,7 @@ public void testImagesAndDiscussions() throws Exception { URI uriGetImage = new URI(baseUrlGetImage); ResponseEntity resultGetImage = this.restTemplate.getForEntity(uriGetImage, String.class); Assert.assertEquals(200, resultGetImage.getStatusCodeValue()); +// deepcode ignore test: String.valueOf and toString() doesnt work for byte[] Assert.assertEquals(resultGetImage.getBody(), new String(image.getData())); //Test update-image @@ -110,7 +111,7 @@ public void testImagesAndDiscussions() throws Exception { ResponseEntity resultGetImageAndCommentsById = this.restTemplate.getForEntity(uriGetImageAndCommentsById, String.class); Assert.assertEquals(200, resultGetImageAndCommentsById.getStatusCodeValue()); JSONObject jsonObjectGetImageAndCommentsById= new JSONObject(resultGetImageAndCommentsById.getBody()); - // deepcode ignore test: String.valueOf and toString() return Array as numbers not the included content as json String + // deepcode ignore test: String.valueOf and toString() doesnt work for byte[] String getImage = new String(Base64.getDecoder().decode(jsonObjectGetImageAndCommentsById.get("image").toString())); Assert.assertTrue(getImage.contains(image.getFileType())); String topicDescription = jsonObjectGetImageAndCommentsById.getJSONArray("topicModels").getJSONObject(0).getJSONObject("discussionTopic").get("description").toString(); From 64ffe37ea5688b178c1eb4d23df5e1b00358a7ce Mon Sep 17 00:00:00 2001 From: beiselmn Date: Mon, 12 Oct 2020 17:13:45 +0200 Subject: [PATCH 23/23] Changing deepcode ignore ID --- .../api/integration/ImageAndDiscussionControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java index 7673219..0de1364 100644 --- a/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java +++ b/src/test/java/com/patternpedia/api/integration/ImageAndDiscussionControllerTest.java @@ -59,7 +59,7 @@ public void testImagesAndDiscussions() throws Exception { URI uriGetImage = new URI(baseUrlGetImage); ResponseEntity resultGetImage = this.restTemplate.getForEntity(uriGetImage, String.class); Assert.assertEquals(200, resultGetImage.getStatusCodeValue()); -// deepcode ignore test: String.valueOf and toString() doesnt work for byte[] + //deepcode ignore ReplaceBoxedConstructor~java.lang.String: String.valueOf and toString() doesnt work for byte[] Assert.assertEquals(resultGetImage.getBody(), new String(image.getData())); //Test update-image @@ -111,7 +111,7 @@ public void testImagesAndDiscussions() throws Exception { ResponseEntity resultGetImageAndCommentsById = this.restTemplate.getForEntity(uriGetImageAndCommentsById, String.class); Assert.assertEquals(200, resultGetImageAndCommentsById.getStatusCodeValue()); JSONObject jsonObjectGetImageAndCommentsById= new JSONObject(resultGetImageAndCommentsById.getBody()); - // deepcode ignore test: String.valueOf and toString() doesnt work for byte[] + // deepcode ignore ReplaceBoxedConstructor~java.lang.String: String.valueOf and toString() doesnt work for byte[] String getImage = new String(Base64.getDecoder().decode(jsonObjectGetImageAndCommentsById.get("image").toString())); Assert.assertTrue(getImage.contains(image.getFileType())); String topicDescription = jsonObjectGetImageAndCommentsById.getJSONArray("topicModels").getJSONObject(0).getJSONObject("discussionTopic").get("description").toString();