From c0ec0fc448af1c5d6eacb195e95938c921ba1bce Mon Sep 17 00:00:00 2001
From: sebdet <sebastien.determe@intl.att.com>
Date: Mon, 18 May 2020 12:31:11 +0200
Subject: Create SVG in UI

Remove the SVG generation from the backend and put it in the UI

Issue-ID: CLAMP-854
Signed-off-by: sebdet <sebastien.determe@intl.att.com>
Change-Id: Icfa9e107d83bb244ac3d87300d013555bfa0b037
---
 .../loop_viewer/svg/LoopComponentConverter.js      |  17 --
 ui-react/src/components/loop_viewer/svg/LoopSvg.js | 110 ----------
 .../src/components/loop_viewer/svg/LoopSvg.test.js | 132 ------------
 .../src/components/loop_viewer/svg/SvgGenerator.js | 240 +++++++++++++++++++++
 .../svg/__snapshots__/LoopSvg.test.js.snap         |  34 ---
 .../src/components/loop_viewer/svg/example.svg     |   1 -
 6 files changed, 240 insertions(+), 294 deletions(-)
 delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
 delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopSvg.js
 delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
 create mode 100644 ui-react/src/components/loop_viewer/svg/SvgGenerator.js
 delete mode 100644 ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap
 delete mode 100644 ui-react/src/components/loop_viewer/svg/example.svg

(limited to 'ui-react/src/components/loop_viewer')

