aboutsummaryrefslogtreecommitdiffstats
path: root/ui-react/src/components/loop_viewer/svg
diff options
context:
space:
mode:
Diffstat (limited to 'ui-react/src/components/loop_viewer/svg')
-rw-r--r--ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js17
-rw-r--r--ui-react/src/components/loop_viewer/svg/LoopSvg.js110
-rw-r--r--ui-react/src/components/loop_viewer/svg/LoopSvg.test.js132
-rw-r--r--ui-react/src/components/loop_viewer/svg/SvgGenerator.js240
-rw-r--r--ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap34
-rw-r--r--ui-react/src/components/loop_viewer/svg/example.svg1
6 files changed, 240 insertions, 294 deletions
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