From 6eb3742d1e4e4b9ff70457a5367eb9ddb367cfce Mon Sep 17 00:00:00 2001 From: Piotr Darosz Date: Fri, 8 Mar 2019 14:50:29 +0100 Subject: Convert modules and relations to SVG Generate SVG image from modules chain and save it to DB. Change-Id: I0f0b065f82de9b4d2084ec51043f485401842e23 Issue-ID: CLAMP-284 Signed-off-by: Piotr Darosz --- .../controller/installer/CsarInstallerImpl.java | 11 +- .../onap/clamp/clds/transform/XslTransformer.java | 3 +- .../java/org/onap/clamp/clds/util/XmlTools.java | 57 +++++++++ .../org/onap/clamp/clds/util/drawing/AwtUtils.java | 71 +++++++++++ .../onap/clamp/clds/util/drawing/ClampGraph.java | 43 +++++++ .../clamp/clds/util/drawing/ClampGraphBuilder.java | 64 ++++++++++ .../clamp/clds/util/drawing/DocumentBuilder.java | 55 +++++++++ .../onap/clamp/clds/util/drawing/ImageBuilder.java | 135 +++++++++++++++++++++ .../clds/util/drawing/InvalidStateException.java | 30 +++++ .../org/onap/clamp/clds/util/drawing/Painter.java | 91 ++++++++++++++ .../onap/clamp/clds/util/drawing/RectTypes.java | 28 +++++ .../onap/clamp/clds/util/drawing/SvgFacade.java | 48 ++++++++ .../org/onap/clamp/clds/util/XmlToolsTest.java | 72 +++++++++++ .../clds/util/drawing/ClampGraphBuilderTest.java | 90 ++++++++++++++ .../clamp/clds/util/drawing/ClampGraphTest.java | 77 ++++++++++++ .../clds/util/drawing/DocumentBuilderTest.java | 80 ++++++++++++ src/test/resources/clds/util/file.xml | 6 + 17 files changed, 955 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/onap/clamp/clds/util/XmlTools.java create mode 100755 src/main/java/org/onap/clamp/clds/util/drawing/AwtUtils.java create mode 100755 src/main/java/org/onap/clamp/clds/util/drawing/ClampGraph.java create mode 100755 src/main/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilder.java create mode 100644 src/main/java/org/onap/clamp/clds/util/drawing/DocumentBuilder.java create mode 100644 src/main/java/org/onap/clamp/clds/util/drawing/ImageBuilder.java create mode 100644 src/main/java/org/onap/clamp/clds/util/drawing/InvalidStateException.java create mode 100755 src/main/java/org/onap/clamp/clds/util/drawing/Painter.java create mode 100644 src/main/java/org/onap/clamp/clds/util/drawing/RectTypes.java create mode 100644 src/main/java/org/onap/clamp/clds/util/drawing/SvgFacade.java create mode 100644 src/test/java/org/onap/clamp/clds/util/XmlToolsTest.java create mode 100644 src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilderTest.java create mode 100644 src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphTest.java create mode 100644 src/test/java/org/onap/clamp/clds/util/drawing/DocumentBuilderTest.java create mode 100644 src/test/resources/clds/util/file.xml (limited to 'src') diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarInstallerImpl.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarInstallerImpl.java index 1303f2abd..17739963e 100644 --- a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarInstallerImpl.java +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarInstallerImpl.java @@ -26,19 +26,16 @@ package org.onap.clamp.clds.sdc.controller.installer; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; import com.google.gson.JsonObject; - import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; - import java.util.Optional; import java.util.Set; import javax.annotation.PostConstruct; import javax.xml.transform.TransformerException; - import org.apache.commons.io.IOUtils; import org.json.simple.parser.ParseException; import org.onap.clamp.clds.client.DcaeInventoryServices; @@ -55,6 +52,7 @@ import org.onap.clamp.clds.service.CldsService; import org.onap.clamp.clds.service.CldsTemplateService; import org.onap.clamp.clds.transform.XslTransformer; import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.drawing.SvgFacade; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; @@ -99,6 +97,9 @@ public class CsarInstallerImpl implements CsarInstaller { @Autowired private ChainGenerator chainGenerator; + @Autowired + private SvgFacade svgFacade; + @PostConstruct public void loadConfiguration() throws IOException { BlueprintParserMappingConfiguration @@ -255,7 +256,7 @@ public class CsarInstallerImpl implements CsarInstaller { if(microServicesChain.isEmpty()) { microServicesChain = blueprintParser.fallbackToOneMicroService(blueprintArtifact.getDcaeBlueprint()); } - //place where SVG text will be generated + String imageText = svgFacade.getSvgImage(microServicesChain); CldsTemplate template = new CldsTemplate(); template.setBpmnId("Sdc-Generated"); @@ -264,7 +265,7 @@ public class CsarInstallerImpl implements CsarInstaller { template.setPropText( "{\"global\":[{\"name\":\"service\",\"value\":[\"" + blueprintArtifact.getDcaeBlueprint() + "\"]}]}"); template - .setImageText(IOUtils.toString(appContext.getResource(configFiles.getSvgXmlFilePath()).getInputStream())); + .setImageText(imageText); template.setName(TEMPLATE_NAME_PREFIX + buildModelName(csar, blueprintArtifact)); template.save(cldsDao, null); logger.info("Fake Clds Template created for blueprint " + blueprintArtifact.getBlueprintArtifactName() diff --git a/src/main/java/org/onap/clamp/clds/transform/XslTransformer.java b/src/main/java/org/onap/clamp/clds/transform/XslTransformer.java index 5886e019f..a8f233e43 100644 --- a/src/main/java/org/onap/clamp/clds/transform/XslTransformer.java +++ b/src/main/java/org/onap/clamp/clds/transform/XslTransformer.java @@ -23,6 +23,7 @@ package org.onap.clamp.clds.transform; +import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import java.io.StringReader; import java.io.StringWriter; @@ -45,7 +46,7 @@ public class XslTransformer { private Templates templates; public void setXslResourceName(String xslResourceName) throws TransformerConfigurationException { - TransformerFactory tfactory = TransformerFactory.newInstance(); + TransformerFactory tfactory = new TransformerFactoryImpl(); tfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); tfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); templates = tfactory.newTemplates(new StreamSource(ResourceFileUtil.getResourceAsStream(xslResourceName))); diff --git a/src/main/java/org/onap/clamp/clds/util/XmlTools.java b/src/main/java/org/onap/clamp/clds/util/XmlTools.java new file mode 100644 index 000000000..391f0087d --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/XmlTools.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util; + +import java.io.StringWriter; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import org.apache.batik.anim.dom.SVGDOMImplementation; +import org.apache.batik.dom.GenericDOMImplementation; +import org.apache.batik.util.SVGConstants; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +public class XmlTools { + public static String exportXmlDocumentAsString(Document doc) { + try { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + return writer.getBuffer().toString(); + } catch (TransformerException e) { + throw new RuntimeException(e); + } + } + public static Document createEmptySvgDocument() { + DOMImplementation domImplementation = GenericDOMImplementation.getDOMImplementation(); + String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; + return domImplementation.createDocument(svgNS, SVGConstants.SVG_SVG_TAG, null); + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/AwtUtils.java b/src/main/java/org/onap/clamp/clds/util/drawing/AwtUtils.java new file mode 100755 index 000000000..f746ab142 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/AwtUtils.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; + +public class AwtUtils { + private static final int ARROW_W = 4; + private static final int ARROW_H = 2; + private static final int FONT_SIZE = 12; + private static final int FONT_STYLE = Font.PLAIN; + private static final String FONT_FACE = "SansSerif"; + private static final Color TRANSPARENT = new Color(0.0f, 0.0f,0.0f,0.0f); + + static void rectWithText(Graphics2D g2d, String text, Point p, int w, int h) { + Rectangle rect = new Rectangle(p.x, p.y, w, h); + g2d.draw(rect); + Color oldColor = g2d.getColor(); + g2d.setColor(TRANSPARENT); + g2d.fill(rect); + g2d.setColor(oldColor); + addText(g2d, text, p.x+w/2, p.y+h/2); + } + + static void drawArrow(Graphics2D g2d, Point from, Point to, int lineThickness) { + int x2 = to.x - lineThickness; + g2d.drawLine(from.x, from.y, x2-lineThickness, to.y); + g2d.drawPolygon(new int[] {x2-ARROW_W, x2-ARROW_W, x2},new int[] {to.y- ARROW_H, to.y+ ARROW_H, to.y},3); + g2d.fillPolygon(new int[] {x2-ARROW_W, x2-ARROW_W, x2},new int[] {to.y- ARROW_H, to.y+ ARROW_H, to.y},3); + } + + private static void addText(Graphics2D g2d, String text, int x, int y) { + Font f = new Font(FONT_FACE, FONT_STYLE, FONT_SIZE); + g2d.setFont(f); + + FontMetrics fm1 = g2d.getFontMetrics(); + int w1 = fm1.stringWidth(text); + int x1 = x - (w1 / 2); + + g2d.setFont(f); + g2d.setColor(Color.BLACK); + g2d.drawString(text, x1, y); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraph.java b/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraph.java new file mode 100755 index 000000000..f49e735eb --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraph.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.util.Objects; +import org.onap.clamp.clds.util.XmlTools; + +public class ClampGraph { + private final DocumentBuilder documentBuilder; + private String svg; + + ClampGraph(DocumentBuilder documentBuilder) { + this.documentBuilder = documentBuilder; + } + + public String getAsSVG() { + if(Objects.isNull(svg) || svg.isEmpty()) { + svg = XmlTools.exportXmlDocumentAsString(this.documentBuilder.getGroupingDocument()); + } + return svg; + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilder.java b/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilder.java new file mode 100755 index 000000000..243cb4aad --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilder.java @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ClampGraphBuilder { + private String policy; + private String collector; + private List microServices = new ArrayList<>(); + private final Painter painter; + + public ClampGraphBuilder(Painter painter) { + this.painter = painter; + } + + public ClampGraphBuilder collector(String c) { + collector = c; + return this; + } + + public ClampGraphBuilder policy(String p) { + policy = p; + return this; + } + + public ClampGraphBuilder microService(String ms) { + microServices.add(ms); + return this; + } + + public ClampGraph build() { + if(microServices.isEmpty()) { + throw new InvalidStateException("At least one microservice is required"); + } + if(Objects.isNull(policy) || policy.trim().isEmpty()) { + throw new InvalidStateException("Policy element must be present"); + } + return new ClampGraph(painter.doPaint(collector, microServices, policy)); + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/DocumentBuilder.java b/src/main/java/org/onap/clamp/clds/util/drawing/DocumentBuilder.java new file mode 100644 index 000000000..f34eaf2ee --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/DocumentBuilder.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import org.apache.batik.svggen.SVGGraphics2D; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class DocumentBuilder { + private final Document groupingDocument; + private final Document documentFactory; + + static final String DATA_ELEMENT_ID_ATTRIBUTE = "data-element-id"; + + DocumentBuilder(Document groupingDocument, Document documentFactory) { + this.groupingDocument = groupingDocument; + this.documentFactory = documentFactory; + } + + void pushChangestoDocument(SVGGraphics2D g2d, String dataElementId) { + Element element = + this.documentFactory.createElementNS(SVGGraphics2D.SVG_NAMESPACE_URI, + SVGGraphics2D.SVG_G_TAG); + element.setAttribute(DATA_ELEMENT_ID_ATTRIBUTE, dataElementId); + g2d.getRoot(element); + Node node = this.groupingDocument.importNode(element, true); + this.groupingDocument.getDocumentElement().appendChild(node); + } + + Document getGroupingDocument() { + return groupingDocument; + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/ImageBuilder.java b/src/main/java/org/onap/clamp/clds/util/drawing/ImageBuilder.java new file mode 100644 index 000000000..4d76581c3 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/ImageBuilder.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.awt.BasicStroke; +import java.awt.Point; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Ellipse2D; +import java.util.UUID; +import org.apache.batik.svggen.SVGGraphics2D; + +public class ImageBuilder { + + public static final int POLICY_LINE_RATIO = 2; + public static final int COLLECTOR_LINE_RATIO = 6; + public static final float MS_LINE_TO_HEIGHT_RATIO = 0.75f; + + private Point currentPoint; + private final int baseLength; + private final int rectHeight; + private final SVGGraphics2D g2d; + private final DocumentBuilder documentBuilder; + + private static final int LINE_THICKNESS = 2; + private static final int CIRCLE_RADIUS = 17; + + ImageBuilder(SVGGraphics2D svgGraphics2D, DocumentBuilder documentBuilder, + Point startingPoint, int baseLength, int rectHeight) { + this.g2d = svgGraphics2D; + this.documentBuilder = documentBuilder; + this.currentPoint = new Point(startingPoint); + this.baseLength = baseLength; + this.rectHeight = rectHeight; + } + + ImageBuilder rectangle(String dataElementId, RectTypes rectType, String text) { + Point next = new Point(currentPoint.x + baseLength, currentPoint.y); + Point p = coordinatesForRectangle(currentPoint, next); + + handleBasedOnRectType(rectType, text, p, baseLength, rectHeight); + + documentBuilder.pushChangestoDocument(g2d, dataElementId); + currentPoint = next; + return this; + } + + ImageBuilder arrow() { + String dataElementId = "Arrow-" + UUID.randomUUID().toString(); + Point to = new Point(currentPoint.x + baseLength, currentPoint.y); + AwtUtils.drawArrow(g2d, currentPoint, to, LINE_THICKNESS); + documentBuilder.pushChangestoDocument(g2d, dataElementId); + currentPoint = to; + return this; + } + + ImageBuilder circle(String dataElementId, int lineThickness) { + Point to = new Point(currentPoint.x + 2 * CIRCLE_RADIUS, currentPoint.y); + Shape circleStart = + new Ellipse2D.Double(currentPoint.x, currentPoint.y - CIRCLE_RADIUS, + 2 * CIRCLE_RADIUS, 2 * CIRCLE_RADIUS); + + Stroke oldStroke = g2d.getStroke(); + g2d.setStroke(new BasicStroke(lineThickness)); + g2d.draw(circleStart); + g2d.setStroke(oldStroke); + documentBuilder.pushChangestoDocument(g2d, dataElementId); + currentPoint = to; + return this; + } + + DocumentBuilder getDocumentBuilder() { + return documentBuilder; + } + + private void handleBasedOnRectType(RectTypes rectType, String text, Point p, int w, int h) { + AwtUtils.rectWithText(g2d, text, p, w, h); + switch (rectType) { + case COLECTOR: + drawVerticalLineForCollector(p, w, h); + break; + case MICROSERVICE: + drawHorizontalLineForMicroService(p, w, h); + break; + case POLICY: + drawDiagonalLineForPolicy(p, w, h); + break; + } + } + + private void drawVerticalLineForCollector(Point p, int w, int h) { + g2d.drawLine(p.x + w / COLLECTOR_LINE_RATIO, p.y, p.x + w / COLLECTOR_LINE_RATIO, p.y + h); + } + + private void drawHorizontalLineForMicroService(Point p, int w, int h) { + int y = calculateMsHorizontalLineYCoordinate(p,h); + g2d.drawLine(p.x, y, p.x + w, y); + } + + private void drawDiagonalLineForPolicy(Point p, int w, int h) { + g2d.drawLine(p.x, p.y + h / POLICY_LINE_RATIO, p.x + w / POLICY_LINE_RATIO, p.y); + } + + private int calculateMsHorizontalLineYCoordinate(Point p, int h) { + return (int)(p.y * h * MS_LINE_TO_HEIGHT_RATIO); + } + + private Point coordinatesForRectangle(Point from, Point next) { + int x = from.x; + int y = from.y - next.y + LINE_THICKNESS / 2; + return new Point(x,y); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/InvalidStateException.java b/src/main/java/org/onap/clamp/clds/util/drawing/InvalidStateException.java new file mode 100644 index 000000000..91af9f1a4 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/InvalidStateException.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +public class InvalidStateException extends RuntimeException { + public InvalidStateException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/Painter.java b/src/main/java/org/onap/clamp/clds/util/drawing/Painter.java new file mode 100755 index 000000000..e41ca8fb3 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/Painter.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Point; +import java.awt.RenderingHints; +import java.util.List; +import org.apache.batik.svggen.SVGGraphics2D; + +public class Painter { + private final int canvasSize; + private final SVGGraphics2D g2d; + private final DocumentBuilder documentBuilder; + + private static final int DEFALUT_CANVAS_SIZE = 900; + private static final int SLIM_LINE = 2; + private static final int THICK_LINE = 4; + private static final double RECT_RATIO = 3.0 / 2.0; + private static final int CIRCLE_RADIUS = 17; + + public Painter(SVGGraphics2D svgGraphics2D, DocumentBuilder documentBuilder) { + this.g2d = svgGraphics2D; + this.documentBuilder = documentBuilder; + this.canvasSize = DEFALUT_CANVAS_SIZE; + } + + DocumentBuilder doPaint(String collector, List microServices, String policy) { + int numOfRectangles = 2 + microServices.size(); + int numOfArrows = numOfRectangles + 1; + int baseLength = (canvasSize - 2 * CIRCLE_RADIUS) / (numOfArrows + numOfRectangles); + int rectHeight = (int) (baseLength / RECT_RATIO); + + adjustGraphics2DProperties(); + + Point origin = new Point(0, rectHeight / 2); + ImageBuilder ib = new ImageBuilder(g2d, documentBuilder, origin, baseLength, rectHeight); + + doTheActualDrawing(collector, microServices, policy, ib); + + return ib.getDocumentBuilder(); + } + + private void doTheActualDrawing(String collector, List microServices, String policy, ImageBuilder ib) { + ib.circle("start-circle", SLIM_LINE) + .arrow() + .rectangle(collector, RectTypes.COLECTOR, collector); + + for(String ms : microServices) { + ib.arrow().rectangle(ms, RectTypes.MICROSERVICE, ms); + } + + ib.arrow() + .rectangle(policy, RectTypes.POLICY, policy) + .arrow() + .circle("stop-circle", THICK_LINE); + } + + private void adjustGraphics2DProperties() { + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + g2d.setStroke(new BasicStroke(SLIM_LINE)); + g2d.setPaint(Color.BLACK); + } + + +} diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/RectTypes.java b/src/main/java/org/onap/clamp/clds/util/drawing/RectTypes.java new file mode 100644 index 000000000..e69324325 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/RectTypes.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +enum RectTypes { + COLECTOR, MICROSERVICE, POLICY +} \ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/util/drawing/SvgFacade.java b/src/main/java/org/onap/clamp/clds/util/drawing/SvgFacade.java new file mode 100644 index 000000000..0ba848639 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/drawing/SvgFacade.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import java.util.List; +import org.apache.batik.svggen.SVGGraphics2D; +import org.onap.clamp.clds.sdc.controller.installer.MicroService; +import org.onap.clamp.clds.util.XmlTools; +import org.springframework.stereotype.Component; +import org.w3c.dom.Document; + +@Component +public class SvgFacade { + public String getSvgImage(List microServicesChain) { + SVGGraphics2D svgGraphics2D = new SVGGraphics2D(XmlTools.createEmptySvgDocument()); + Document document = XmlTools.createEmptySvgDocument(); + DocumentBuilder dp = new DocumentBuilder(document, svgGraphics2D.getDOMFactory()); + Painter p = new Painter(svgGraphics2D, dp); + ClampGraphBuilder cgp = new ClampGraphBuilder(p).collector("VES"); + for(MicroService ms : microServicesChain) { + cgp = cgp.microService(ms.getName()); + } + ClampGraph cg = cgp.policy("Policy").build(); + return cg.getAsSVG(); + } + +} diff --git a/src/test/java/org/onap/clamp/clds/util/XmlToolsTest.java b/src/test/java/org/onap/clamp/clds/util/XmlToolsTest.java new file mode 100644 index 000000000..4351a80d4 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/XmlToolsTest.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util; + +import java.io.IOException; +import java.io.StringReader; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.apache.batik.anim.dom.SVGDOMImplementation; +import org.apache.batik.util.SVGConstants; +import org.junit.Assert; +import org.junit.Test; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class XmlToolsTest { + + @Test + public void exportXmlDocumentAsStringTest() throws IOException, ParserConfigurationException, SAXException { + String expected = ResourceFileUtil.getResourceAsString("clds/util/file.xml"); + Document document = parseStringToXmlDocument(expected); + String actual = XmlTools.exportXmlDocumentAsString(document); + Assert.assertEquals(expected.trim(), actual.trim()); + } + + @Test + public void createEmptySvgDocumentTest() { + Document doc = XmlTools.createEmptySvgDocument(); + Assert.assertEquals(SVGDOMImplementation.SVG_NAMESPACE_URI, doc.getDocumentElement().getNamespaceURI()); + Assert.assertEquals(SVGConstants.SVG_SVG_TAG, doc.getDocumentElement().getNodeName()); + Assert.assertNull(doc.getDoctype()); + } + + + public static Document parseStringToXmlDocument(String res) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(false); + dbf.setNamespaceAware(true); + dbf.setFeature("http://xml.org/sax/features/namespaces", false); + dbf.setFeature("http://xml.org/sax/features/validation", false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + DocumentBuilder db = dbf.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(res)); + return db.parse(is); + } + +} \ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilderTest.java b/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilderTest.java new file mode 100644 index 000000000..477e6a73f --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphBuilderTest.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.Arrays; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClampGraphBuilderTest { + @Mock + private Painter mockPainter; + + @Captor + private ArgumentCaptor collectorCaptor; + + @Captor + private ArgumentCaptor> microServicesCaptor; + + @Captor + private ArgumentCaptor policyCaptor; + + @Test + public void clampGraphBuilderCompleteChainTest() { + String collector = "VES"; + String ms1 = "ms1"; + String ms2 = "ms2"; + String policy = "Policy"; + List microServices = Arrays.asList(ms1, ms2); + + ClampGraphBuilder clampGraphBuilder = new ClampGraphBuilder(mockPainter); + clampGraphBuilder.collector(collector).microService(ms1).microService(ms2).policy(policy).build(); + + verify(mockPainter, times(1)) + .doPaint(collectorCaptor.capture(), microServicesCaptor.capture(), policyCaptor.capture()); + + Assert.assertEquals(collector, collectorCaptor.getValue()); + Assert.assertEquals(microServices, microServicesCaptor.getValue()); + Assert.assertEquals(policy, policyCaptor.getValue()); + } + + @Test(expected = InvalidStateException.class) + public void clampGraphBuilderNoPolicyGivenTest() { + String collector = "VES"; + String ms1 = "ms1"; + String ms2 = "ms2"; + + ClampGraphBuilder clampGraphBuilder = new ClampGraphBuilder(mockPainter); + clampGraphBuilder.collector(collector).microService(ms1).microService(ms2).build(); + } + + @Test(expected = InvalidStateException.class) + public void clampGraphBuilderNoMicroServiceGivenTest() { + String collector = "VES"; + String policy = "Policy"; + + ClampGraphBuilder clampGraphBuilder = new ClampGraphBuilder(mockPainter); + clampGraphBuilder.collector(collector).policy(policy).build(); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphTest.java b/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphTest.java new file mode 100644 index 000000000..6bbebdfde --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/drawing/ClampGraphTest.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import javax.xml.parsers.ParserConfigurationException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.clamp.clds.util.ResourceFileUtil; +import org.onap.clamp.clds.util.XmlToolsTest; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +@RunWith(MockitoJUnitRunner.class) +public class ClampGraphTest { + @Mock + private DocumentBuilder mockDocumentBuilder; + + @Test + public void getAsSVGTest() throws IOException, ParserConfigurationException, SAXException { + String expected = ResourceFileUtil.getResourceAsString("clds/util/file.xml"); + Document document = XmlToolsTest.parseStringToXmlDocument(expected); + + when(mockDocumentBuilder.getGroupingDocument()).thenReturn(document); + + String actual = new ClampGraph(mockDocumentBuilder).getAsSVG(); + Assert.assertEquals(expected.trim(), actual.trim()); + } + + @Test + public void getAsSVGLazyTest() throws IOException, ParserConfigurationException, SAXException { + String expected = ResourceFileUtil.getResourceAsString("clds/util/file.xml"); + Document document = XmlToolsTest.parseStringToXmlDocument(expected); + + when(mockDocumentBuilder.getGroupingDocument()).thenReturn(document); + ClampGraph cg = new ClampGraph(mockDocumentBuilder); + + String actualFirst = cg.getAsSVG(); + verify(mockDocumentBuilder, times(1)).getGroupingDocument(); + + String actualSecond = cg.getAsSVG(); + verifyNoMoreInteractions(mockDocumentBuilder); + + Assert.assertEquals(expected.trim(), actualFirst.trim()); + Assert.assertEquals(expected.trim(), actualSecond.trim()); + + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/util/drawing/DocumentBuilderTest.java b/src/test/java/org/onap/clamp/clds/util/drawing/DocumentBuilderTest.java new file mode 100644 index 000000000..6546553c7 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/drawing/DocumentBuilderTest.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.clds.util.drawing; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import javax.xml.parsers.ParserConfigurationException; +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.batik.util.SVGConstants; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.clamp.clds.util.ResourceFileUtil; +import org.onap.clamp.clds.util.XmlToolsTest; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +@RunWith(MockitoJUnitRunner.class) +public class DocumentBuilderTest { + @Mock + private SVGGraphics2D mockG2d; + + @Mock + private Document mockDomImpl; + + @Test + public void pushChangestoDocumentTest() throws IOException, ParserConfigurationException, SAXException { + String dataElementId = "someId"; + String newNodeTag = "tagged"; + String newNodeText = "Sample text"; + String xml = ResourceFileUtil.getResourceAsString("clds/util/file.xml"); + Document document = XmlToolsTest.parseStringToXmlDocument(xml); + Node newNode = document.createElement(newNodeTag); + newNode.appendChild(document.createTextNode(newNodeText)); + + when(mockG2d.getRoot(any(Element.class))).then(a -> a.getArgumentAt(0, Element.class).appendChild(newNode)); + + DocumentBuilder db = new DocumentBuilder(document, document); + db.pushChangestoDocument(mockG2d, dataElementId); + Document actualDocument = db.getGroupingDocument(); + + Node addedActualNode = actualDocument.getDocumentElement().getLastChild(); + String actualDataElementId = + addedActualNode.getAttributes().getNamedItem(DocumentBuilder.DATA_ELEMENT_ID_ATTRIBUTE).getTextContent(); + + Assert.assertEquals(dataElementId, actualDataElementId); + Assert.assertEquals(SVGConstants.SVG_G_TAG, addedActualNode.getNodeName()); + + Node addedActualNodeChild = addedActualNode.getLastChild(); + Assert.assertEquals(newNodeTag, addedActualNodeChild.getNodeName()); + Assert.assertEquals(newNodeText, addedActualNodeChild.getTextContent()); + } +} \ No newline at end of file diff --git a/src/test/resources/clds/util/file.xml b/src/test/resources/clds/util/file.xml new file mode 100644 index 000000000..81560bab4 --- /dev/null +++ b/src/test/resources/clds/util/file.xml @@ -0,0 +1,6 @@ + + Tove + Jani + Reminder + Message body + -- cgit 1.2.3-korg