package com.kodcu.service.extension; import com.kodcu.config.ExtensionConfigBean; import com.kodcu.controller.ApplicationController; import com.kodcu.other.Current; import com.kodcu.other.IOHelper; import com.kodcu.service.DirectoryService; import com.kodcu.service.ThreadService; import com.kodcu.service.cache.BinaryCacheService; import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileSystem; import net.sourceforge.plantuml.SourceStringReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Path; import java.util.Objects; import static java.nio.file.StandardOpenOption.*; /** * Created by usta on 25.12.2014. */ @Component public class PlantUmlService { private final Logger logger = LoggerFactory.getLogger(PlantUmlService.class); private final Current current; private final ApplicationController controller; private final ThreadService threadService; private final BinaryCacheService binaryCacheService; private final ExtensionConfigBean extensionConfigBean; private final DirectoryService directoryService; @Autowired public PlantUmlService(final Current current, final ApplicationController controller, final ThreadService threadService, BinaryCacheService binaryCacheService, ExtensionConfigBean extensionConfigBean, DirectoryService directoryService) { this.current = current; this.controller = controller; this.threadService = threadService; this.binaryCacheService = binaryCacheService; this.extensionConfigBean = extensionConfigBean; this.directoryService = directoryService; } public void plantUml(String uml, String type, String imagesDir, String imageTarget, String nodename) { Objects.requireNonNull(imageTarget); boolean cachedResource = imageTarget.contains("/afx/cache"); if (!imageTarget.endsWith(".png") && !imageTarget.endsWith(".svg") && !cachedResource) return; StringBuffer stringBuffer = new StringBuffer(uml); appendHeaderNotExist(stringBuffer, nodename, "uml", "uml"); appendHeaderNotExist(stringBuffer, nodename, "ditaa", "ditaa"); appendHeaderNotExist(stringBuffer, nodename, "graphviz", "uml"); uml = stringBuffer.toString(); if (nodename.contains("uml")) { if (!uml.contains("skinparam") && !uml.contains("dpi")) { uml = uml.replaceFirst("@startuml", String.format("@startuml\nskinparam dpi %d\n", extensionConfigBean.getDefaultImageDpi())); } } if (uml.contains("@startdot")) { if (!uml.contains("dpi=")) { uml = uml.replaceFirst("\\{", String.format("{\ndpi=%d;\n", extensionConfigBean.getDefaultImageDpi())); } } if (nodename.contains("ditaa")) { if (!uml.contains("scale=")) { uml = uml.replaceFirst("@startditaa", String.format("@startditaa(scale=%d)", extensionConfigBean.getDefaultImageScale())); } } if (uml.contains("@startditaa")) { if (!uml.contains("scale=")) { uml = uml.replaceFirst("@startditaa", String.format("@startditaa(scale=%d)", extensionConfigBean.getDefaultImageScale())); } } Integer cacheHit = current.getCache().get(imageTarget); int hashCode = (imageTarget + imagesDir + type + uml + nodename).hashCode(); if (Objects.nonNull(cacheHit)) if (hashCode == cacheHit) return; logger.debug("UML extension is started for {}", imageTarget); SourceStringReader reader = new SourceStringReader(uml); try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { Path path = current.currentTab().getParentOrWorkdir(); Path umlPath = path.resolve(imageTarget); FileSystem.getInstance().setCurrentDir(path.toFile()); FileFormat fileType = imageTarget.endsWith(".svg") ? FileFormat.SVG : FileFormat.PNG; threadService.runTaskLater(() -> { try { reader.generateImage(os, new FileFormatOption(fileType)); if (!cachedResource) { IOHelper.createDirectories(path.resolve(imagesDir)); IOHelper.writeToFile(umlPath, os.toByteArray(), CREATE, WRITE, TRUNCATE_EXISTING, SYNC); } else { binaryCacheService.putBinary(imageTarget, os.toByteArray()); } logger.debug("UML extension is ended for {}", imageTarget); threadService.runActionLater(() -> { controller.clearImageCache(umlPath); }); } catch (Exception e) { logger.error("Problem occured while generating UML diagram", e); } }); current.getCache().put(imageTarget, hashCode); } catch (IOException e) { logger.error("Problem occured while generating UML diagram", e); } } private void appendHeaderNotExist(StringBuffer stringBuffer, String nodename, String ifNode, String header) { if (nodename.contains(ifNode)) { if (stringBuffer.indexOf("@start") == -1) { stringBuffer.insert(0, "@start" + header + "\n"); } if (stringBuffer.indexOf("@end") == -1) { stringBuffer.append("\n@end" + header); } } } }