diff --git a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
deleted file mode 100644
index 29422a1f..00000000
--- a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default class LoopComponentConverter {
-
-	static buildMapOfComponents(loopCache) {
-		var componentsMap = new Map([]);
-		if (typeof (loopCache.getMicroServicePolicies()) !== "undefined") {
-			loopCache.getMicroServicePolicies().forEach(ms => {
-				componentsMap.set(ms.name, "/policyModal/MICRO-SERVICE-POLICY/"+ms.name);
-			})
-		}
-		if (typeof (loopCache.getOperationalPolicies()) !== "undefined") {
-			loopCache.getOperationalPolicies().forEach(op => {
-				componentsMap.set(op.name, "/policyModal/OPERATIONAL-POLICY/"+op.name);
-			})
-		}
-		return componentsMap;
-	}
-}
diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.js
deleted file mode 100644
index 048f6304..00000000
--- a/ui-react/src/components/loop_viewer/svg/LoopSvg.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. 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============================================
- * ===================================================================
- *
- */
-import React from 'react';
-import styled from 'styled-components';
-import LoopCache from '../../../api/LoopCache';
-import { withRouter } from "react-router-dom";
-import LoopService from '../../../api/LoopService';
-import LoopComponentConverter from './LoopComponentConverter';
-
-const LoopViewSvgDivStyled = styled.svg`
-	display: flex;
-	flex-direction: row;
-	overflow-x: scroll;
-	background-color: ${props => (props.theme.loopViewerBackgroundColor)};
-	border: 1px solid;
-	border-color: ${props => (props.theme.loopViewerHeaderColor)};
-	margin-top: 1em;
-	margin-left: auto;
-	margin-right:auto;
-	margin-bottom: -3em;
-	align-items: center;
-	height: 100%;
-	width: 100%;
-
-`
-
-class LoopViewSvg extends React.Component {
-
-	static emptySvg = "<svg><text x=\"20\" y=\"40\">No LOOP (SVG)</text></svg>";
-
-	state = {
-		svgContent: LoopViewSvg.emptySvg,
-		loopCache: new LoopCache({}),
-		componentModalMapping: new Map([])
-	}
-
-	constructor(props) {
-		super(props);
-		this.handleSvgClick = this.handleSvgClick.bind(this);
-		this.getSvg = this.getSvg.bind(this);
-		this.state.loopCache = props.loopCache;
-		this.state.componentModalMapping = LoopComponentConverter.buildMapOfComponents(props.loopCache);
-		this.getSvg(props.loopCache.getLoopName());
-	}
-
-	shouldComponentUpdate(nextProps, nextState) {
-		return this.state.svgContent !== nextState.svgContent;
-	}
-
-	componentWillReceiveProps(newProps) {
-		if (this.state.loopCache !== newProps.loopCache) {
-			this.setState({
-				loopCache: newProps.loopCache,
-				componentModalMapping: LoopComponentConverter.buildMapOfComponents(newProps.loopCache)
-			});
-			this.getSvg(newProps.loopCache.getLoopName());
-		}
-	}
-
-	getSvg(loopName) {
-		if (typeof loopName !== "undefined") {
-			LoopService.getSvg(loopName).then(svgXml => {
-				if (svgXml.length !== 0) {
-					this.setState({ svgContent: svgXml })
-				} else {
-					this.setState({ svgContent: LoopViewSvg.emptySvg })
-				}
-			});
-		} else {
-			this.setState({ svgContent: LoopViewSvg.emptySvg })
-		}
-	}
-
-	handleSvgClick(event) {
-		console.debug("svg click event received");
-		var elementName = event.target.parentNode.parentNode.parentNode.getAttribute('data-element-id');
-		console.info("SVG element clicked", elementName);
-		this.props.history.push(this.state.componentModalMapping.get(elementName));
-	}
-
-	render() {
-		return (
-			<LoopViewSvgDivStyled dangerouslySetInnerHTML={{ __html: this.state.svgContent }} onClick={this.handleSvgClick}>
-
-			</LoopViewSvgDivStyled>
-		);
-	}
-}
-
-export default withRouter(LoopViewSvg);
diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
deleted file mode 100644
index e54b500f..00000000
--- a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. 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============================================
- * ===================================================================
- *
- */
-import React from 'react';
-import { shallow } from 'enzyme';
-import LoopSvg from './LoopSvg';
-import LoopCache from '../../../api/LoopCache';
-import LoopService from '../../../api/LoopService';
-
-describe('Verify LoopSvg', () => {
-    const loopCache = new LoopCache({
-        "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
-        "microServicePolicies": [{
-            "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca",
-            "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app",
-            "properties": {"domain": "measurementsForVfScaling"},
-            "shared": false,
-            "jsonRepresentation": {"schema": {}}
-        }],
-        "operationalPolicies": [{
-            "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca",
-            "configurationsJson": {
-                "operational_policy": {
-                    "controlLoop": {},
-                    "policies": []
-                }
-            }
-        }]
-    });
-
-    it('Test the render method no loopName', () => {
-        const localLoopCache = new LoopCache({
-        "microServicePolicies": [{
-            "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca",
-            "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app",
-            "properties": {"domain": "measurementsForVfScaling"},
-            "shared": false,
-            "jsonRepresentation": {"schema": {}}
-          }]
-        });
-        const component = shallow(
-            <LoopSvg.WrappedComponent loopCache={localLoopCache}/>
-        );
-
-        expect(component).toMatchSnapshot();
-    });
-
-    it('Test the render method', () => {
-        const component = shallow(
-            <LoopSvg.WrappedComponent  loopCache={loopCache}/>
-        );
-
-        expect(component).toMatchSnapshot();
-    });
-
-    it('Test the render method svg not empty', async () => {
-        const flushPromises = () => new Promise(setImmediate);
-        LoopService.getSvg = jest.fn().mockImplementation(() => {
-            return Promise.resolve("<svg><text test</text></svg>");
-        });
-        const component = shallow(
-            <LoopSvg.WrappedComponent  loopCache={loopCache}/>
-        );
-        await flushPromises();
-        expect(component).toMatchSnapshot();
-    });
-
-    it('Test handleSvgClick', () => {
-        const historyMock = { push: jest.fn() };
-
-        const component = shallow(
-            <LoopSvg.WrappedComponent loopCache={loopCache} history={historyMock}/>
-        );
-        let dummyElement = document.createElement('div');
-        dummyElement.setAttribute("data-element-id","TCA_h2NMX_v1_0_ResourceInstanceName1_tca");
-
-        const event = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}};
-
-        component.simulate('click', event);
-        component.update();
-
-        expect(historyMock.push.mock.calls[0]).toEqual([ '/policyModal/MICRO-SERVICE-POLICY/TCA_h2NMX_v1_0_ResourceInstanceName1_tca']);
-
-        //click operational policy
-        dummyElement.setAttribute("data-element-id","OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca");
-        const event2 = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}};
-
-        component.simulate('click', event2);
-        component.update();
-
-        expect(historyMock.push.mock.calls[1]).toEqual([ '/policyModal/OPERATIONAL-POLICY/OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca']);
-    });
-
-    it('Test componentWillReceiveProps method', () => {
-        const localLoopCache = new LoopCache({
-        "microServicePolicies": [{
-            "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca",
-            "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app",
-            "properties": {"domain": "measurementsForVfScaling"},
-            "shared": false,
-            "jsonRepresentation": {"schema": {}}
-          }]
-        });
-        const component = shallow(
-            <LoopSvg.WrappedComponent loopCache={localLoopCache}/>
-        );
-
-        expect(component.state('componentModalMapping').size).toEqual(1);
-
-        component.setProps({loopCache: loopCache});
-        expect(component.state('componentModalMapping').size).toEqual(2);
-    });
-});
diff --git a/ui-react/src/components/loop_viewer/svg/SvgGenerator.js b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
new file mode 100644
index 00000000..d718c2e4
--- /dev/null
+++ b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js
@@ -0,0 +1,240 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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============================================
+ * ===================================================================
+ *
+ */
+
+import React from 'react'
+import styled from 'styled-components';
+import { withRouter } from "react-router-dom";
+import LoopCache from '../../../api/LoopCache';
+import OnapConstant from '../../../utils/OnapConstants';
+
+const DivStyled = styled.div`
+	overflow-x: scroll;
+    width: 100%;
+    height: 100%;
+`
+
+const emptySvg = (<svg> <text x="20" y="40">No LOOP (SVG)</text> </svg>);
+
+class SvgGenerator extends React.Component {
+    boxWidth = 200;
+    boxHeight = 100;
+    boxSpace = 50;
+
+    static GENERATED_FROM_INSTANCE = "INSTANCE";
+    static GENERATED_FROM_TEMPLATE = "TEMPLATE";
+
+	state = {
+		loopCache: new LoopCache({}),
+		clickable: false,
+		generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE
+	}
+
+	constructor(props) {
+		super(props);
+		this.state.loopCache = props.loopCache;
+		this.state.clickable = props.clickable;
+		this.state.generatedFrom = props.generatedFrom;
+		this.handleSvgClick = this.handleSvgClick.bind(this);
+		this.renderSvg = this.renderSvg.bind(this);
+	}
+
+	shouldComponentUpdate(nextProps, nextState) {
+		return this.state.loopCache !== nextState.loopCache;
+	}
+
+	componentWillReceiveProps(newProps) {
+		if (this.state.loopCache !== newProps.loopCache) {
+			this.setState({
+				loopCache: newProps.loopCache,
+			});
+		}
+	}
+
+	handleSvgClick(event) {
+	    if (this.state.clickable) {
+            console.debug("svg click event received");
+            var elementName = event.target.parentNode.getAttribute('policyId');
+            console.info("SVG element clicked", elementName);
+            if (elementName !== null) {
+                this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName);
+            }
+		}
+	}
+
+    createVesBox (xPos) {
+        return this.createOneBox(xPos,null,null,'VES Collector','VES',null);
+    }
+
+    createOneArrow(xPos) {
+        return (
+         <svg width={this.boxSpace} height={this.boxHeight} x={xPos}>
+           <defs>
+            		<marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow">
+            			<path d="m 1 5 l 0 -3 l 7 3 l -7 3 z"
+            				stroke-width= "1" stroke-linecap= "butt" stroke-dasharray= "10000, 1"
+            				fill="#000000" stroke="#000000" />
+            		</marker>
+           </defs>
+           <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/>
+         </svg>
+        );
+    }
+
+    createBeginCircle(xPos, text) {
+            return (
+            <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
+                <circle cx={this.boxWidth-30} cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/>
+                <text x={this.boxWidth-30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
+            </svg>
+            );
+    }
+
+    createEndCircle(xPos, text) {
+            return (
+            <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
+                <circle cx={30} cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/>
+                <text x={30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
+            </svg>
+            );
+    }
+
+    createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) {
+        return (
+        <svg width={this.boxWidth} height={this.boxHeight} x={xPos} title="test">
+            <g policyId={policyId} loopElementModelId={loopElementModelId} policyType={policyType}>
+                <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/>
+                <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{title}</text>
+                <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs" >{name}</text>
+                <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs" >{policyId}</text>
+            </g>
+        </svg>
+        );
+    }
+
+    createSvgFromTemplate() {
+        const allElements = [];
+        var xPos = 0;
+
+        allElements.push(this.createBeginCircle(xPos,"Start"))
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        allElements.push(this.createOneArrow(xPos-this.boxSpace));
+
+        allElements.push(this.createVesBox(xPos));
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        allElements.push(this.createOneArrow(xPos-this.boxSpace));
+        //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType)
+        for (var loopElement of this.state.loopCache.getAllLoopElementModels()) {
+
+            allElements.push(this.createOneBox(xPos,
+                loopElement['name'],
+                loopElement['name'],
+                loopElement['shortName'],
+                loopElement['loopElementType'],
+                loopElement['loopElementType']))
+            xPos+=(this.boxWidth+this.boxSpace);
+            allElements.push(this.createOneArrow(xPos-this.boxSpace));
+        }
+
+        allElements.push(this.createEndCircle(xPos, "End"))
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        return allElements;
+    }
+
+    createSvgFromInstance() {
+        const allElements = [];
+        var xPos = 0;
+
+        allElements.push(this.createBeginCircle(xPos,"Start"))
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        allElements.push(this.createOneArrow(xPos-this.boxSpace));
+
+        allElements.push(this.createVesBox(xPos));
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        allElements.push(this.createOneArrow(xPos-this.boxSpace));
+
+        for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) {
+            var loopElementModelName =  this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel'];
+            if (loopElementModelName !== undefined) {
+                loopElementModelName = loopElementModelName['name'];
+            }
+            allElements.push(this.createOneBox(xPos,
+                this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'],
+                loopElementModelName,
+                this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'],
+                'microservice',
+                OnapConstant.microServiceType))
+            xPos+=(this.boxWidth+this.boxSpace);
+            allElements.push(this.createOneArrow(xPos-this.boxSpace));
+        }
+
+        for (var opPolicy in this.state.loopCache.getOperationalPolicies()) {
+            loopElementModelName =  this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel'];
+            if (loopElementModelName !== undefined) {
+                loopElementModelName = loopElementModelName['name'];
+            }
+            allElements.push(this.createOneBox(xPos,
+                this.state.loopCache.getOperationalPolicies()[opPolicy]['name'],
+                loopElementModelName,
+                this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'],
+                'operational',
+                OnapConstant.operationalPolicyType))
+            xPos+=(this.boxWidth+this.boxSpace);
+            allElements.push(this.createOneArrow(xPos-this.boxSpace));
+        }
+
+        allElements.push(this.createEndCircle(xPos, "End"))
+        xPos+=(this.boxWidth+this.boxSpace);
+
+        return allElements;
+    }
+
+    renderSvg() {
+        if (this.state.loopCache.getLoopName() === undefined) {
+            return [emptySvg];
+        }
+        if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) {
+            return this.createSvgFromInstance();
+        } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) {
+            return this.createSvgFromTemplate();
+        }
+    }
+
+    render() {
+        var allTheElements = this.renderSvg();
+        var svgWidth = this.boxWidth*allTheElements.length;
+        var svgHeight = this.boxHeight+100;
+        return (
+            <DivStyled onClick={this.handleSvgClick} >
+                <svg height={svgHeight} width={svgWidth}  preserveAspectRatio="none">
+                    {allTheElements}
+                </svg>
+            </DivStyled>
+        );
+    }
+}
+
+export default withRouter(SvgGenerator);
diff --git a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap b/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap
deleted file mode 100644
index e05f1c79..00000000
--- a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap
+++ /dev/null
@@ -1,34 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Verify LoopSvg Test the render method 1`] = `
-<styled.svg
-  dangerouslySetInnerHTML={
-    Object {
-      "__html": "<svg><text x=\\"20\\" y=\\"40\\">No LOOP (SVG)</text></svg>",
-    }
-  }
-  onClick={[Function]}
-/>
-`;
-
-exports[`Verify LoopSvg Test the render method no loopName 1`] = `
-<styled.svg
-  dangerouslySetInnerHTML={
-    Object {
-      "__html": "<svg><text x=\\"20\\" y=\\"40\\">No LOOP (SVG)</text></svg>",
-    }
-  }
-  onClick={[Function]}
-/>
-`;
-
-exports[`Verify LoopSvg Test the render method svg not empty 1`] = `
-<styled.svg
-  dangerouslySetInnerHTML={
-    Object {
-      "__html": "<svg><text test</text></svg>",
-    }
-  }
-  onClick={[Function]}
-/>
-`;
diff --git a/ui-react/src/components/loop_viewer/svg/example.svg b/ui-react/src/components/loop_viewer/svg/example.svg
deleted file mode 100644
index a7c40ee2..00000000
--- a/ui-react/src/components/loop_viewer/svg/example.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg"><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="start-circle" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><circle fill="none" r="17" cx="18" cy="41"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="Arrow-82c14603-02fc-4df7-8977-9b10e4c775d1" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><line y2="41" fill="none" x1="35" x2="123" y1="41"/><polygon fill="none" points=" 121 39 121 43 125 41"/><polygon points=" 121 39 121 43 125 41" stroke="none"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="VES" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><rect fill="none" x="127" width="123" y="1" height="82"/></g><g fill-opacity="0" fill="rgb(0,0,0)" text-rendering="optimizeQuality" shape-rendering="geometricPrecision" stroke="rgb(0,0,0)" stroke-opacity="0" stroke-width="2"><rect x="127" width="123" y="1" height="82" stroke="none"/></g><g text-rendering="optimizeQuality" stroke-width="2" shape-rendering="geometricPrecision" font-family="sans-serif"><text x="176.5" xml:space="preserve" y="46.5" stroke="none">VES</text><line y2="83" fill="none" x1="147" x2="147" y1="1"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="Arrow-dbbb2d5a-e9c4-446d-92b9-c71908854434" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><line y2="41" fill="none" x1="250" x2="338" y1="41"/><polygon fill="none" points=" 336 39 336 43 340 41"/><polygon points=" 336 39 336 43 340 41" stroke="none"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="TCA_Jbv1z_v1_0_ResourceInstanceName1_tca" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><rect fill="none" x="342" width="123" y="1" height="82"/></g><g fill-opacity="0" fill="rgb(0,0,0)" text-rendering="optimizeQuality" shape-rendering="geometricPrecision" stroke="rgb(0,0,0)" stroke-opacity="0" stroke-width="2"><rect x="342" width="123" y="1" height="82" stroke="none"/></g><g text-rendering="optimizeQuality" stroke-width="2" shape-rendering="geometricPrecision" font-family="sans-serif"><text x="392" xml:space="preserve" y="46.5" stroke="none">TCA</text><line y2="61" fill="none" x1="342" x2="465" y1="61"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="Arrow-3892abbc-c49c-40df-984b-8959b6df44e6" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><line y2="41" fill="none" x1="465" x2="553" y1="41"/><polygon fill="none" points=" 551 39 551 43 555 41"/><polygon points=" 551 39 551 43 555 41" stroke="none"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="OperationalPolicy" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><rect fill="none" x="557" width="123" y="1" height="82"/></g><g fill-opacity="0" fill="rgb(0,0,0)" text-rendering="optimizeQuality" shape-rendering="geometricPrecision" stroke="rgb(0,0,0)" stroke-opacity="0" stroke-width="2"><rect x="557" width="123" y="1" height="82" stroke="none"/></g><g text-rendering="optimizeQuality" stroke-width="2" shape-rendering="geometricPrecision" font-family="sans-serif"><text x="564.5" xml:space="preserve" y="46.5" stroke="none">OperationalPolicy</text><line y2="1" fill="none" x1="557" x2="618" y1="42"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="Arrow-44a8b77e-d0eb-4c0d-82b6-0822ff35573f" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="2"><line y2="41" fill="none" x1="680" x2="768" y1="41"/><polygon fill="none" points=" 766 39 766 43 770 41"/><polygon points=" 766 39 766 43 770 41" stroke="none"/></g></g></g><g fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" font-family="'Dialog'" font-style="normal" data-element-id="stop-circle" stroke-linejoin="miter" font-size="12px" image-rendering="auto" stroke-dashoffset="0"><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"/><g><g shape-rendering="geometricPrecision" text-rendering="optimizeQuality" stroke-width="4"><circle fill="none" r="17" cx="789" cy="41"/></g></g></g></svg>
\ No newline at end of file
-- 
cgit