You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cg...@apache.org on 2023/02/28 17:49:31 UTC
[plc4x] 07/07: Apache Hop integration.
This is an automated email from the ASF dual-hosted git repository.
cgarcia pushed a commit to branch feat/hop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 239d61d79d39873529d814cbbcf638f65f93da15
Author: César García <ce...@ceos.com.ve>
AuthorDate: Tue Feb 28 13:48:37 2023 -0400
Apache Hop integration.
---
.../apache-hop/plc4x-hop-actions/pom.xml | 146 +++
.../plc4x/hop/actions/ActionSampleMetaData.java | 35 +
.../plc4x/hop/actions/Plc4xCheckConnections.java | 271 ++++
.../hop/actions/Plc4xCheckConnectionsDialog.java | 371 ++++++
.../hop/actions/messages/messages_en_US.properties | 49 +
.../src/main/resources/plc4x_toddy.svg | 1306 ++++++++++++++++++++
.../plc4x-hop-assemblies-action/pom.xml | 82 ++
.../src/assembly/assembly.xml | 52 +
.../src/main/resources/version.xml | 20 +
.../plc4x-hop-assemblies-metadata/pom.xml | 82 ++
.../src/assembly/assembly.xml | 69 ++
.../src/main/resources/version.xml | 20 +
.../plc4x-hop-assemblies-transform/pom.xml | 82 ++
.../src/assembly/assembly.xml | 52 +
.../src/main/resources/version.xml | 20 +
.../{ => apache-hop/plc4x-hop-assemblies}/pom.xml | 59 +-
.../apache-hop/plc4x-hop-metadata/pom.xml | 129 ++
.../apache/plc4x/hop/metadata/Plc4xConnection.java | 73 ++
.../plc4x/hop/metadata/Plc4xConnectionEditor.java | 148 +++
.../metadata/messages/messages_en_US.properties | 22 +
.../src/main/resources/plc4x_toddy.svg | 1306 ++++++++++++++++++++
.../apache-hop/plc4x-hop-transformer/pom.xml | 143 +++
.../hop/transforms/plc4xevent/Plc4xEvent.java | 346 ++++++
.../hop/transforms/plc4xevent/Plc4xEventData.java | 50 +
.../transforms/plc4xevent/Plc4xEventDialog.java | 663 ++++++++++
.../hop/transforms/plc4xevent/Plc4xEventMeta.java | 239 ++++
.../plc4x/hop/transforms/plc4xinput/Plc4xRead.java | 446 +++++++
.../hop/transforms/plc4xinput/Plc4xReadData.java | 48 +
.../hop/transforms/plc4xinput/Plc4xReadDialog.java | 600 +++++++++
.../hop/transforms/plc4xinput/Plc4xReadMeta.java | 308 +++++
.../hop/transforms/plc4xoutput/Plc4xWrite.java | 478 +++++++
.../hop/transforms/plc4xoutput/Plc4xWriteData.java | 49 +
.../transforms/plc4xoutput/Plc4xWriteDialog.java | 674 ++++++++++
.../hop/transforms/plc4xoutput/Plc4xWriteMeta.java | 310 +++++
.../plc4x/hop/transforms/plc4xsubs/Plc4xSubs.java | 446 +++++++
.../hop/transforms/plc4xsubs/Plc4xSubsData.java | 49 +
.../hop/transforms/plc4xsubs/Plc4xSubsDialog.java | 601 +++++++++
.../hop/transforms/plc4xsubs/Plc4xSubsMeta.java | 310 +++++
.../plc4x/hop/transforms/util/Plc4xDataType.java | 115 ++
.../hop/transforms/util/Plc4xGeneratorField.java | 275 +++++
.../plc4x/hop/transforms/util/Plc4xPlcField.java | 148 +++
.../transforms/util/Plc4xWrapperConnection.java | 60 +
.../plc4xevent/messages/messages_en_US.properties | 69 ++
.../plc4xevent/messages/messages_es_ES.properties | 69 ++
.../plc4xinput/messages/messages_en_US.properties | 69 ++
.../plc4xinput/messages/messages_es_ES.properties | 69 ++
.../plc4xoutput/messages/messages_en_US.properties | 69 ++
.../plc4xoutput/messages/messages_es_ES.properties | 69 ++
.../plc4xsubs/messages/messages_en_US.properties | 69 ++
.../plc4xsubs/messages/messages_es_ES.properties | 69 ++
.../src/main/resources/plc4x_action.svg | 1306 ++++++++++++++++++++
.../src/main/resources/plc4x_event.svg | 822 ++++++++++++
.../src/main/resources/plc4x_read.svg | 813 ++++++++++++
.../src/main/resources/plc4x_subs.svg | 743 +++++++++++
.../src/main/resources/plc4x_write.svg | 810 ++++++++++++
.../plc4x-hop-utils/hop-plc4x-grafana/pom.xml | 138 +++
.../hop/utils/transforms/grafana/GrafanaPost.java | 589 +++++++++
.../grafana/GrafanaPostArgumentField.java | 70 ++
.../utils/transforms/grafana/GrafanaPostData.java | 66 +
.../transforms/grafana/GrafanaPostDialog.java | 1098 ++++++++++++++++
.../grafana/GrafanaPostLoookupField.java | 65 +
.../utils/transforms/grafana/GrafanaPostMeta.java | 425 +++++++
.../utils/transforms/grafana/GrafanaPostQuery.java | 57 +
.../transforms/grafana/GrafanaPostResultField.java | 90 ++
.../src/main/resources/grafana.svg | 103 ++
.../grafana/messages/messages_en_US.properties | 138 +++
.../{ => apache-hop/plc4x-hop-utils}/pom.xml | 50 +-
plc4j/integrations/apache-hop/pom.xml | 251 ++++
plc4j/integrations/pom.xml | 1 +
.../protocols/ads/images/ads-statemachine.svg | 1 +
src/site/asciidoc/images/plc4x-architecture.png | Bin 0 -> 24761 bytes
src/site/asciidoc/images/protocols-s7-osi.png | Bin 0 -> 49183 bytes
72 files changed, 18868 insertions(+), 72 deletions(-)
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-actions/pom.xml
new file mode 100644
index 0000000000..ee58270dbc
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-apache-hop</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>plc4x-hop-action</artifactId>
+ <packaging>jar</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Action</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>8</source>
+ <target>8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.jandex</groupId>
+ <artifactId>jandex-maven-plugin</artifactId>
+ <version>1.0.8</version>
+ <executions>
+ <execution>
+ <id>make-index</id>
+ <goals>
+ <goal>jandex</goal>
+ </goals>
+ <!-- phase is 'process-classes by default' -->
+ <configuration>
+ <!-- Nothing needed here for simple cases -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <ignoredDependencies>
+ <dependency>org.apache.plc4x:plc4j-api:jar:${project.version}</dependency>
+ <dependency>org.apache.plc4x:plc4j-spi:jar:${project.version}</dependency>
+ <dependency>org.apache.plc4x:plc4j-driver-s7:jar:${project.version}</dependency>
+ <dependency>org.apache.plc4x:plc4j-transport-tcp:jar:${project.version}</dependency>
+ </ignoredDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-core</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-ui</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
+ <version>${org.eclipse.platform.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-driver-s7</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-transport-tcp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>plc4x-hop-metadata</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-engine</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.w3c</groupId>
+ <artifactId>dom</artifactId>
+ <version>2.3.0-jaxb-1.0.6</version>
+ <scope>provided</scope>
+ </dependency>
+ -->
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/ActionSampleMetaData.java b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/ActionSampleMetaData.java
new file mode 100644
index 0000000000..ecaaf6efdf
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/ActionSampleMetaData.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.plc4x.hop.actions;
+
+import org.apache.hop.metadata.api.HopMetadata;
+import org.apache.hop.metadata.api.HopMetadataBase;
+import org.apache.hop.metadata.api.IHopMetadata;
+
+/**
+ *
+ * @author cgarcia
+ */
+@HopMetadata(
+ key = "Xplc4xconnection",
+ name = "PLC4x Connection",
+ description = "A shared PLC4x connection to a PLC",
+ image = "plc4x_toddy.svg",
+ documentationUrl = "/metadata-types/neo4j/neo4j-connection.html")
+public class ActionSampleMetaData extends HopMetadataBase implements IHopMetadata {
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnections.java b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnections.java
new file mode 100644
index 0000000000..752890f7f2
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnections.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.actions;
+
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.annotations.Action;
+import org.apache.hop.core.exception.HopXmlException;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.xml.XmlHandler;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.apache.hop.workflow.action.ActionBase;
+import org.apache.hop.workflow.action.IAction;
+
+
+import java.util.List;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.w3c.dom.Node;
+
+
+@Action(
+ id = "CHECK_PLC4X_CONNECTIONS",
+ name = "i18n::Plc4xAction.Name",
+ description = "i18n::Plc4xAction.Description",
+ image = "plc4x_toddy.svg",
+ categoryDescription = "i18n:org.apache.hop.workflow:ActionCategory.Category.Conditions",
+ keywords = "i18n::Plc4xAction.keyword",
+ documentationUrl = "/workflow/actions/checkdbconnection.html")
+public class Plc4xCheckConnections extends ActionBase implements Cloneable, IAction {
+ private static final Class<?> PKG = Plc4xCheckConnections.class; // Needed by Translator
+
+
+ private Plc4xConnection[] connections;
+
+ protected static final String[] unitTimeDesc =
+ new String[] {
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.UnitTimeMilliSecond.Label"),
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.UnitTimeSecond.Label"),
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.UnitTimeMinute.Label"),
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.UnitTimeHour.Label"),
+ };
+ protected static final String[] unitTimeCode =
+ new String[] {"millisecond", "second", "minute", "hour"};
+
+ public static final int UNIT_TIME_MILLI_SECOND = 0;
+ public static final int UNIT_TIME_SECOND = 1;
+ public static final int UNIT_TIME_MINUTE = 2;
+ public static final int UNIT_TIME_HOUR = 3;
+
+ private String[] waitfors;
+ private int[] waittimes;
+
+ private long timeStart;
+ private long now;
+
+ public Plc4xCheckConnections( String name) {
+ super(name, "");
+ //connections = null;
+ waitfors = null;
+ waittimes = null;
+ }
+
+ public Plc4xCheckConnections() {
+ this( "");
+ }
+
+ public Object clone() {
+ Plc4xCheckConnections c = (Plc4xCheckConnections) super.clone();
+ return c;
+ }
+
+
+ public Plc4xConnection[] getConnections() {
+ return connections;
+ }
+
+ public void setConnections(Plc4xConnection[] connections) {
+ this.connections = connections;
+ }
+
+ public String[] getWaitfors() {
+ return waitfors;
+ }
+
+ public void setWaitfors(String[] waitfors) {
+ this.waitfors = waitfors;
+ }
+
+ public int[] getWaittimes() {
+ return waittimes;
+ }
+
+ public void setWaittimes(int[] waittimes) {
+ this.waittimes = waittimes;
+ }
+
+ public long getTimeStart() {
+ return timeStart;
+ }
+
+ public long getNow() {
+ return now;
+ }
+
+ private static String getWaitTimeCode(int i) {
+ if (i < 0 || i >= unitTimeCode.length) {
+ return unitTimeCode[0];
+ }
+ return unitTimeCode[i];
+ }
+
+ public static String getWaitTimeDesc(int i) {
+ if (i < 0 || i >= unitTimeDesc.length) {
+ return unitTimeDesc[0];
+ }
+ return unitTimeDesc[i];
+ }
+
+ public static int getWaitTimeByDesc(String tt) {
+ if (tt == null) {
+ return 0;
+ }
+
+ for (int i = 0; i < unitTimeDesc.length; i++) {
+ if (unitTimeDesc[i].equalsIgnoreCase(tt)) {
+ return i;
+ }
+ }
+
+ // If this fails, try to match using the code.
+ return getWaitTimeByCode(tt);
+ }
+
+ private static int getWaitTimeByCode(String tt) {
+ if (tt == null) {
+ return 0;
+ }
+
+ for (int i = 0; i < unitTimeCode.length; i++) {
+ if (unitTimeCode[i].equalsIgnoreCase(tt)) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+
+
+ /**
+ *
+ * Save values to XML
+ *
+ * @return
+ */
+ @Override
+ public String getXml() {
+ StringBuilder xml = new StringBuilder(120);
+ xml.append(super.getXml());
+ xml.append(" <connections>").append(Const.CR);
+ if (connections != null) {
+ for (int i = 0; i < connections.length; i++) {
+ xml.append(" <connection>").append(Const.CR);
+ xml.append(" ")
+ .append(
+ XmlHandler.addTagValue(
+ "name", connections[i] == null ? null : connections[i].getName()));
+ xml.append(" ").append(XmlHandler.addTagValue("waitfor", waitfors[i]));
+ xml.append(" ")
+ .append(XmlHandler.addTagValue("waittime", getWaitTimeCode(waittimes[i])));
+ xml.append(" </connection>").append(Const.CR);
+ }
+ }
+ xml.append(" </connections>").append(Const.CR);
+
+ return xml.toString();
+ }
+
+ /**
+ *
+ * Read the XML and get the values needed for the acton
+ *
+ * @param entrynode
+ * @param metadataProvider
+ * @throws HopXmlException
+ */
+ @Override
+ public void loadXml( Node entrynode, IHopMetadataProvider metadataProvider, IVariables variables ) throws HopXmlException {
+ try {
+ super.loadXml(entrynode);
+ Node fields = XmlHandler.getSubNode(entrynode, "connections");
+
+ // How many hosts?
+ int nrFields = XmlHandler.countNodes(fields, "connection");
+ connections = new Plc4xConnection[nrFields];
+ waitfors = new String[nrFields];
+ waittimes = new int[nrFields];
+ // Read them all...
+ for (int i = 0; i < nrFields; i++) {
+ Node fnode = XmlHandler.getSubNodeByNr(fields, "connection", i);
+ String dbname = XmlHandler.getTagValue(fnode, "name");
+
+ //connections[i] = Plc4xConnection.loadDatabase(metadataProvider, dbname);
+ if (dbname != null) {
+ connections[i] = metadataProvider.getSerializer(Plc4xConnection.class).load(dbname);
+ waitfors[i] = XmlHandler.getTagValue(fnode, "waitfor");
+ waittimes[i] = getWaitTimeByCode(Const.NVL(XmlHandler.getTagValue(fnode, "waittime"), ""));
+ };
+ }
+ } catch (HopXmlException xe) {
+ throw new HopXmlException(
+ BaseMessages.getString(
+ PKG,
+ "Plc4xCheckConnections.ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node",
+ xe.getMessage()));
+ } catch (HopException ex) {
+ throw new HopXmlException(
+ BaseMessages.getString(
+ PKG,
+ "Plc4xCheckConnections.ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node",
+ ex.getMessage()));
+ }
+ }
+
+ /**
+ * Execute this action and return the result. In this case it means, just set the result boolean in the Result
+ * class.
+ *
+ * @param result The result of the previous execution
+ * @return The Result of the execution.
+ */
+ @Override
+ public Result execute( Result result, int nr ) {
+ result.setResult(true);
+ System.out.println("NR: " + nr);
+
+ return result;
+ }
+
+ /**
+ *
+ * Add checks to report warnings
+ *
+ * @param remarks
+ * @param workflowMeta
+ * @param variables
+ * @param metadataProvider
+ */
+ @Override
+ public void check( List<ICheckResult> remarks, WorkflowMeta workflowMeta, IVariables variables,
+ IHopMetadataProvider metadataProvider ) {
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnectionsDialog.java b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnectionsDialog.java
new file mode 100644
index 0000000000..791d3b8861
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/java/org/apache/plc4x/hop/actions/Plc4xCheckConnectionsDialog.java
@@ -0,0 +1,371 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.plc4x.hop.actions;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.gui.WindowProperty;
+import org.apache.hop.ui.core.widget.ColumnInfo;
+import org.apache.hop.ui.core.widget.TableView;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.apache.hop.ui.workflow.action.ActionDialog;
+import org.apache.hop.ui.workflow.dialog.WorkflowDialog;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.apache.hop.workflow.action.IAction;
+import org.apache.hop.workflow.action.IActionDialog;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.*;
+
+import org.apache.hop.metadata.api.IHopMetadata;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.metadata.MetadataManager;
+import org.apache.hop.ui.core.widget.MetaSelectionLine;
+
+
+public class Plc4xCheckConnectionsDialog extends ActionDialog implements IActionDialog {
+ private static final Class<?> PKG = Plc4xCheckConnectionsDialog.class; // Needed by Translator
+
+ private Shell shell;
+
+ private Text wName;
+
+ private Plc4xCheckConnections action;
+
+ private boolean changed;
+
+ private TableView wFields;
+
+ private MetaSelectionLine<Plc4xConnection> wConnection;
+
+ public Plc4xCheckConnectionsDialog(Shell parent, IAction action, WorkflowMeta workflowMeta, IVariables variables) {
+ super( parent, workflowMeta, variables );
+ this.action = (Plc4xCheckConnections) action;
+ if ( this.action.getName() == null ) {
+ this.action.setName( BaseMessages.getString( PKG, "Plc4xCheckConnections.Label" ) );
+ }
+ }
+
+ @Override
+ public IAction open() {
+ Shell parent = getParent();
+
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.MIN | SWT.MAX | SWT.RESIZE);
+ props.setLook(shell);
+ WorkflowDialog.setShellImage(shell, action);
+
+ ModifyListener lsMod = (ModifyEvent e) -> action.setChanged();
+ changed = action.hasChanged();
+
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Plc4xCheckonnections.Title"));
+
+ int middle = props.getMiddlePct();
+ int margin = Const.MARGIN;
+
+ // Buttons at the bottom
+ //
+ Button wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, (Event e) -> ok());
+ Button wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, (Event e) -> cancel());
+ BaseTransformDialog.positionBottomButtons(shell, new Button[] {wOk, wCancel}, margin, null);
+
+ // Filename line
+ Label wlName = new Label(shell, SWT.RIGHT);
+ wlName.setText(BaseMessages.getString(PKG, "Plc4xCheckConnections.Name.Label"));
+ props.setLook(wlName);
+ FormData fdlName = new FormData();
+ fdlName.left = new FormAttachment(0, 0);
+ fdlName.right = new FormAttachment(middle, -margin);
+ fdlName.top = new FormAttachment(0, margin);
+ wlName.setLayoutData(fdlName);
+ wName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wName);
+ wName.addModifyListener(lsMod);
+ FormData fdName = new FormData();
+ fdName.left = new FormAttachment(middle, 0);
+ fdName.top = new FormAttachment(0, margin);
+ fdName.right = new FormAttachment(100, 0);
+ wName.setLayoutData(fdName);
+
+ Label wlFields = new Label(shell, SWT.NONE);
+ wlFields.setText(BaseMessages.getString(PKG, "Plc4xCheckConnections.Fields.Label"));
+ props.setLook(wlFields);
+ FormData fdlFields = new FormData();
+ fdlFields.left = new FormAttachment(0, 0);
+ // fdlFields.right= new FormAttachment(middle, -margin);
+ fdlFields.top = new FormAttachment(wName, 2 * margin);
+ wlFields.setLayoutData(fdlFields);
+
+
+ wConnection =
+ new MetaSelectionLine<>(
+ variables,
+ metadataProvider,
+ Plc4xConnection.class,
+ shell,
+ SWT.NONE,
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.Connection.Label"),
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.Connection.Tooltip"));
+ props.setLook(wConnection);
+ FormData fdConnection = new FormData();
+ fdConnection.left = new FormAttachment(0, 0);
+ fdConnection.right = new FormAttachment(100, 0);
+ //fdConnection.top = new FormAttachment(wTransformName, margin);
+ wConnection.setLayoutData(fdConnection);
+
+ try {
+ wConnection.fillItems();
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "Error listing Cassandra connection metadata objects", e);
+ }
+
+
+ // Buttons to the right of the screen...
+ Button wbGetConnections = new Button(shell, SWT.PUSH | SWT.CENTER);
+ props.setLook(wbGetConnections);
+ wbGetConnections.setText(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.GetConnections"));
+ wbGetConnections.setToolTipText(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.GetConnections.Tooltip"));
+ FormData fdbGetConnections = new FormData();
+ fdbGetConnections.right = new FormAttachment(100, -margin);
+ fdbGetConnections.top = new FormAttachment(wlFields, margin);
+ wbGetConnections.setLayoutData(fdbGetConnections);
+
+ // Buttons to the right of the screen...
+ Button wbdSourceFileFolder = new Button(shell, SWT.PUSH | SWT.CENTER);
+ props.setLook(wbdSourceFileFolder);
+ wbdSourceFileFolder.setText(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.DeleteEntry"));
+ wbdSourceFileFolder.setToolTipText(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.DeleteSourceFileButton.Label"));
+ FormData fdbdSourceFileFolder = new FormData();
+ fdbdSourceFileFolder.right = new FormAttachment(100, -margin);
+ fdbdSourceFileFolder.top = new FormAttachment(wbGetConnections, margin);
+ wbdSourceFileFolder.setLayoutData(fdbdSourceFileFolder);
+
+ int rows =
+ action.getConnections() == null
+ ? 1
+ : (action.getConnections().length == 0 ? 0 : action.getConnections().length);
+
+ final int FieldsRows = rows;
+
+ ColumnInfo[] colinf =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.Fields.Argument.Label"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ this.getWorkflowMeta().getDatabaseNames(),
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.Fields.WaitFor.Label"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4xCheckConnections.Fields.WaitForTime.Label"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ Plc4xCheckConnections.unitTimeDesc,
+ false),
+ };
+
+ colinf[0].setToolTip(BaseMessages.getString(PKG, "Plc4xCheckConnections.Fields.Column"));
+ colinf[1].setUsingVariables(true);
+ colinf[1].setToolTip(BaseMessages.getString(PKG, "Plc4xCheckConnections.WaitFor.ToolTip"));
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
+ colinf,
+ FieldsRows,
+ lsMod,
+ props);
+
+ FormData fdFields = new FormData();
+ fdFields.left = new FormAttachment(0, 0);
+ fdFields.top = new FormAttachment(wlFields, margin);
+ fdFields.right = new FormAttachment(wbGetConnections, -margin);
+ fdFields.bottom = new FormAttachment(wOk, -2 * margin);
+ wFields.setLayoutData(fdFields);
+
+ // Delete files from the list of files...
+ wbdSourceFileFolder.addListener(
+ SWT.Selection,
+ e -> {
+ int[] idx = wFields.getSelectionIndices();
+ wFields.remove(idx);
+ wFields.removeEmptyRows();
+ wFields.setRowNums();
+ });
+
+ // get connections...
+ wbGetConnections.addListener(SWT.Selection, e -> getConnections());
+
+ getData();
+
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return action;
+ }
+
+ // public void addDatabases() {
+ // connections = workflowMeta.getDatabaseNames();
+ // }
+
+ public void getConnections() {
+ /*
+ this.workflowMeta.getMetadataProvider().getMetadataClasses().forEach(
+ (c) -> {
+ System.out.println("Name: " + c.getName());
+ });
+ IHopMetadataProvider hmdp = this.workflowMeta.getMetadataProvider();
+ */
+ Class<IHopMetadata> metadataClass = null;
+
+ java.util.List<Plc4xConnection> databases = new ArrayList<>(); //this.workflowMeta.getMetadataProvider().
+ try {
+ metadataClass = metadataProvider.getMetadataClassForKey("plc4x-connection");
+ MetadataManager<IHopMetadata> manager = new MetadataManager<>(variables, metadataProvider, metadataClass, null);
+ manager.getNames().forEach((s)->{
+ try {
+ databases.add((Plc4xConnection) manager.loadElement(s));
+ } catch (HopException ex) {
+ Logger.getLogger(Plc4xCheckConnectionsDialog.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ });
+
+ } catch (Exception ex) {
+ Logger.getLogger(Plc4xCheckConnectionsDialog.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+
+ wFields.removeAll();
+
+ for (Plc4xConnection ci : databases) {
+ if (ci != null) {
+ wFields.add(new String[] {ci.getName(), "0", Plc4xCheckConnections.unitTimeDesc[0]});
+ }
+ }
+ wFields.removeEmptyRows();
+ wFields.setRowNums();
+ wFields.optWidth(true);
+ }
+
+ public void dispose() {
+ WindowProperty winprop = new WindowProperty(shell);
+ props.setScreen(winprop);
+ shell.dispose();
+ }
+
+ /** Copy information from the meta-data input to the dialog fields. */
+ public void getData() {
+ if (action.getName() != null) {
+ wName.setText(action.getName());
+ }
+
+ if (action.getConnections() != null) {
+ for (int i = 0; i < action.getConnections().length; i++) {
+ TableItem ti = wFields.table.getItem(i);
+ if (action.getConnections()[i] != null) {
+ ti.setText(1, action.getConnections()[i].getName());
+ ti.setText(2, "" + Const.toInt(action.getWaitfors()[i], 0));
+ ti.setText(3, Plc4xCheckConnections.getWaitTimeDesc(action.getWaittimes()[i]));
+ }
+ }
+ wFields.setRowNums();
+ wFields.optWidth(true);
+ }
+ wName.selectAll();
+ wName.setFocus();
+ }
+
+ private void cancel() {
+ action.setChanged(changed);
+ action = null;
+ dispose();
+ }
+
+ private void ok() {
+ if (Utils.isEmpty(wName.getText())) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ mb.setText(BaseMessages.getString(PKG, "System.TransformActionNameMissing.Title"));
+ mb.setMessage(BaseMessages.getString(PKG, "System.ActionNameMissing.Msg"));
+ mb.open();
+ return;
+ }
+ Class<IHopMetadata> metadataClass = null;
+ action.setName(wName.getText());
+
+ int nrItems = wFields.nrNonEmpty();
+ System.out.println("Numero de items: " + nrItems);
+
+ Plc4xConnection[] connections = new Plc4xConnection[nrItems];
+ String[] waitfors = new String[nrItems];
+ int[] waittimes = new int[nrItems];
+
+
+ try {
+ metadataClass = metadataProvider.getMetadataClassForKey("plc4x-connection");
+ } catch (HopException ex) {
+ Logger.getLogger(Plc4xCheckConnectionsDialog.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ MetadataManager<IHopMetadata> manager = new MetadataManager<>(variables, metadataProvider, metadataClass, null);
+
+ for (int i = 0; i < nrItems; i++) {
+ String arg = wFields.getNonEmpty(i).getText(1);
+ Plc4xConnection conn;
+ try {
+ conn = (Plc4xConnection) manager.loadElement(arg);
+ if (conn != null) {
+ connections[i] = conn;
+ waitfors[i] = "" + Const.toInt(wFields.getNonEmpty(i).getText(2), 0);
+ waittimes[i] =
+ Plc4xCheckConnections.getWaitTimeByDesc(wFields.getNonEmpty(i).getText(3));
+ }
+ } catch (HopException ex) {
+ Logger.getLogger(Plc4xCheckConnectionsDialog.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ }
+ action.setConnections(connections);
+ action.setWaitfors(waitfors);
+ action.setWaittimes(waittimes);
+
+ dispose();
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/org/apache/plc4x/hop/actions/messages/messages_en_US.properties b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/org/apache/plc4x/hop/actions/messages/messages_en_US.properties
new file mode 100644
index 0000000000..f13f6255eb
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/org/apache/plc4x/hop/actions/messages/messages_en_US.properties
@@ -0,0 +1,49 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+#
+#
+Plc4xCheckConnections.Name=Check PLC connections
+Plc4xCheckConnections.Description=Check if we can connect to one or several databases.
+Plc4xCheckConnections.ConnectionOK=We can successfully connect to database [{0}] (connection [{1}])
+Plc4xCheckConnections.ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node=Unable to load action of type 'Check Db connection' from XML node. Exception : {0}
+Plc4xCheckConnections.Exception=Cannot connect to database [{0}] (connection [{1}]). Exception : [{2}]
+Plc4xCheckConnections.Log.Info.ConnectionsInSuccess=[{0}] connections were successfully checked.
+Plc4xCheckConnections.Log.Info.ConnectionsInError=[{0}] connections were in error.
+Plc4xCheckConnections.UnitTimeMilliSecond.Label=Milliseconds
+Plc4xCheckConnections.UnitTimeSecond.Label=Seconds
+Plc4xCheckConnections.UnitTimeMinute.Label=Minutes
+Plc4xCheckConnections.UnitTimeHour.Label=Hours
+Plc4xCheckConnections.Connected=Connected to database [{0}] (connection [{1}])...
+Plc4xCheckConnections.Wait=We need to leave the connection open {0} {1} ...
+Plc4xCheckConnections.WaitTimeIsElapsed.Label=Wait time is elapsed for plc [{0}] (connection [{1}]). The connection will be closed ...
+Plc4xCheckConnections.Title=Check PLC connections
+Plc4xCheckConnections.Name.Default=Check PLC connections
+Plc4xCheckConnections.Name.Label=Action name
+Plc4xCheckConnections.Fields.Argument.Label=Connection
+Plc4xCheckConnections.Fields.Label=Connections
+Plc4xCheckConnections.Fields.Column=Connections
+Plc4xCheckConnections.Fields.WaitFor.Label=Wait
+Plc4xCheckConnections.Fields.WaitForTime.Label=Units of time
+Plc4xCheckConnections.WaitFor.ToolTip=After the connection was opened\nwait x (s, mn,..)
+Plc4xCheckConnections.DeleteSourceFileButton.Label=Remove selected items from the list.
+Plc4xCheckConnections.DeleteEntry=Delete
+Plc4xCheckConnections.GetConnections=Get connections
+Plc4xCheckConnections.GetConnections.Tooltip=Get available connections
+Plc4xCheckConnections.keyword=check,plc,database,connection
+Plc4xCheckConnections.Connection.Label
+Plc4xCheckConnections.Connection.Tooltip
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/plc4x_toddy.svg b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/plc4x_toddy.svg
new file mode 100644
index 0000000000..01694ecd5d
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-actions/src/main/resources/plc4x_toddy.svg
@@ -0,0 +1,1306 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ sodipodi:docname="iconotoddyconplc2.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="101.5"
+ inkscape:cx="8.3201971"
+ inkscape:cy="4.5960591"
+ inkscape:window-width="1920"
+ inkscape:window-height="1001"
+ inkscape:window-x="-9"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer52" />
+ <defs
+ id="defs2">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath78260">
+ <path
+ id="path78262"
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 324.28906,352.80664 v 76.18359 h 20.58203 c -0.0462,-0.10335 -0.0829,-0.21015 -0.10742,-0.31835 -0.43816,-10e-6 -0.87632,-3e-5 -1.31445,0 -0.55264,8e-5 -1.10556,9.9e-4 -1.6582,0 -0.64072,-10e-4 -1.28115,0.007 -1.92188,0.002 -0.35799,-0.003 -0.73573,0.008 -1.09766,-0.0156 -0.003,0 0.007,-0.003 0.01,-0.004 0.0863,-0.0166 0.17347,-0.0342 0.25977,-0.0508 -0.2144,0.025 -0.42708,0.0642 -0.64063,0.0957 -0.49177,-0.0339 -0.98416,-0.0786 -1.47656,-0.10156 -0.0774,-0.004 0.30541,0.05 [...]
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath81911">
+ <path
+ id="path81913"
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 395.09961,461.69922 v 42.96484 c 0.0746,-0.0504 0.14872,-0.10118 0.22266,-0.15234 0.93912,-0.64976 1.92039,-1.23589 2.85742,-1.88867 1.25063,-0.87125 2.48887,-1.7632 3.73242,-2.64453 1.05963,-0.76014 2.1181,-1.51916 3.17773,-2.2793 1.81669,-1.30323 3.50814,-1.82371 4.91016,-1.78711 0.85754,0.0224 1.60218,0.25706 2.20508,0.64258 0.23436,-0.0636 0.46865,-0.12661 0.70117,-0.19531 0.40305,-0.0456 0.80391,-0.11562 1.20898,-0.13672 0.21987,-0.0113 0.43985,-0.0169 0.66016,-0.0156 [...]
+ </clipPath>
+ </defs>
+ <g
+ inkscape:groupmode="layer"
+ id="layer52"
+ inkscape:label="Capa 2">
+ <path
+ style="fill:#f5f5f5;stroke:#f5f5f5;stroke-width:0.9355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 5.1062072,5.7391588 6.8487514,7.1431509 8.7779937,7.0574466 9.7326615,6.3436554 10.276258,4.8805204 9.7326615,4.1109178 6.1778718,4.5009157 Z"
+ id="path1177" />
+ </g>
+ <g
+ inkscape:label="Capa 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline;opacity:1"
+ sodipodi:insensitive="true">
+ <g
+ id="g1481"
+ transform="matrix(0.01850365,0,0,0.01824053,1.5356497,-1.2454454)">
+ <g
+ inkscape:label="Image"
+ id="g830"
+ style="display:none;opacity:1">
+ <image
+ width="696.6618"
+ height="985.07983"
+ preserveAspectRatio="none"
+ style="image-rendering:optimizeSpeed"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+gAAAWGCAYAAAAcjY/0AAAACXBIWXMAADXTAAA10wEMIUN3AAAA B3RJTUUH5AMeFSExccvdCgAAIABJREFUeJzs3Xl83PV97/v3bxbNSCNrl7yMx+s4YGOMjTzYjLGd mIMzEGhZ0kKBljRtgSaFkJySntKQk5w4t7nNuU3vOb23hXNOcnqT9qa5N8staXFCSxsIDsaYGDBe sAy2ZSTbsrVY1jrL7/7xG1mLtcyMfrPq9eQxWJ75zff3ndHImvd8vosEAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [...]
+ id="image832" />
+ </g>
+ <g
+ id="layer45"
+ inkscape:label="bracitoplc 2"
+ style="display:inline">
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1712"
+ width="13.140327"
+ height="54.751366"
+ x="555.72638"
+ y="753.92633" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1714"
+ width="13.140317"
+ height="54.203869"
+ x="555.72638"
+ y="699.72247" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1721"
+ width="13.961588"
+ height="47.359943"
+ x="555.72638"
+ y="652.36255" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1723"
+ width="12.866549"
+ height="47.907455"
+ x="569.68799"
+ y="651.815" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1725"
+ width="13.687866"
+ height="54.203857"
+ x="568.8667"
+ y="699.72247" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1727"
+ width="13.687866"
+ height="54.751343"
+ x="568.8667"
+ y="753.92633" />
+ </g>
+ <g
+ id="layer47"
+ inkscape:label="bracitoplc 4"
+ style="display:inline">
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828"
+ sodipodi:type="arc"
+ sodipodi:cx="575.69299"
+ sodipodi:cy="659.0755"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 578.11268,659.0755 a 2.4196913,2.564873 0 0 1 -2.40082,2.5648 2.4196913,2.564873 0 0 1 -2.43826,-2.5248 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828-6"
+ sodipodi:type="arc"
+ sodipodi:cx="572.78937"
+ sodipodi:cy="803.04718"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 575.20906,803.04718 a 2.4196913,2.564873 0 0 1 -2.40083,2.5648 2.4196913,2.564873 0 0 1 -2.43826,-2.5248 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828-6-9"
+ sodipodi:type="arc"
+ sodipodi:cx="561.36841"
+ sodipodi:cy="802.36963"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 563.7881,802.36963 a 2.4196913,2.564873 0 0 1 -2.40083,2.56479 2.4196913,2.564873 0 0 1 -2.43826,-2.52479 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ </g>
+ <g
+ id="layer46"
+ inkscape:label="bracitoplc 3"
+ style="display:inline">
+ <path
+ style="fill:#9d9eab;fill-opacity:0.996078;stroke:#432c33;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 580.77512,652.91004 9.44461,1.77942 0.13688,27.23881 -9.44461,4.92762 7.93895,1.09503 -1.09503,23.81684 -7.52831,0.27376 z"
+ id="path1763" />
+ <path
+ style="fill:#939d4d;fill-opacity:0.992157;stroke:#432c33;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 578.9957,808.13017 7.52831,-6.70704 v -14.78287 l -6.84392,-4.24323 7.80207,-0.13688 0.27376,-22.72182 -8.62334,-0.27376 z"
+ id="path1765" />
+ <rect
+ style="fill:#939d4d;fill-opacity:0.992157;stroke:#432c33;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1789"
+ width="8.6233397"
+ height="47.496811"
+ x="579.13257"
+ y="711.76776" />
+ </g>
+ <g
+ id="layer35"
+ inkscape:label="bracitoplc 1"
+ style="display:inline">
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1687"
+ width="138.26697"
+ height="114.77483"
+ x="425.67212"
+ y="619.44098" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1689"
+ width="42.706066"
+ height="10.40276"
+ x="439.65347"
+ y="734.21582" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1691"
+ width="42.706074"
+ height="11.497789"
+ x="482.35953"
+ y="734.21582" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1693"
+ width="41.611038"
+ height="96.909912"
+ x="439.65347"
+ y="744.61859" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1695"
+ width="43.801086"
+ height="95.81488"
+ x="481.26453"
+ y="745.71362" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1697"
+ width="13.414075"
+ height="106.49141"
+ x="525.06561"
+ y="735.03711" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1699"
+ width="15.877909"
+ height="102.93256"
+ x="538.47968"
+ y="735.03711" />
+ </g>
+ <g
+ id="layer48"
+ inkscape:label="bracitoplc 5"
+ style="display:inline">
+ <rect
+ style="fill:#6d9ed8;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14676"
+ width="31.552776"
+ height="10.646642"
+ x="435.73804"
+ y="632.60413" />
+ <rect
+ style="fill:#d3c9b7;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14678"
+ width="4.6458073"
+ height="5.4201088"
+ x="437.28662"
+ y="645.18652" />
+ <rect
+ style="fill:#f56a9e;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14680"
+ width="4.6458073"
+ height="16.647476"
+ x="437.28662"
+ y="655.25244" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14682"
+ width="4.8393826"
+ height="11.420943"
+ x="437.48019"
+ y="677.51361" />
+ <rect
+ style="fill:#191928;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14684"
+ width="7.9365878"
+ height="11.614519"
+ x="440.57742"
+ y="699.58118" />
+ <rect
+ style="fill:#191928;fill-opacity:1;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14686"
+ width="7.9365878"
+ height="11.808094"
+ x="440.771"
+ y="716.61578" />
+ <rect
+ style="fill:#9fbfc1;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14688"
+ width="8.7108889"
+ height="61.944099"
+ x="487.03549"
+ y="637.83063" />
+ <rect
+ style="fill:#72a2b1;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14690"
+ width="5.2265334"
+ height="11.227368"
+ x="487.42264"
+ y="715.45435" />
+ <rect
+ style="fill:#4e4d53;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14692"
+ width="7.1622868"
+ height="10.646642"
+ x="526.52484"
+ y="701.51691" />
+ <rect
+ style="fill:#4d4c52;fill-opacity:1;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14694"
+ width="6.775136"
+ height="9.4851904"
+ x="545.10809"
+ y="701.71051" />
+ </g>
+ <g
+ id="layer49"
+ inkscape:label="bracitoplc 6"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#432c33;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 480.6475,733.45686 479.48605,617.8924"
+ id="path33186" />
+ <path
+ style="fill:none;stroke:#422d34;stroke-width:3.4723;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 521.10445,618.08707 0.96846,116.53014"
+ id="path33188" />
+ <path
+ style="fill:none;stroke:#432c33;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 541.8173,735.19904 0.38715,-116.72592"
+ id="path33190" />
+ </g>
+ <g
+ id="layer50"
+ inkscape:label="bracitoplc 7"
+ style="display:inline">
+ <rect
+ style="fill:#acacb8;fill-opacity:0.996078;stroke:#422d34;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36118"
+ width="11.808094"
+ height="41.037968"
+ x="495.16565"
+ y="766.17108" />
+ <rect
+ style="fill:#acacb8;fill-opacity:1;stroke:#422d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36120"
+ width="7.549437"
+ height="41.812267"
+ x="526.71844"
+ y="762.29956" />
+ <rect
+ style="fill:#acacb8;fill-opacity:1;stroke:#422d34;stroke-width:1.0613;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36120-1"
+ width="7.549437"
+ height="47.095997"
+ x="541.91406"
+ y="762.04877" />
+ <rect
+ style="fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396"
+ width="3.7518525"
+ height="13.356678"
+ x="530.37915"
+ y="762.42542" />
+ <rect
+ style="fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3"
+ width="3.7518525"
+ height="13.356678"
+ x="545.71167"
+ y="762.04877" />
+ <rect
+ style="display:inline;fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3-0"
+ width="3.7518525"
+ height="13.356678"
+ x="528.73328"
+ y="786.12146"
+ inkscape:transform-center-x="-15.877896"
+ inkscape:transform-center-y="-23.679966" />
+ <rect
+ style="display:inline;fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3-0-9"
+ width="3.7518525"
+ height="13.356678"
+ x="543.72144"
+ y="789.26965"
+ inkscape:transform-center-x="-15.877896"
+ inkscape:transform-center-y="-23.679966" />
+ </g>
+ <g
+ id="layer51"
+ inkscape:label="bracitoplc 8">
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="692.67322" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="688.22467" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="683.77612" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="679.32758" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="674.87903" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="670.43048" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="665.98193" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="661.53339" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="657.08484" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="652.63629" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="648.18774" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-8"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="643.7392" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-7"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="693.17474" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="688.7262" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="684.27765" />
+ <rect
+ style="fill:#a5b17b;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-8"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="679.8291" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-6"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="675.38055" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="670.93201" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="666.48346" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-0"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="662.03491" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-2"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="657.58636" />
+ <rect
+ style="fill:#a5b17b;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="653.13782" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-9"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="648.68927" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-8-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="644.24072" />
+ </g>
+ <g
+ id="layer12"
+ inkscape:label="piernas1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 303.67005,695.87776 c 0,0 8.17142,20.65132 10.53645,31.4521 3.12408,14.26726 4.49063,28.95763 4.71781,43.56116 0.0425,2.73357 -0.62904,8.17755 -0.62904,8.17755 0,0 -13.5481,8.85046 -20.91565,12.10906 -2.21358,0.97904 -6.91946,2.20164 -6.91946,2.20164 0,0 -4.25625,-0.25265 -5.9759,0.78631 -1.86725,1.12814 -2.87795,3.35789 -3.77425,5.34685 -1.21716,2.70097 -2.89417,5.81127 -2.04439,8.64933 0.74456,2.48665 3.27563,4.32412 5.66138,5.34686 4.5353,1.94422 10.4375,0.95612 15.568 [...]
+ id="path45804"
+ sodipodi:nodetypes="csscscsssssscsccc" />
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 349.74737,702.16818 8.96385,72.02531 c 0,0 1.1094,6.66922 3.30248,9.5929 2.73079,3.64053 7.23484,4.9864 11.32275,6.13316 9.2398,2.59198 28.14963,-0.78631 28.14963,-0.78631 0,0 7.49833,-5.59383 8.80659,-10.06467 0.91855,-3.13907 0.53128,-6.91577 -1.10082,-9.75015 -1.00971,-1.75352 -2.94495,-3.00961 -4.87508,-3.617 -1.75081,-0.55096 -3.72827,-0.30668 -5.50412,0.15726 -4.80939,1.25645 -8.57615,5.12018 -13.20988,6.91947 -2.6787,1.04015 -5.47589,1.91194 -8.33481,2.20164 -3.708 [...]
+ id="path45806"
+ sodipodi:nodetypes="ccsscssssssscsssccc" />
+ </g>
+ <g
+ id="layer13"
+ inkscape:label="piernas2"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 296.59332,813.27273 c -1.65123,-1.49398 -2.14474,-1.41645 -2.3724,-5.09025 0,0 0.98475,-2.852 3.1587,-5.15134 l -0.80374,5.75966 0.72511,4.16741 z"
+ id="path50785"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 283.80717,811.40996 c -1.09189,-1.9407 -1.5845,-2.02376 -0.63475,-5.57997 0,0 1.83877,-2.39219 4.62994,-3.88295 l -2.58967,5.20704 -0.63462,4.18214 z"
+ id="path50785-5"
+ sodipodi:nodetypes="cccccc"
+ inkscape:transform-center-x="1.2111362"
+ inkscape:transform-center-y="0.54705423" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 406.70034,784.46583 c -0.51381,-2.16669 -0.20814,-2.56182 -3.31794,-4.53103 0,0 -2.97366,-0.51087 -6.03585,0.28661 l 5.43453,2.07014 3.30274,2.64292 z"
+ id="path50785-7"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1.00157;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.42874,777.16475 c -0.51381,-2.16669 -0.20814,-2.56182 -3.31794,-4.53103 0,0 -2.97366,-0.51087 -6.03585,0.28661 l 5.43453,2.07014 3.30274,2.64292 z"
+ id="path50785-7-0"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ <g
+ id="layer8"
+ inkscape:label="cola1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 266.43514,668.97904 c 0,0 -35.74884,34.3707 -51.59679,53.37598 -7.82609,9.38525 -14.93118,19.40333 -21.3504,29.8016 -5.01676,8.12647 -10.13103,16.36002 -13.34399,25.35359 -4.4804,12.54132 -6.29825,18.70817 -6.2272,32.02559 0.0413,7.73538 1.21731,22.30215 3.1136,29.8016 3.25519,12.87359 11.11999,38.25279 11.11999,38.25279 l 5.7824,33.35999 8.896,-16.4576 18.6816,48.48319 -6.2272,-42.70079 c 0,0 24.6715,21.78542 39.58719,28.0224 16.39477,6.85546 34.77126,7.94088 52.48639,9. [...]
+ id="path26360"
+ sodipodi:nodetypes="cssssscccccssssssssssssccsssssscsscc" />
+ </g>
+ <g
+ id="layer9"
+ inkscape:label="cola2"
+ style="display:inline">
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 352.28151,872.69739 c 0,0 7.44415,4.85397 10.2304,8.2288 1.81572,2.19929 3.29625,4.79864 4.0032,7.5616 1.30484,5.0997 0.91579,10.57227 0.2224,15.79039 -0.782,5.88496 -2.57092,11.661 -4.8928,17.1248 -2.31244,5.4416 -10.15408,16.28915 -10.15408,16.28915 0,0 30.85563,-3.23121 45.07087,-7.17076 13.95855,-3.86841 26.07208,-13.03889 40.03199,-16.90239 7.14369,-1.97707 14.72383,-1.79375 22.0176,-3.1136 7.09741,-1.28432 14.47159,-1.8928 21.12799,-4.6704 16.52917,-6.89734 32.61892 [...]
+ id="path30974"
+ sodipodi:nodetypes="csssscsssssssssscccccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 295.79193,876.25579 c 0,0 0.86685,2.27962 1.7792,5.3376 0.97587,3.27088 0.88529,6.84558 0.4448,10.23039 -0.93197,7.16143 -2.93554,14.374 -6.4496,20.6832 -4.29611,7.71331 -17.3472,20.01599 -17.3472,20.01599 -18.29893,-1.24213 -29.41982,-9.37518 -40.47679,-17.56959 l -5.1152,-3.5584 c 0,0 14.80505,-2.82191 19.3488,-4.8928 5.26384,-2.39908 10.73722,-4.88001 14.9008,-8.896 3.24121,-3.12632 6.06377,-7.02353 7.33919,-11.34239 1.82667,-6.18552 -0.2224,-15.7904 -0.2224,-15.7904 l [...]
+ id="path30976"
+ sodipodi:nodetypes="cssscccsssccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 173.91676,809.9806 c 0,0 6.53772,7.07804 10.8976,8.6736 7.10409,2.59984 22.68479,0.6672 22.68479,0.6672 l 20.01599,-6.0048 4.6704,15.3456 c 0,0 -2.92583,10.40351 -5.78239,14.9008 -2.36154,3.71794 -5.42281,7.16682 -9.1184,9.56319 -5.01672,3.25305 -10.99731,5.06684 -16.9024,6.0048 -5.5663,0.88415 -16.90239,-0.4448 -16.90239,-0.4448 l -3.1136,-9.5632 -5.1152,-19.12639 z"
+ id="path30978"
+ sodipodi:nodetypes="cscccssscccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 186.37115,764.83342 c 0,0 2.61472,6.12608 4.8928,8.45119 3.70148,3.77789 8.5302,6.61323 13.5664,8.2288 4.6723,1.49883 9.79676,1.60842 14.6784,1.112 4.83236,-0.49141 14.01119,-4.0032 14.01119,-4.0032 l 8.6736,-16.01279 c 0,0 -3.5584,0.2224 -7.784,0 -4.2256,-0.2224 -13.59615,1.11289 -19.57119,-1.5568 -3.9257,-1.75403 -7.03587,-5.26626 -9.3408,-8.896 -1.88504,-2.96851 -3.336,-10.008 -3.336,-10.008 z"
+ id="path30980"
+ sodipodi:nodetypes="csssccssscc" />
+ </g>
+ <g
+ id="layer11"
+ inkscape:label="cola3"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 213.28155,724.35663 c 1.31933,2.2684 3.06616,4.67929 7.8952,8.11759 5.15226,3.05071 10.30453,4.25128 15.45679,3.4472 -3.89287,-1.51625 -7.70178,-3.36833 -11.00879,-7.228 -4.65549,-4.19699 -3.58085,-7.57539 -4.448,-11.23119 z"
+ id="path40775"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 228.57154,708.45503 4.0588,5.6156 c 4.42518,4.67147 3.92725,4.15725 5.56,5.5044 4.59015,4.00912 10.45844,3.96209 16.0684,3.892 -3.57693,-2.13133 -9.02839,-4.26267 -10.7308,-6.394 -0.7713,-0.89985 -4.23439,-5.78656 -6.3384,-8.618 -1.12088,-1.50842 -3.3916,-4.5036 -3.3916,-4.5036 z"
+ id="path43167"
+ sodipodi:nodetypes="cccccscc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 242.24407,693.48199 c 1.31933,2.2684 3.06616,4.67929 7.8952,8.11759 5.15226,3.05071 10.30453,4.25128 15.45679,3.4472 -3.89287,-1.51625 -7.70178,-3.36833 -11.00879,-7.228 -4.65549,-4.19699 -3.58085,-7.57539 -4.448,-11.23119 z"
+ id="path40775-6"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:2.20844;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 255.92442,678.49794 c 0.76194,2.01697 1.84443,4.20907 5.23803,7.664 3.69756,3.18742 7.6251,4.88104 11.80188,4.95614 -2.41828,-1.84402 -5.67527,-3.8023 -7.8123,-7.38345 -3.16198,-4.04309 -1.89165,-6.61971 -2.1233,-9.6933 z"
+ id="path40775-3"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ <g
+ id="layer42"
+ inkscape:label="brazos"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 251.17189,538.75344 c -10.30848,7.4695 -21.90306,14.08159 -30.25013,22.85869 0.93037,8.39579 11.48929,15.65882 17.93107,23.40621 l 2.87445,15.05663 6.02265,7.93895 -3.8326,-27.78632 -9.03397,-12.31906 12.45593,-9.03397 z"
+ id="path106114"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <g
+ id="layer43"
+ inkscape:label="brazos 1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 229.81886,606.09762 -1.64254,-3.8326 c 0,0 5.02138,-4.18315 7.93894,-3.83259 4.98818,0.59936 11.63467,9.58149 11.63467,9.58149 l -0.27376,10.67651 c 0,0 -16.95316,1.72375 -24.36435,-1.64254 -2.34995,-1.06739 -4.90487,-2.95792 -5.47514,-5.47513 -1.05857,-4.67255 4.79074,-13.55097 4.79074,-13.55097 0,0 4.88203,-7.88988 8.21271,-6.70704 2.76577,0.98222 1.77942,8.62334 1.77942,8.62334"
+ id="path108592"
+ sodipodi:nodetypes="ccaccaacac" />
+ </g>
+ <g
+ id="layer44"
+ inkscape:label="brazos 2"
+ style="display:none;opacity:1">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.96038,558.17441 c 0,0 10.7989,2.96383 12.96955,7.45265 5.79413,11.98202 -5.90405,39.48936 -5.90405,39.48936 0,0 4.54276,2.00875 6.19441,3.77472 1.76439,1.88651 3.63847,4.28954 3.58115,6.87192 -0.0314,1.41627 -2.12933,3.67793 -2.12933,3.67793 l -6.19441,3.87151 -10.84022,-43.45766 z"
+ id="path109612"
+ sodipodi:nodetypes="cacaacccc" />
+ </g>
+ <g
+ id="layer34"
+ inkscape:label="bracitoplc">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 404.95955,523.81479 c 0,0 7.56997,8.77919 10.84022,13.55028 14.94151,21.79874 39.87651,68.52566 39.87651,68.52566 h 13.55028 l 9.09804,0.38715 c 0,0 7.39921,5.48435 7.35586,9.48519 -0.0333,3.07341 -5.80726,7.16228 -5.80726,7.16228 h -6.38799 l -3.67793,-4.45223 c 0,0 6.30824,4.95935 5.22654,7.93659 -0.69013,1.8995 -3.80845,2.04074 -5.80726,1.74218 -4.14173,-0.61864 -10.45307,-6.96871 -10.45307,-6.96871 l -10.64664,-8.13017 -32.32708,-38.32791 z"
+ id="path1012"
+ sodipodi:nodetypes="cacccacccaacccc" />
+ </g>
+ <g
+ id="layer1-0"
+ inkscape:label="cuerpo1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:5.91496;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 274.89137,499.14486 c 0,0 -12.68668,21.84593 -16.98413,33.65375 -5.48792,15.07878 -10.30664,30.83258 -11.00824,46.86363 -0.96332,22.01137 3.20928,44.28601 9.43563,65.42037 2.34659,7.96513 5.39306,16.00563 10.3792,22.64552 7.32006,9.7479 17.01388,17.99725 27.67784,23.90359 9.02196,4.9969 19.35356,7.67485 29.56498,9.12111 11.62794,1.64688 23.84306,2.2592 35.22635,-0.62904 8.81758,-2.23725 17.12692,-6.8826 24.21812,-12.58084 7.77455,-6.24736 13.87649,-14.51702 19.18579,-22.9 [...]
+ id="path948"
+ sodipodi:nodetypes="csssssssssssssccc" />
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="cuerpo2"
+ style="display:inline">
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#67464f;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.992157"
+ d="m 254.76202,547.89562 c 0,0 6.01284,-0.6026 9.12112,0.62904 5.46166,2.16415 11.75134,1.01913 17.61317,0.62904 4.98734,-0.33189 14.78249,-2.51617 14.78249,-2.51617 0,0 -5.50262,-3.48901 -8.17755,-5.34685 -2.03224,-1.41147 -4.23666,-2.64338 -5.97589,-4.4033 -2.90413,-2.93868 -5.53439,-6.29888 -7.23399,-10.06467 -1.54841,-3.43081 -1.57944,-7.36261 -2.51617,-11.00824 -0.56983,-2.21771 -1.88712,-6.60494 -1.88712,-6.60494 z"
+ id="path4530"
+ sodipodi:nodetypes="csscsssscc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 249.10065,603.56584 c 0,0 16.74071,-2.54379 24.53264,-5.66138 5.5423,-2.2175 10.58478,-5.60871 15.41153,-9.12111 4.86456,-3.53992 13.5244,-11.9518 13.5244,-11.9518 0,0 -5.45796,-0.18457 -8.17755,0 -4.64498,0.31525 -9.18421,1.79268 -13.83892,1.88713 -6.63346,0.1346 -13.58445,0.39398 -19.81482,-1.88713 -4.31495,-1.57982 -11.32276,-7.86302 -11.32276,-7.86302 l -2.83069,12.26632 z"
+ id="path8585"
+ sodipodi:nodetypes="csscsssccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#6b4852;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 398.34087,536.88738 c 0,0 -4.40524,8.31835 -8.3348,10.3792 -6.46951,3.39293 -21.85922,1.5726 -21.85922,1.5726 l 7.86303,9.59289 c 0,0 8.07129,2.72998 12.26632,2.83069 4.42008,0.10611 9.28625,-0.0431 13.05262,-2.35891 2.51854,-1.54854 5.14278,-4.12726 5.34686,-7.07672 0.39362,-5.68889 -8.33481,-14.93975 -8.33481,-14.93975 z m -33.49649,42.77486"
+ id="path11029"
+ sodipodi:nodetypes="csccsssc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#6b4953;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 410.44993,571.95648 5.81864,17.92769 c 0,0 -3.66745,1.821 -5.66138,2.04439 -6.77165,0.75866 -13.92872,-0.065 -20.2866,-2.51617 -4.42369,-1.70546 -11.63728,-8.17754 -11.63728,-8.17754 l 11.00823,-0.47179 c 0,0 9.85612,-0.66712 14.15345,-2.83069 2.6519,-1.33514 6.60494,-5.97589 6.60494,-5.97589 z"
+ id="path11483"
+ sodipodi:nodetypes="ccssccsc" />
+ </g>
+ <g
+ id="layer3"
+ inkscape:label="cuerpo3"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 339.60472,521.75027 -0.2224,71.39039 28.24479,25.35359 20.9056,-23.79679 c 0,0 1.15878,-20.29151 -0.4448,-30.2464 -1.53253,-9.51383 -8.6736,-27.57759 -8.6736,-27.57759 l -6.2272,-13.344 z"
+ id="path15367"
+ sodipodi:nodetypes="ccccsccc" />
+ </g>
+ <g
+ id="layer4"
+ inkscape:label="cuerpo4"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path17570-8"
+ sodipodi:type="arc"
+ sodipodi:cx="643.40137"
+ sodipodi:cy="363.7131"
+ sodipodi:rx="2.4238381"
+ sodipodi:ry="7.0955071"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 645.82521,363.7131 a 2.4238381,7.0955071 0 0 1 -2.38763,7.09472 2.4238381,7.0955071 0 0 1 -2.45897,-6.88273 2.4238381,7.0955071 0 0 1 2.31416,-7.30037 2.4238381,7.0955071 0 0 1 2.52811,6.66461 l -2.41951,0.42377 z"
+ transform="matrix(0.88968208,0.45658055,-0.54212471,0.84029804,0,0)" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path18346"
+ sodipodi:type="arc"
+ sodipodi:cx="383.65356"
+ sodipodi:cy="587.5553"
+ sodipodi:rx="1.4546597"
+ sodipodi:ry="1.3760295"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 385.10822,587.5553 a 1.4546597,1.3760295 0 0 1 -1.43292,1.37587 1.4546597,1.3760295 0 0 1 -1.47575,-1.33476 1.4546597,1.3760295 0 0 1 1.38884,-1.41576 1.4546597,1.3760295 0 0 1 1.51724,1.29247 l -1.45207,0.0822 z" />
+ </g>
+ <g
+ id="layer7"
+ inkscape:label="cuerpo5"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 291.89993,633.39505 c 0,0 3.89054,-1.12226 5.8936,-1.3344 3.17022,-0.33576 7.6637,-2.44906 9.5632,0.1112 0.71293,0.96093 -0.27054,2.49938 -1.0008,3.4472 -0.79147,1.02727 -2.05095,1.8274 -3.336,2.0016 -2.05856,0.27905 -6.0048,-1.668 -6.0048,-1.668 l -1.2232,-0.8896"
+ id="path22026"
+ sodipodi:nodetypes="csssscc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 277.44393,673.42704 c 0,0 0.96236,-3.33842 2.3352,-4.1144 1.25889,-0.71157 3.07074,-0.77887 4.5036,-0.5838 0.75716,0.10308 1.59414,0.64314 2.0572,1.251 0.94367,1.23875 0.34538,3.1816 -0.1112,4.6704 -0.54263,1.7694 -3.0024,4.6704 -3.0024,4.6704"
+ id="path22028"
+ sodipodi:nodetypes="cssssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 335.82392,667.42224 c 0,0 0.76468,-4.17048 2.1128,-5.6712 0.94161,-1.04819 2.40947,-1.56667 3.7808,-1.8904 1.98413,-0.46839 4.12867,-0.4546 6.116,0 1.16358,0.26617 2.97066,0.39053 3.2248,1.5568 0.35872,1.64617 -1.74518,3.08621 -3.2248,3.892 -1.37686,0.74983 -4.6704,0.556 -4.6704,0.556"
+ id="path22030"
+ sodipodi:nodetypes="csssssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 318.92152,681.21104 5.1152,-0.1112 c 0,0 1.84002,0.0173 2.0016,-0.6672 0.13248,-0.5612 -1.3344,-1.112 -1.3344,-1.112 l -3.2248,-1.112"
+ id="path22032"
+ sodipodi:nodetypes="ccscc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 380.41511,671.42544 8.2288,-4.448 c 0,0 2.08613,-0.60007 2.5576,0.1112 1.11458,1.68146 -0.9049,4.05547 -2.1128,5.6712 -0.44388,0.59375 -1.7792,1.3344 -1.7792,1.3344"
+ id="path22034"
+ sodipodi:nodetypes="ccssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 395.7607,615.60305 c 0,0 -0.76638,2.41373 0,3.1136 0.90696,0.82825 2.59389,0.25922 3.6696,-0.3336 1.22718,-0.6763 2.89206,-1.9753 2.5576,-3.336 -0.27313,-1.1112 -1.75804,-1.52103 -2.79908,-1.99601 -1.07172,-0.48898 -4.56151,0.0484 -4.56151,0.0484"
+ id="path22036"
+ sodipodi:nodetypes="cssssc" />
+ </g>
+ <g
+ id="layer5"
+ inkscape:label="cuerpo6"
+ style="display:inline">
+ <path
+ style="fill:#47353a;fill-opacity:1;stroke:#48353a;stroke-width:1.00476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 254.95538,649.80043 c 0,0 18.44089,3.8226 27.8543,4.71782 12.13083,1.15364 24.37576,0.90865 36.55876,0.62904 12.56559,-0.28839 25.19664,-0.16575 37.66662,-1.72987 9.51549,-1.19353 18.94306,-3.2207 28.17083,-5.81864 11.3354,-3.19131 33.23524,-11.9518 33.23524,-11.9518 l 3.16526,-24.21812 c 0,0 -5.37313,2.11683 -8.07141,3.14521 -8.41679,3.20784 -16.29513,7.11271 -24.68904,10.37919 -7.5347,2.93213 -15.28512,6.11555 -23.10642,8.17755 -14.45191,3.81009 -29.53062,5.2585 -44.471 [...]
+ id="path18608"
+ sodipodi:nodetypes="cssssccssssscccc" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:label="cuerpo7"
+ style="display:inline">
+ <rect
+ style="fill:#47353a;fill-opacity:1;stroke:#8f8381;stroke-width:6.67087;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect21069"
+ width="36.327179"
+ height="16.826874"
+ x="277.61121"
+ y="659.9422"
+ transform="rotate(-4.2348532)" />
+ </g>
+ <g
+ id="layer14"
+ inkscape:label="cabeza1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 217.0195,218.90663 -38.37156,-11.32276 c 0,0 -58.46937,0.0343 -67.93654,13.83893 -6.96054,10.14957 -1.00939,27.41604 3.14521,39.00061 5.34747,14.91071 26.73429,38.37156 26.73429,38.37156 l 12.26632,11.00823 c 0,0 -1.4636,16.46148 -3.14521,24.53264 -1.75948,8.44492 -7.23399,24.84716 -7.23399,24.84716 l -16.35509,18.55675 23.58908,7.5485 -35.54088,20.12934 44.97651,7.86303 -25.79073,12.89536 c 0,0 48.88224,30.62342 74.22696,44.34747 21.44031,11.60983 42.86475,23.62943 65.73 [...]
+ id="path57316"
+ sodipodi:nodetypes="ccssccsccccccsscccccccccsscccccssccssssscc" />
+ </g>
+ <g
+ id="layer36"
+ inkscape:label="SOMBRAS 3"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 155.53776,308.75262 c -2.62623,17.54433 -4.84338,37.94961 -11.32415,52.36212 l -13.84064,15.48602 c 0,0 26.42303,8.22696 25.26158,8.22696 -1.16145,0 -33.97247,19.26074 -33.97247,19.26074 l 45.4902,8.32374 -28.93951,14.13099 52.5557,31.55278 -16.77414,-15.94078 -14.48827,-14.93448 25.93909,-20.51898 c 0,0 -17.22335,1.62206 -24.19692,-2.51648 -3.03217,-1.79947 -6.21244,-5.19132 -6.00083,-8.71089 0.4856,-8.07682 16.06675,-18.19608 16.06675,-18.19608 0,0 -10.57214,-1.63693 -1 [...]
+ id="path65911"
+ sodipodi:nodetypes="cccscccccccaacaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 480.45392,261.32667 c -20.50896,7.18066 -48.63851,54.13462 -62.33125,87.10889 -8.68146,20.90633 -11.00017,44.34101 -11.22737,66.97706 -0.22256,22.17337 9.67877,65.8156 9.67877,65.8156 l 10.45306,1.5486 2.32291,7.35586 -2.32291,7.74302 -16.26032,10.06591 -11.22737,8.51732 -2.71005,5.42011 19.74468,-1.93576 8.51731,-9.29161 17.03463,-18.97038 -0.58072,-22.7451 c 0,0 8.48676,-5.08539 12.77596,-7.54944 10.30639,-5.9208 16.16505,-16.08504 22.26116,-25.8423 4.83237,-7.73455 16. [...]
+ id="path65913"
+ sodipodi:nodetypes="caacccccccccccsscccccccccccc" />
+ </g>
+ <g
+ id="layer15"
+ inkscape:label="ojjos 1"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 202.55154,385.28825 c 0,0 21.31315,24.22071 33.33923,34.91183 10.68757,9.50119 22.05463,18.37662 34.28279,25.79073 10.82678,6.56443 22.60415,11.46424 34.28279,16.35509 11.62446,4.86816 23.18495,10.41378 35.54087,12.89536 6.3803,1.28143 12.9973,1.19081 19.50031,0.94356 3.37856,-0.12846 7.12276,0.40814 10.06467,-1.25808 6.95287,-3.93793 10.95952,-11.85453 14.78249,-18.87126 5.52024,-10.13193 9.52298,-21.31327 11.32275,-32.71019 1.63567,-10.35778 0.15288,-20.99516 -0.62904,- [...]
+ id="path61200"
+ sodipodi:nodetypes="csssssssssssssssssc" />
+ </g>
+ <g
+ id="layer16"
+ inkscape:label="ojos2"
+ style="display:inline">
+ <path
+ style="fill:#744a54;fill-opacity:1;stroke:#744a54;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 269.22999,399.4417 c 0,0 4.78954,-16.35662 9.12111,-23.58908 3.5524,-5.93148 8.66074,-10.81211 13.52441,-15.72605 4.024,-4.0656 8.08471,-8.22771 12.89536,-11.32276 5.80107,-3.73227 12.06628,-7.36317 18.87126,-8.49207 5.50596,-0.9134 11.88204,0.48822 16.66961,1.57261 3.1747,0.71907 6.80808,0.46276 9.62921,-1.16114 1.83406,-1.05573 3.72411,-3.8021 4.30187,-5.83792 0.76057,-2.67998 -0.13185,-6.00728 -1.93576,-8.13017 -3.03403,-3.57053 -12.96954,-5.42011 -12.96954,-5.42011 0, [...]
+ id="path63630"
+ sodipodi:nodetypes="csssssssscssssssssssssccssssc" />
+ </g>
+ <g
+ id="layer17"
+ inkscape:label="ojos3"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 274.48979,398.95871 c 0,0 4.13955,-13.53875 7.74301,-19.5511 3.69512,-6.16529 8.67339,-11.55954 13.93742,-16.4539 5.61443,-5.22015 11.78528,-10.00631 18.58323,-13.55028 3.87217,-2.01868 8.03099,-3.20496 12.38882,-3.48435 4.47055,-0.28662 8.94731,0.42084 13.16312,1.93575 4.67217,1.6789 9.27383,3.88306 13.16313,6.96871 5.69678,4.51965 10.43724,10.30824 14.32457,16.4539 5.34455,8.44943 9.47328,17.81483 12.00167,27.4877 1.14796,4.39173 1.35502,13.55027 1.35502,13.55027 0,0 -6 [...]
+ id="path67428"
+ sodipodi:nodetypes="csssssssscsssssc" />
+ </g>
+ <g
+ id="layer18"
+ inkscape:label="ojos4"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 314.3663,350.17773 c -2.33914,1.61419 -4.73085,3.26325 -6.58156,5.42011 -3.61747,4.21589 -6.41804,9.18135 -8.51731,14.32458 -1.85701,4.5497 -2.78357,9.46071 -3.48436,14.32457 -0.58037,4.02809 -0.89055,8.13736 -0.58072,12.19524 0.37091,4.85783 2.90363,14.32458 2.90363,14.32458 0,0 1.44908,3.64045 2.41969,4.30705 0.84954,0.58346 12.02736,3.85876 18.34125,5.27492 5.96771,1.33852 11.80171,1.92363 17.76054,2.22612 5.54352,0.28141 15.97871,1.26633 21.9708,-0.19357 5.91594,-1.44 [...]
+ id="path70242"
+ sodipodi:nodetypes="ssssscssssscsssssssss" />
+ </g>
+ <g
+ id="layer19"
+ inkscape:label="ojos5"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:2.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 353.55558,353.9808 c 0,0 -4.55113,-0.32472 -6.28147,0.0684 -1.67452,0.38048 -4.20397,1.26512 -5.94615,2.91051 -1.74218,1.64539 -5.42224,4.70379 -7.7977,8.22007 -2.59931,3.84763 -4.20108,8.36707 -5.32332,12.87276 -1.30037,5.2209 -1.7468,10.69 -1.54861,16.06675 0.12661,3.43465 0.6825,6.89315 1.74218,10.1627 1.35237,4.1726 3.2043,8.27764 5.80726,11.8081 1.92315,2.60843 7.11389,6.92032 7.11389,6.92032 3.177,0.77776 6.67504,0.27133 10.01753,0.38714 3.85537,-0.17036 7.71075,-0. [...]
+ id="path78492"
+ sodipodi:nodetypes="csssssssccccsccccc" />
+ </g>
+ <g
+ id="layer20"
+ inkscape:label="ojos6"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path80803"
+ sodipodi:type="arc"
+ sodipodi:cx="341.92657"
+ sodipodi:cy="373.2132"
+ sodipodi:rx="5.347518"
+ sodipodi:ry="5.6136842"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 347.27409,373.2132 a 5.347518,5.6136842 0 0 1 -5.26763,5.61305 5.347518,5.6136842 0 0 1 -5.42502,-5.44534 5.347518,5.6136842 0 0 1 5.10554,-5.77576 5.347518,5.6136842 0 0 1 5.57757,5.27277 l -5.33798,0.33528 z" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 345.96747,382.04507 c -0.52605,-0.045 -0.91728,0.20181 -1.25824,0.60493 -0.32711,0.38674 -0.57973,0.90602 -0.48394,1.40341 0.11562,0.60036 0.41803,1.26055 0.94368,1.5728 0.49971,0.29684 1.2174,0.32248 1.74218,0.0726 0.46315,-0.22053 0.78564,-0.73883 0.91948,-1.23404 0.1313,-0.48582 0.11184,-1.08287 -0.16937,-1.50021 -0.35899,-0.53276 -1.05371,-0.86471 -1.69379,-0.91949 z"
+ id="path81104"
+ sodipodi:nodetypes="ssssssss" />
+ </g>
+ <g
+ id="layer21"
+ inkscape:label="ojos7"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 502.61754,353.96758 c 0,0 1.23515,-9.40721 0.27375,-13.9616 -1.20579,-5.71213 -3.84306,-11.24202 -7.39143,-15.8779 -4.13306,-5.39977 -9.53449,-10.07454 -15.60414,-13.14032 -6.28235,-3.17321 -13.49898,-4.64989 -20.53176,-4.92763 -5.26172,-0.2078 -10.8125,0.28 -15.60414,2.46382 -5.42213,2.47117 -10.07094,6.76236 -13.68784,11.49778 -4.75835,6.22987 -7.4632,13.8877 -9.85525,21.35303 -2.83428,8.84549 -4.10372,18.1523 -5.20138,27.37569 -1.3172,11.06813 -2.05038,22.25956 -1.6425 [...]
+ id="path84123"
+ sodipodi:nodetypes="cssssssssssccsssc" />
+ </g>
+ <g
+ id="layer22"
+ inkscape:label="ojos8"
+ style="display:inline">
+ <path
+ style="fill:#744a54;fill-opacity:1;stroke:#744a54;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 467.02915,310.714 c 0,0 -6.24469,0.99641 -8.76022,2.73757 -6.61529,4.57888 -14.85131,19.0261 -14.85131,19.0261 0,0 6.33033,-0.28027 9.30773,0.61595 5.8607,1.76412 11.3072,5.11014 15.94634,9.10242 4.18588,3.60222 7.80207,8.34958 10.26588,13.00344 2.46381,4.65387 4.31278,7.5869 5.33826,11.77155 0.98972,4.03874 1.18667,8.32814 0.68439,12.45593 -0.56484,4.64194 -1.21069,9.74233 -4.10635,13.41409 -4.78742,6.07056 -12.84614,8.80197 -19.98425,11.77154 -7.31589,3.04353 -15.22762, [...]
+ id="path87132"
+ sodipodi:nodetypes="cacaasaaaassssscaac" />
+ </g>
+ <g
+ id="layer23"
+ inkscape:label="ojos9"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.19753,340.00598 -7.39143,66.79667 c 0,0 9.0644,0.38848 13.55096,-0.13688 9.01468,-1.05559 18.10479,-2.70863 26.55441,-6.02265 6.87021,-2.69456 19.16298,-11.08715 19.16298,-11.08715 0,0 2.14811,-8.97556 2.19005,-13.55097 0.0414,-4.51657 -0.35645,-9.17521 -1.91629,-13.41408 -2.83271,-7.6979 -7.10724,-15.24819 -13.14033,-20.80552 -3.40731,-3.13862 -7.84064,-5.24818 -12.31906,-6.43329 -3.66335,-0.96942 -7.60932,-0.94494 -11.36091,-0.41063 -5.32799,0.75882 -15.33038,5.0645 [...]
+ id="path92268"
+ sodipodi:nodetypes="ccaacaaaaac" />
+ </g>
+ <g
+ id="layer24"
+ inkscape:label="ojos10"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.47129,339.73222 26.82817,62.55344 c 8.51952,-3.52914 12.42628,-5.36693 15.5357,-6.91236 l 2.39537,-11.97686 c 1.66485,-8.14938 2.74407,-14.1317 -0.61595,-26.07534 -0.48453,-2.7093 -3.97116,-11.17671 -5.88577,-13.41409 -3.35252,-3.79435 -7.44261,-6.87827 -13.34565,-8.48646 l -7.93895,-0.75283 z"
+ id="path95549"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <g
+ id="layer25"
+ inkscape:label="ojos11"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 426.94726,339.56284 -6.45677,56.97393 c 0,0 1.14877,4.63212 2.53225,6.50172 1.27054,1.71698 5.03029,3.96948 5.03029,3.96948 3.5926,0.125 7.90171,-0.19696 11.12136,-0.78705 4.01508,-0.77266 9.69122,-2.02184 14.4749,-3.28509 0.61056,-0.16123 1.81363,-0.54751 1.81363,-0.54751 0,0 4.30506,-5.7163 5.81734,-8.93132 2.02395,-4.30279 3.36692,-8.94581 4.24323,-13.6194 0.79648,-4.24783 1.24029,-8.6274 0.88971,-12.93501 -0.25855,-3.1768 -1.06849,-6.32428 -2.19006,-9.30773 -1.76325,- [...]
+ id="path99061"
+ sodipodi:nodetypes="ccaccacaaaaaaaac" />
+ </g>
+ <g
+ id="layer26"
+ inkscape:label="ojos12"
+ style="display:inline">
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path80803-0"
+ sodipodi:type="arc"
+ sodipodi:cx="433.45966"
+ sodipodi:cy="364.8652"
+ sodipodi:rx="3.9689827"
+ sodipodi:ry="4.0279403"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 437.42864,364.8652 a 3.9689827,4.0279403 0 0 1 -3.90969,4.02749 3.9689827,4.0279403 0 0 1 -4.02651,-3.90715 3.9689827,4.0279403 0 0 1 3.78939,-4.14423 3.9689827,4.0279403 0 0 1 4.13972,3.78333 l -3.96189,0.24056 z"
+ inkscape:transform-center-x="5.6407799"
+ inkscape:transform-center-y="0.9722915" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.685875px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.15746,373.80187 c -0.36481,-0.0305 -0.63612,0.13689 -0.87257,0.41035 -0.22685,0.26234 -0.40204,0.6146 -0.33561,0.952 0.0802,0.40725 0.2899,0.85509 0.65443,1.06691 0.34654,0.20136 0.84425,0.21875 1.20818,0.0492 0.32119,-0.1496 0.54483,-0.50119 0.63764,-0.83711 0.0911,-0.32956 0.0776,-0.73457 -0.11745,-1.01767 -0.24896,-0.3614 -0.73073,-0.58657 -1.17462,-0.62373 z"
+ id="path81104-5"
+ sodipodi:nodetypes="ssssssss" />
+ </g>
+ <g
+ id="layer10"
+ inkscape:label="nariz4"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 437.09305,464.77432 6.19441,12.77597 -1.35503,17.03463 -18.97038,17.2282 -4.06508,6.38798 -13.47938,5.16188 -7.86302,-0.31452 -9.12111,-13.83893 -3.21859,-31.85282 19.74468,-13.55027 z"
+ id="path944" />
+ </g>
+ <g
+ id="layer29"
+ inkscape:label="nariz3"
+ style="display:inline">
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 398.72682,507.13452 5.84558,-4.80659 1.03256,-3.50877 14.44067,-2.70335 c 0,0 -0.65017,2.29272 -0.51329,2.29272 0.13688,0 2.7522,1.30613 2.7522,1.30613 l -3.36815,2.04739 -13.55097,4.41433 -6.57016,1.5741 z"
+ id="path121669" />
+ </g>
+ <g
+ id="layer27"
+ inkscape:label="nariz1"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 330.43305,494.19777 16.4539,15.29244 c 0,0 10.35541,11.75749 17.42178,14.32458 6.91404,2.51175 14.87381,1.73059 22.06759,0.19357 4.99773,-1.06782 13.93742,-6.38798 13.93742,-6.38798 l 4.64581,-6.38799"
+ id="path103332"
+ sodipodi:nodetypes="ccaacc" />
+ <path
+ style="fill:none;stroke:#684650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 410.76681,511.42597 12.19524,0.38715 c 0,0 7.71212,-4.99359 11.03379,-8.13016 2.49884,-2.35959 5.00722,-4.88155 6.58156,-7.93659 1.49843,-2.90773 2.21151,-6.22833 2.51648,-9.48519 0.33174,-3.54276 -0.0128,-7.17083 -0.7743,-10.64664 -0.58994,-2.69265 -2.90363,-7.74302 -2.90363,-7.74302 l -2.3229,-3.0972"
+ id="path103334"
+ sodipodi:nodetypes="ccaaaacc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 392.18358,521.49188 c 0,0 9.02373,1.69497 13.55027,1.35503 3.38647,-0.25432 6.98431,-0.72983 9.87234,-2.51648 3.19022,-1.9736 7.35586,-8.51731 7.35586,-8.51731"
+ id="path103336"
+ sodipodi:nodetypes="caac" />
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 397.21654,500.68254 c 0,0 1.56844,-2.31284 2.80684,-2.71006 1.67703,-0.53792 4.20555,-0.66075 5.22653,0.77431 0.70428,0.98992 -0.67751,3.58114 -0.67751,3.58114 l -6.96871,5.42011 c 0,0 -7.10496,0.97495 -9.29162,-1.25824 -2.58985,-2.64496 -2.18162,-7.44905 -1.25824,-11.0338 0.75029,-2.91278 2.86558,-5.49222 5.22653,-7.35586 3.24944,-2.56498 7.3859,-4.38916 11.51774,-4.6458 1.63241,-0.10139 3.1146,1.41541 4.74259,1.25824 2.42726,-0.23433 4.15668,-2.93618 6.58156,-3.194 3.10 [...]
+ id="path103338"
+ sodipodi:nodetypes="caaccaaaaaaaaccacc" />
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#67464f;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 397.60369,507.74804 c 0,0 3.22164,1.4085 4.93617,1.45181 2.48761,0.0628 5.10779,-0.49153 7.25907,-1.74218 1.22343,-0.71124 2.90363,-3.0972 2.90363,-3.0972 0,0 0.33123,2.3459 1.25824,2.71005 1.58926,0.62429 3.42269,-0.85254 4.74259,-1.93575 1.67391,-1.37374 3.58115,-5.42011 3.58115,-5.42011 v 0"
+ id="path103340"
+ sodipodi:nodetypes="caacaacc" />
+ </g>
+ <g
+ id="layer37"
+ inkscape:label="sombra5"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#dad2d1;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.69422,513.43431 8.42052,0.29037 c -0.89939,1.28114 -1.55467,3.28485 -6.17021,5.80726 -6.91095,1.97763 -10.46171,1.62023 -13.62286,0.99207 l 2.3229,-1.33083 4.98457,-6.79933 5.81974,-6.8762 0.39353,1.12069 c 0.37206,0.43706 0.38352,1.01034 1.71098,1.08647 2.01068,-0.18971 2.20166,-0.657 2.9771,-1.03514 0,0 1.51372,-1.1186 2.13873,-1.81364 0.90858,-1.01039 1.60235,-2.20024 2.29271,-3.37063 1.05872,-1.79486 2.82312,-5.57779 2.82312,-5.57779 0,0 1.21845,-0.77832 1.77942,- [...]
+ id="path78067"
+ sodipodi:nodetypes="ccccccccccaacaaaaaaaaaaaaaaaccccccccccc"
+ clip-path="url(#clipPath81911)" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 412.26067,462.13575 2.66801,18.91099 1.45181,-0.12098 c 0,0 1.5728,0.0726 1.63329,0.0726 0.0605,0 1.45182,0.18148 1.50021,0.18148 0.0484,0 0.7864,0.18147 0.7864,0.18147 l 1.597,0.49604 0.87109,0.41135 0.83479,0.43554 0.7864,0.54443 0.84689,0.68962 1.42762,1.47601 1.19775,1.69378 0.67751,1.50021 0.39925,1.70588 v 1.04047 l -0.18148,0.7985 -0.38715,0.738 -0.7259,0.87109 -0.93158,0.8106 -1.34293,0.94368 -0.5846,0.41111 -2.65779,5.22677 -1.17355,2.00834 -1.00417,1.39133 -0.66 [...]
+ id="path82108"
+ sodipodi:nodetypes="cccssccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+ </g>
+ <g
+ id="layer28"
+ inkscape:label="nariz2"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#684650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 426.39801,475.54195 c -0.75398,0.59916 -1.35987,1.76916 -1.06466,2.68585 0.4259,1.32251 2.13044,2.42705 3.50855,2.25032 1.5569,-0.19965 3.24382,-1.8913 3.19399,-3.46016 -0.0308,-0.96934 -1.1804,-1.71605 -2.10513,-2.00835 -1.1355,-0.35893 -2.60041,-0.20856 -3.53275,0.53234 z"
+ id="path103438"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#67464f;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.992157"
+ d="m 430.82605,486.45475 c -0.65127,0.89445 -0.76426,2.38207 -0.16938,3.31498 0.61281,0.96104 2.06309,1.5551 3.1698,1.28244 0.94459,-0.23272 1.55756,-1.31089 1.88736,-2.22612 0.47581,-1.3204 1.11149,-3.42001 -0.0484,-4.21026 -1.42613,-0.97165 -3.82362,0.44391 -4.83938,1.83896 z"
+ id="path103440"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694750;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 369.92242,501.94078 c -1.74253,0.11096 -3.65435,0.98243 -4.64581,2.41969 -0.94074,1.36374 -1.53205,3.57979 -0.58073,4.93617 1.5413,2.19757 5.2778,2.63962 7.8398,1.83896 1.28636,-0.40201 2.59478,-1.65764 2.71006,-3.00041 0.18604,-2.16706 -1.79343,-4.14886 -3.48436,-5.5169 -0.50786,-0.41089 -1.18702,-0.71902 -1.83896,-0.67751 z"
+ id="path103342"
+ sodipodi:nodetypes="aaaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 370.74511,482.34128 c -1.06402,0.75907 -1.98064,2.33168 -1.59699,3.58114 0.32323,1.05268 1.70828,1.66608 2.80684,1.74218 1.549,0.1073 3.78147,-0.40979 4.25865,-1.88736 0.44213,-1.36905 -0.89961,-3.06587 -2.17772,-3.72633 -0.97829,-0.50553 -2.39433,-0.34916 -3.29078,0.29037 z"
+ id="path103388"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.64582,486.0676 c -0.36057,1.41343 1.2673,3.22088 2.71005,3.43596 1.39859,0.2085 3.28975,-1.0191 3.48436,-2.41969 0.1609,-1.15792 -1.09054,-2.43233 -2.22612,-2.71005 -1.39705,-0.34166 -3.61279,0.30019 -3.96829,1.69378 z"
+ id="path103390"
+ sodipodi:nodetypes="aaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.06308,514.48996 c 0,0 0.92034,-2.35683 1.98414,-2.66166 1.36499,-0.39114 3.41207,0.24216 3.9683,1.5486 0.44477,1.04465 -0.58195,2.27156 -1.30664,3.1456 -0.35696,0.43053 -1.40342,0.91948 -1.40342,0.91948"
+ id="path103392"
+ sodipodi:nodetypes="caaac" />
+ </g>
+ <g
+ id="layer31"
+ inkscape:label="SOMBRAS"
+ style="display:inline">
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 547.81813,821.92077 -14.71173,6.58156 c 0,0 -20.04642,9.4511 -20.13183,18.58323 -0.0401,4.28964 9.8648,4.6531 9.29162,8.90446 -1.22993,9.12259 -40.07226,7.0871 -40.65082,18.58323 -0.23206,4.6112 16.368,3.85278 12.38882,6.19441 -8.7326,5.13888 -115.3747,51.08568 -115.37088,51.10388 22.3368,-2.2537 41.71738,-14.30148 55.55041,-19.96007 11.32914,-1.74424 22.65827,-2.80865 33.98741,-5.52947 14.55542,-1.8339 26.06489,-10.97808 38.99618,-16.70988 18.06089,-13.95357 25.08208,-25 [...]
+ id="path949"
+ sodipodi:nodetypes="ccassscccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 445.3366,835.93267 c 0,0 -16.17886,14.32145 -25.27818,20.05735 -15.42858,9.72566 -49.16813,24.00334 -49.16813,24.00334 -4.44886,2.75522 -5.38193,1.67502 -5.87368,0.11339 l -7.23844,-6.64798 c 18.35192,-6.49248 36.75539,-13.2943 55.46787,-21.95016 z"
+ id="path951"
+ sodipodi:nodetypes="caccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 272.35476,872.90958 c 0,0 0.57084,7.71915 0.10249,11.53601 -0.2354,1.91841 -1.45182,5.61369 -1.45182,5.61369 l 25.1648,1.88735 c 0.47994,-2.9835 0.36177,-4.37206 0.49764,-6.43805 -0.55144,-2.5936 -1.0986,-5.18806 -2.27941,-7.65579 0,0 -5.84602,-0.64508 -8.71988,-1.24687 -4.50803,-0.94399 -13.31382,-3.69634 -13.31382,-3.69634 z"
+ id="path953"
+ sodipodi:nodetypes="caccccac" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 226.28954,815.53279 c 0,0 -7.95288,2.68162 -12.00168,3.7747 -3.38519,0.91392 -10.25948,2.32291 -10.25948,2.32291 0,0 1.3589,13.85165 3.48435,20.4222 1.2834,3.96745 5.5169,11.22737 5.5169,11.22737 5.56183,-2.04316 6.86738,-4.39034 9.00125,-6.67835 3.87527,-4.01314 6.35463,-11.0035 9.00125,-17.2282 z"
+ id="path955"
+ sodipodi:nodetypes="cacacccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 220.99255,764.33128 -8.78502,16.50455 c 2.97496,0.55016 6.51461,0.25328 10.21418,-0.28348 2.48336,-0.80195 1.67568,-0.38328 9.9428,-3.33373 l 6.71642,-12.83266 -8.92023,0.16037 z"
+ id="path957"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <g
+ id="layer32"
+ inkscape:label="SOMBRAS 1"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 298.02413,877.42421 c 2.73354,7.81873 1.97618,9.48503 2.11154,13.52964 l 35.91107,-2.05603 25.81194,-4.66526 c -2.00278,-2.61499 -5.49159,-5.52718 -9.30134,-8.50356 l -23.63967,3.7249 z"
+ id="path960"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 232.36854,834.45015 c -1.72206,4.96881 -3.87893,9.57529 -6.69495,13.63246 -2.98321,3.45811 -6.32185,6.34751 -10.21656,8.34723 0,0 7.00444,12.3255 12.18753,16.98196 6.62044,5.94777 14.88148,10.07695 23.22904,13.16312 5.05634,1.86938 15.87318,3.0972 15.87318,3.0972 1.94325,-2.09404 3.81964,-10.11169 1.67265,-19.47249 -5.17626,-1.71992 -8.96515,-3.76359 -15.4165,-9.5638 z"
+ id="path962"
+ sodipodi:nodetypes="cccaacccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 210.58644,784.48054 c 0,0 -4.33631,9.886 -5.54524,15.11465 -1.37844,5.96186 -1.88391,18.2605 -1.88391,18.2605 3.64141,0.81129 13.27584,-3.06759 20.71256,-5.22654 0,0 -0.53922,-8.93795 0.1721,-13.32147 0.97292,-5.99566 5.53836,-17.36022 5.53836,-17.36022 0,0 -6.69889,2.0907 -10.1627,2.51648 -2.92174,0.35915 -8.83117,0.0166 -8.83117,0.0166 z"
+ id="path964"
+ sodipodi:nodetypes="caccacac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 222.12767,760.75097 c 2.04496,0.68598 14.10806,0.16978 21.88374,0.16808 35.976,-34.5304 40.26607,-47.39531 50.90058,-65.11259 -10.98778,-6.04029 -18.83771,-12.86789 -24.97123,-19.16397 0,0 5.48103,10.16148 4.93618,15.58282 -1.5279,15.20293 -12.85105,28.0321 -22.26116,40.07009 -8.56139,10.95226 -30.48811,28.45557 -30.48811,28.45557 z"
+ id="path966"
+ sodipodi:nodetypes="ccccaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 320.27035,703.64625 c 0,0 11.9013,8.35426 14.61494,14.71173 4.09221,9.58716 0.7743,31.26241 0.7743,31.26241 0,0 2.56105,-10.59133 3.38757,-15.96996 1.43253,-9.32234 2.71005,-28.16521 2.71005,-28.16521 -7.31232,-0.0128 -14.43105,-0.80008 -21.48686,-1.83897 z"
+ id="path968"
+ sodipodi:nodetypes="cacacc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.50064,704.8077 5.90405,48.10347 c 0,0 -0.49128,-14.99406 0.67751,-22.35795 1.11707,-7.03805 2.1625,-14.51487 6.00083,-20.51898 2.90655,-4.54658 7.55844,-7.88631 12.19525,-10.64664 2.5438,-1.51434 8.32374,-3.09721 8.32374,-3.09721 1.71361,-2.54812 2.03574,-5.32816 2.22611,-8.13016 0,0 -10.62032,8.20645 -16.64747,11.03379 -5.88629,2.76125 -18.68002,5.61368 -18.68002,5.61368 z"
+ id="path1083"
+ sodipodi:nodetypes="ccaaaccac" />
+ </g>
+ <g
+ id="layer33"
+ inkscape:label="SOMBRAS 2"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 311.69279,694.98153 c 0,0 21.20519,4.69219 31.9133,4.0926 8.86972,-0.49666 17.88896,-2.46095 25.89066,-6.31989 7.44831,-3.59207 13.96971,-9.14786 19.60849,-15.19636 7.11032,-7.62698 12.69856,-16.69142 17.38356,-26.0069 1.90749,-3.79279 4.28047,-11.99548 4.28047,-11.99548 0,0 -10.47172,4.15202 -15.81432,5.92586 -5.7265,1.9013 -17.38356,5.04789 -17.38356,5.04789 0,0 -3.26415,8.74334 -6.08337,12.37291 -7.32531,9.43088 -16.67786,17.69547 -27.23881,23.26933 -9.94266,5.24753 -3 [...]
+ id="path37537"
+ sodipodi:nodetypes="caaaacacaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 315.02567,516.1685 c 0,0 8.11408,7.52388 11.63467,11.77154 3.8928,4.69674 10.40275,15.05663 10.40275,15.05663 l 0.13689,-19.09454 c -7.39144,-2.48908 -14.78288,-4.89781 -22.17431,-7.73363 z"
+ id="path37541"
+ sodipodi:nodetypes="caccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 396.60521,531.49889 0.65016,2.05317 c -0.50841,1.64487 -1.38541,3.23708 -2.53224,4.79074 -1.27909,1.80275 -2.59144,3.6166 -4.14057,5.50936 -3.42223,2.80405 -3.85636,2.02238 -5.16716,2.29271 -3.92172,-11.13692 -3.3389,-8.6049 -4.89341,-12.55859 l 6.09109,2.87445 z"
+ id="path37788"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 387.05794,550.69608 c 5.24841,-0.82446 8.96129,-4.92956 11.66889,-9.64993 3.16683,3.47899 4.59204,7.02643 6.57016,10.50542 -1.83514,2.1826 -3.46722,4.59796 -5.64624,5.7489 -4.67848,2.29176 -7.33873,1.6093 -10.36853,1.47144 -0.61183,-2.95115 -1.43945,-5.47069 -2.22428,-8.07583 z"
+ id="path37790"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 390.52954,563.38467 c 2.56922,-0.0156 5.13266,-0.0269 8.70898,-0.79778 2.48973,-0.6753 4.1443,-2.3528 6.03498,-3.74696 l 3.51875,12.25975 c -2.74256,2.86412 -5.43184,5.58839 -7.1618,5.79445 -3.13945,0.87612 -6.28817,1.74297 -10.18427,1.86244 -0.12873,-10.02199 -0.57481,-11.37611 -0.91664,-15.3719 z"
+ id="path37792"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 391.30116,587.75591 c 3.51978,1.44667 7.46595,2.19057 12.07952,2.36115 3.84475,0.13634 7.83163,0.52185 10.60809,-1.30034 l -4.1748,-13.68784 c 0,0 -5.03409,3.74951 -7.80207,5.20138 -0.79345,0.41618 -1.63058,0.76807 -2.49803,0.99237 -2.68337,0.69386 -8.24692,1.0608 -8.24692,1.0608 z"
+ id="path37794"
+ sodipodi:nodetypes="ccccaacc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:0.996364;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 391.30117,591.79383 c 0,0 -0.78111,10.57858 -0.95815,15.87788 -0.17521,5.2442 -0.10266,15.74103 -0.10266,15.74103 l 25.80158,-10.4712 c 0,0 0.68403,-7.53051 0.47908,-11.29247 -0.16885,-3.0992 -1.40301,-9.20507 -1.40301,-9.20507 0,0 -2.47918,1.04873 -3.79837,1.19769 -6.1974,0.69982 -18.64969,-1.50567 -18.64969,-1.50567 z"
+ id="path37796"
+ sodipodi:nodetypes="caccacasc" />
+ </g>
+ <g
+ id="layer38"
+ inkscape:label="SOMBRAS 4"
+ style="display:inline">
+ <path
+ style="fill:#908482;fill-opacity:1;stroke:#908482;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 174.79851,270.03756 17.80892,-21.68044 -11.03379,-6.19441 -19.74468,-0.19357 c 0,0 8.05542,8.61931 10.36719,13.92401 1.91521,4.39475 2.60236,14.14441 2.60236,14.14441 z"
+ id="path84668"
+ sodipodi:nodetypes="ccccac" />
+ <path
+ style="fill:#908482;fill-opacity:1;stroke:#908482;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 491.94102,223.45401 9.64993,-7.25455 9.78681,-1.23191 -3.90104,27.581 -5.0645,-4.51699 -10.40276,-14.23535 z"
+ id="path84798" />
+ </g>
+ <g
+ id="layer39"
+ inkscape:label="orejas"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 195.39394,245.83363 c 0,0 -3.45588,-4.19123 -5.7489,-5.54357 -2.13818,-1.26102 -4.66627,-1.79943 -7.11768,-2.19005 -2.56868,-0.40932 -5.20686,-0.31168 -7.80207,-0.13688 -2.85536,0.19231 -5.66572,0.81707 -8.48646,1.30034 -3.50152,0.59991 -10.47119,1.98474 -10.47119,1.98474 l -10.40276,2.12161 c -0.81574,0.68439 -1.30941,1.36879 0.75283,2.05318 v 0 l 8.07582,-0.0684 13.00345,0.13684 c 0,0 5.16735,-0.31374 7.73363,-0.0685 2.17787,0.20818 4.41163,0.46408 6.43329,1.30035 1.946 [...]
+ id="path87054"
+ sodipodi:nodetypes="caaaaccccccaaasaacscccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 487.49247,220.16893 21.14772,-6.6386 7.04924,-1.9163 c 0,0 0.34428,6.95974 -0.0684,10.40275 -0.50773,4.23597 -1.40696,8.47572 -2.94289,12.45594 -1.25722,3.25796 -5.0645,9.17086 -5.0645,9.17086 l -0.20532,0.88971 4.38011,10.40276 c 0,0 0.27376,2.66913 0,2.73757 -0.27375,0.0684 -5.47513,-1.43723 -5.47513,-1.43723 l 0.0684,-3.28508 -5.68045,-18.34171 4.85918,6.84392 0.61596,-0.13688 4.10635,-18.41014 c 0,0 1.47984,-5.02104 -0.0684,-6.57017 -1.46762,-1.46845 -4.20331,-0.52774 [...]
+ id="path92311"
+ sodipodi:nodetypes="cccaacccsccccccaaaacc" />
+ </g>
+ <g
+ id="layer30"
+ inkscape:label="casco1"
+ style="display:inline">
+ <path
+ style="fill:#ffe300;fill-opacity:0.996078;stroke:#694650;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 144.79433,311.2691 439.41595,-26.7134 -30.97204,-7.74301 -28.262,-11.61451 c -14.77268,-6.07097 -33.64256,-17.60462 -41.03797,-33.68211 -5.07051,-11.0232 0.14051,-24.43766 0.77431,-36.39216 0.49741,-9.38182 -5.60961,-18.05537 -10.06592,-26.32624 -7.23676,-13.43137 -15.48728,-26.83463 -26.71339,-37.16646 -8.5558,-7.87423 -30.24588,-8.00899 -42.58657,-17.03463 -8.36237,-6.116 -11.35719,-17.921827 -19.74468,-24.003335 -11.77674,-8.538948 -26.13513,-14.92456 -40.65082,-15.873 [...]
+ id="path1910"
+ sodipodi:nodetypes="cccsasasaaaacaaccaac" />
+ </g>
+ <g
+ id="layer40"
+ inkscape:label="casco2"
+ style="display:inline">
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#ccb500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 257.33142,117.37324 c 0,0 14.66769,-3.34433 21.83211,-1.9163 11.50806,2.29381 31.20828,16.28853 31.20828,16.28853 -7.95406,-11.30046 -14.11739,-19.76237 -22.23496,-30.4088 -3.0627,1.22517 -10.9099,4.15792 -10.82118,4.4019 -0.36669,-0.45836 -13.96143,6.97356 -19.98425,11.63467 z"
+ id="path94173"
+ sodipodi:nodetypes="cacccc" />
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#ccb500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 410.77212,118.81046 c 0,0 8.43736,17.37195 11.77155,26.41754 3.44769,9.35353 6.18704,18.45001 9.03397,27.10192 2.73472,8.31091 7.39144,25.18563 7.39144,25.18563 0,0 -1.64913,-34.41237 -5.20138,-51.19252 -1.03392,-4.88403 -2.39479,-9.78348 -4.65387,-14.23536 -0.81364,-1.60341 -3.1482,-4.38011 -3.1482,-4.38011 z"
+ id="path94175"
+ sodipodi:nodetypes="csscaacc" />
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#cbb400;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 334.66772,259.11084 114.1566,-6.9808 c -19.16051,-2.69367 -30.65772,-5.90983 -57.55737,-8.07583 -21.52187,3.24857 -37.73931,10.03343 -56.59923,15.05663 z"
+ id="path94177"
+ sodipodi:nodetypes="cccc" />
+ </g>
+ <g
+ id="layer41"
+ inkscape:label="casco3"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 304.28072,264.85973 164.66473,-10.95027 -75.55689,-0.82127 z"
+ id="path94180" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 286.87072,99.523031 21.20439,28.623829 26.42303,26.81018 -23.32583,-29.52024 z"
+ id="path94182"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 381.34336,95.819779 c 0,0 8.10743,9.275991 11.61452,14.324571 5.94104,8.55232 10.85071,17.78486 15.87317,26.90697 5.59522,10.16239 15.87318,30.97205 15.87318,30.97205 l 16.64748,37.55361 c 0,0 -3.51333,-11.34761 -5.22654,-17.03463 -3.61001,-11.98342 -6.33752,-24.25485 -10.64664,-36.00501 -4.9536,-13.50755 -17.42178,-39.48936 -17.42178,-39.48936 L 397.99084,98.916983 Z"
+ id="path94184"
+ sodipodi:nodetypes="caaccaaccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 368.06606,84.180225 c 0,0 6.39675,3.886923 9.10241,6.433285 1.61991,1.524537 4.17489,5.206269 4.17489,5.206269 l 16.64748,3.097204 -8.77707,-10.082892 -13.89316,-8.897097 z"
+ id="path94186"
+ sodipodi:nodetypes="caccccc" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/pom.xml
new file mode 100644
index 0000000000..3f95f27e84
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-assemblies</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>plc4x-hop-assemblies-action</artifactId>
+ <packaging>pom</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Assemblies: Action</name>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-action</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${maven-assembly-plugin.version}</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>assembly</id>
+ <activation>
+ <file>
+ <exists>${basedir}/src/assembly/assembly.xml</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assembly_package</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorSourceDirectory>${basedir}/src/assembly</descriptorSourceDirectory>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/assembly/assembly.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/assembly/assembly.xml
new file mode 100644
index 0000000000..84529d10ba
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/assembly/assembly.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+
+ <id>plc4x-plugin-assemblies-action</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>plugins/actions/plc4x</baseDirectory>
+ <files>
+ <file>
+ <source>${project.basedir}/src/main/resources/version.xml</source>
+ <outputDirectory>.</outputDirectory>
+ <filtered>true</filtered>
+ </file>
+ </files>
+ <fileSets>
+ <fileSet>
+ <outputDirectory>lib</outputDirectory>
+ <excludes>
+ <exclude>**/*</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>false</useProjectArtifact>
+ <includes>
+ <include>org.apache.plc4x:plc4x-hop-action:jar</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+</assembly>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/main/resources/version.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/main/resources/version.xml
new file mode 100644
index 0000000000..2703899672
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-action/src/main/resources/version.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<version>${project.version}</version>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/pom.xml
new file mode 100644
index 0000000000..290099015a
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-assemblies</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4x-hop-assemblies-metadata</artifactId>
+ <packaging>pom</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Assemblies: Metadata</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-metadata</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${maven-assembly-plugin.version}</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>assembly</id>
+ <activation>
+ <file>
+ <exists>${basedir}/src/assembly/assembly.xml</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assembly_package</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorSourceDirectory>${basedir}/src/assembly</descriptorSourceDirectory>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/assembly/assembly.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/assembly/assembly.xml
new file mode 100644
index 0000000000..c79e513518
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/assembly/assembly.xml
@@ -0,0 +1,69 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+
+ <id>plc4x-plugin-assemblies-metadata</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>plugins/metadata/plc4x</baseDirectory>
+ <files>
+ <file>
+ <source>${project.basedir}/src/main/resources/version.xml</source>
+ <outputDirectory>.</outputDirectory>
+ <filtered>true</filtered>
+ </file>
+ </files>
+ <fileSets>
+ <fileSet>
+ <outputDirectory>lib</outputDirectory>
+ <excludes>
+ <exclude>**/*</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>false</useProjectArtifact>
+ <includes>
+ <include>org.apache.plc4x:plc4x-hop-metadata:jar</include>
+ </includes>
+ </dependencySet>
+
+ <dependencySet>
+ <outputDirectory>lib</outputDirectory>
+ <useProjectArtifact>false</useProjectArtifact>
+ <useTransitiveDependencies>true</useTransitiveDependencies>
+ <scope>runtime</scope>
+ <includes>
+ <include>com.github.jinahya:bit-io:jar</include>
+ <include>ch.qos.logback:logback-core</include>
+ <include>io.netty:netty-buffer</include>
+ <include>io.netty:netty-codec:jar</include>
+ <include>io.netty:netty-common:jar</include>
+ <include>io.netty:netty-resolver:jar</include>
+ <include>io.netty:netty-transport</include>
+ </includes>
+ </dependencySet>
+
+ </dependencySets>
+</assembly>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/main/resources/version.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/main/resources/version.xml
new file mode 100644
index 0000000000..2703899672
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-metadata/src/main/resources/version.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<version>${project.version}</version>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/pom.xml
new file mode 100644
index 0000000000..66253b8596
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-assemblies</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>plc4x-hop-assemblies-transform</artifactId>
+ <packaging>pom</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Assemblies: Transform</name>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-hop-transform</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${maven-assembly-plugin.version}</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>assembly</id>
+ <activation>
+ <file>
+ <exists>${basedir}/src/assembly/assembly.xml</exists>
+ </file>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assembly_package</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorSourceDirectory>${basedir}/src/assembly</descriptorSourceDirectory>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/assembly/assembly.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/assembly/assembly.xml
new file mode 100644
index 0000000000..3321a4ce6f
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/assembly/assembly.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+
+ <id>plc4x-plugin-assemblies-transform</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>plugins/transforms/plc4x</baseDirectory>
+ <files>
+ <file>
+ <source>${project.basedir}/src/main/resources/version.xml</source>
+ <outputDirectory>.</outputDirectory>
+ <filtered>true</filtered>
+ </file>
+ </files>
+ <fileSets>
+ <fileSet>
+ <outputDirectory>lib</outputDirectory>
+ <excludes>
+ <exclude>**/*</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>false</useProjectArtifact>
+ <includes>
+ <include>org.apache.plc4x:plc4x-hop-transform:jar</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+</assembly>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/main/resources/version.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/main/resources/version.xml
new file mode 100644
index 0000000000..2703899672
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/plc4x-hop-assemblies-transform/src/main/resources/version.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<version>${project.version}</version>
\ No newline at end of file
diff --git a/plc4j/integrations/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/pom.xml
similarity index 53%
copy from plc4j/integrations/pom.xml
copy to plc4j/integrations/apache-hop/plc4x-hop-assemblies/pom.xml
index 253dcb038b..ccc6d04b8e 100644
--- a/plc4j/integrations/pom.xml
+++ b/plc4j/integrations/apache-hop/plc4x-hop-assemblies/pom.xml
@@ -8,7 +8,7 @@
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
- https://www.apache.org/licenses/LICENSE-2.0
+ 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
@@ -18,38 +18,25 @@
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.plc4x</groupId>
- <artifactId>plc4j</artifactId>
- <version>0.11.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>plc4j-integrations</artifactId>
- <packaging>pom</packaging>
-
- <name>PLC4J: Integrations</name>
- <description>Parent of all product specific integration modules.</description>
-
- <modules>
- <module>apache-nifi</module>
- <module>apache-calcite</module>
- <module>opcua-server</module>
- </modules>
-
- <!-- ! the kafka maven plugin currently seems to have issues with Java 19 -->
- <profiles>
- <profile>
- <id>java-version-not-19</id>
- <activation>
- <jdk>[1.8, 19)</jdk>
- </activation>
- <modules>
- <module>apache-kafka</module>
- </modules>
- </profile>
- </profiles>
-
-</project>
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-apache-hop</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4x-hop-assemblies</artifactId>
+ <packaging>pom</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Assemblies</name>
+
+ <properties>
+ <assembly.dir>${project.build.directory}/assembly</assembly.dir>
+ </properties>
+
+ <modules>
+ <module>plc4x-hop-assemblies-metadata</module>
+ <module>plc4x-hop-assemblies-action</module>
+ <module>plc4x-hop-assemblies-transform</module>
+ </modules>
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-metadata/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-metadata/pom.xml
new file mode 100644
index 0000000000..22eccd03ab
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-metadata/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-apache-hop</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>plc4x-hop-metadata</artifactId>
+ <packaging>jar</packaging>
+
+ <name>PLC4J: Integrations: Apache Hop: Metadata</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>8</source>
+ <target>8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.jandex</groupId>
+ <artifactId>jandex-maven-plugin</artifactId>
+ <version>1.0.8</version>
+ <executions>
+ <execution>
+ <id>make-index</id>
+ <goals>
+ <goal>jandex</goal>
+ </goals>
+ <!-- phase is 'process-classes by default' -->
+ <configuration>
+ <!-- Nothing needed here for simple cases -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <ignoredDependencies>
+ <dependency>org.apache.plc4x:plc4j-spi:jar:${project.version}</dependency>
+ <dependency>org.apache.plc4x:plc4j-driver-s7:jar:${project.version}</dependency>
+ <dependency>org.apache.plc4x:plc4j-transport-tcp:jar:${project.version}</dependency>
+ <dependency>org.apache.hop:hop-engine:jar:${hop.version}</dependency>
+ <dependency>javax.annotation:javax.annotation-api:jar:1.2</dependency>
+ </ignoredDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-ui</artifactId>
+ <version>${hop.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-engine</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
+ <version>3.114.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-driver-s7</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-transport-tcp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-core</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnection.java b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnection.java
new file mode 100644
index 0000000000..3a2b711c53
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnection.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.plc4x.hop.metadata;
+
+import org.apache.hop.core.gui.plugin.GuiElementType;
+import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiWidgetElement;
+import org.apache.hop.metadata.api.HopMetadata;
+import org.apache.hop.metadata.api.HopMetadataBase;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.metadata.api.IHopMetadata;
+
+@GuiPlugin
+@HopMetadata(
+ key = "plc4x-connection",
+ name = "Plc4x Connection",
+ description = "Describes a connection to a PLC",
+ image = "plc4x_toddy.svg",
+ documentationUrl = "/metadata-types/plc4x/plc4x-connection.html")
+public class Plc4xConnection extends HopMetadataBase implements IHopMetadata {
+
+ public static final String WIDGET_ID_URL = "10000-url";
+
+ @HopMetadataProperty
+ @GuiWidgetElement(
+ id = WIDGET_ID_URL,
+ type = GuiElementType.TEXT,
+ parentId = Plc4xConnectionEditor.PARENT_WIDGET_ID,
+ label = "URL",
+ toolTip = "Specify the hostname of your cassandra server")
+ private String url;
+
+
+ public Plc4xConnection() {}
+
+ public Plc4xConnection(Plc4xConnection p) {
+ super(p.name);
+ this.url = p.url;
+ }
+
+
+ /**
+ * Gets url
+ *
+ * @return value of hostname
+ */
+ public String getUrl() {
+ return url;
+ }
+
+ /** @param hostname The hostname to set */
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnectionEditor.java b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnectionEditor.java
new file mode 100644
index 0000000000..1118a5ff74
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/java/org/apache/plc4x/hop/metadata/Plc4xConnectionEditor.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.plc4x.hop.metadata;
+
+import org.apache.hop.core.Const;
+import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.gui.GuiCompositeWidgets;
+import org.apache.hop.ui.core.gui.GuiCompositeWidgetsAdapter;
+import org.apache.hop.ui.core.metadata.IMetadataEditor;
+import org.apache.hop.ui.core.metadata.MetadataEditor;
+import org.apache.hop.ui.core.metadata.MetadataManager;
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.widgets.*;
+
+
+public class Plc4xConnectionEditor extends MetadataEditor<Plc4xConnection>
+ implements IMetadataEditor<Plc4xConnection>{
+
+ private static final Class<?> PKG = Plc4xConnectionEditor.class; // For Translator
+
+ public static final String PARENT_WIDGET_ID = "Plc4xConnectionEditor.Widgets.ParentId";
+
+ private Composite parent;
+ private Text wName;
+ private GuiCompositeWidgets widgets;
+
+ public Plc4xConnectionEditor(HopGui hopGui, MetadataManager<Plc4xConnection> manager, Plc4xConnection metadata) {
+ super(hopGui, manager, metadata);
+ }
+
+
+ @Override
+ public void createControl(Composite parent) {
+ this.parent = parent;
+ PropsUi props = PropsUi.getInstance();
+ int margin = props.getMargin();
+ int middle = props.getMiddlePct();
+ // Name...
+ //
+ // What's the name
+ Label wlName = new Label(parent, SWT.RIGHT);
+ props.setLook(wlName);
+ wlName.setText("Plc4x url name");
+ FormData fdlName = new FormData();
+ fdlName.top = new FormAttachment(0, margin * 2);
+ fdlName.left = new FormAttachment(0, 0);
+ fdlName.right = new FormAttachment(middle, 0);
+ wlName.setLayoutData(fdlName);
+ wName = new Text(parent, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wName);
+
+ FormData fdName = new FormData();
+ fdName.top = new FormAttachment(wlName, 0, SWT.CENTER);
+ fdName.left = new FormAttachment(middle, margin);
+ fdName.right = new FormAttachment(100, 0);
+ wName.setLayoutData(fdName);
+
+ // Rest of the widgets...
+ //
+ widgets = new GuiCompositeWidgets(manager.getVariables());
+ widgets.createCompositeWidgets(getMetadata(), null, parent, PARENT_WIDGET_ID, wName);
+
+ // Set content on the widgets...
+ //
+ setWidgetsContent();
+
+ // Add changed listeners
+ wName.addListener(SWT.Modify, e -> setChanged());
+ widgets.setWidgetsListener(
+ new GuiCompositeWidgetsAdapter() {
+ @Override
+ public void widgetModified(
+ GuiCompositeWidgets compositeWidgets, Control changedWidget, String widgetId) {
+ setChanged();
+ }
+ });
+ }
+
+
+ @Override
+ public void setWidgetsContent() {
+ Plc4xConnection meta = getMetadata();
+ wName.setText(Const.NVL(meta.getName(), ""));
+ widgets.setWidgetsContents(meta, parent, PARENT_WIDGET_ID);
+ }
+
+ @Override
+ public void getWidgetsContent(Plc4xConnection meta) {
+ meta.setName(wName.getText());
+ widgets.getWidgetsContents(meta, PARENT_WIDGET_ID);
+ }
+
+ @Override
+ public Button[] createButtonsForButtonBar(Composite parent) {
+ PropsUi props = PropsUi.getInstance();
+
+ Button wbTest = new Button(parent, SWT.PUSH | SWT.CENTER);
+ props.setLook(wbTest);
+ wbTest.setText("Test");
+ wbTest.addListener(SWT.Selection, e -> test());
+
+ return new Button[] {wbTest};
+ }
+
+ public void test() {
+ PlcConnection plcConnection;
+ try {
+ Plc4xConnection meta = getMetadata();
+ plcConnection = new DefaultPlcDriverManager().getConnection(meta.getUrl());
+ plcConnection.connect();
+ Thread.sleep(100);
+ plcConnection.close();
+ MessageBox box = new MessageBox(parent.getShell(), SWT.ICON_INFORMATION | SWT.OK);
+ box.setText("Success!");
+ box.setMessage("It's possible to connect to Device with this metadata!");
+ box.open();
+
+ } catch (Exception e) {
+ new ErrorDialog(parent.getShell(), "Error", "We couldn't connect using this information", e);
+ }
+ }
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/org/apache/plc4x/hop/metadata/messages/messages_en_US.properties b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/org/apache/plc4x/hop/metadata/messages/messages_en_US.properties
new file mode 100644
index 0000000000..6db5c3fea3
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/org/apache/plc4x/hop/metadata/messages/messages_en_US.properties
@@ -0,0 +1,22 @@
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+Plc4x.Name=Sample Transform
+Plc4x.Description=Sample Transform Description
+Plc4x.Shell.Title=Sample Transform Title
+Plc4x.TransformName.Label=Sample Name
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/plc4x_toddy.svg b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/plc4x_toddy.svg
new file mode 100644
index 0000000000..01694ecd5d
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-metadata/src/main/resources/plc4x_toddy.svg
@@ -0,0 +1,1306 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ sodipodi:docname="iconotoddyconplc2.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="101.5"
+ inkscape:cx="8.3201971"
+ inkscape:cy="4.5960591"
+ inkscape:window-width="1920"
+ inkscape:window-height="1001"
+ inkscape:window-x="-9"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer52" />
+ <defs
+ id="defs2">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath78260">
+ <path
+ id="path78262"
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 324.28906,352.80664 v 76.18359 h 20.58203 c -0.0462,-0.10335 -0.0829,-0.21015 -0.10742,-0.31835 -0.43816,-10e-6 -0.87632,-3e-5 -1.31445,0 -0.55264,8e-5 -1.10556,9.9e-4 -1.6582,0 -0.64072,-10e-4 -1.28115,0.007 -1.92188,0.002 -0.35799,-0.003 -0.73573,0.008 -1.09766,-0.0156 -0.003,0 0.007,-0.003 0.01,-0.004 0.0863,-0.0166 0.17347,-0.0342 0.25977,-0.0508 -0.2144,0.025 -0.42708,0.0642 -0.64063,0.0957 -0.49177,-0.0339 -0.98416,-0.0786 -1.47656,-0.10156 -0.0774,-0.004 0.30541,0.05 [...]
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath81911">
+ <path
+ id="path81913"
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 395.09961,461.69922 v 42.96484 c 0.0746,-0.0504 0.14872,-0.10118 0.22266,-0.15234 0.93912,-0.64976 1.92039,-1.23589 2.85742,-1.88867 1.25063,-0.87125 2.48887,-1.7632 3.73242,-2.64453 1.05963,-0.76014 2.1181,-1.51916 3.17773,-2.2793 1.81669,-1.30323 3.50814,-1.82371 4.91016,-1.78711 0.85754,0.0224 1.60218,0.25706 2.20508,0.64258 0.23436,-0.0636 0.46865,-0.12661 0.70117,-0.19531 0.40305,-0.0456 0.80391,-0.11562 1.20898,-0.13672 0.21987,-0.0113 0.43985,-0.0169 0.66016,-0.0156 [...]
+ </clipPath>
+ </defs>
+ <g
+ inkscape:groupmode="layer"
+ id="layer52"
+ inkscape:label="Capa 2">
+ <path
+ style="fill:#f5f5f5;stroke:#f5f5f5;stroke-width:0.9355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 5.1062072,5.7391588 6.8487514,7.1431509 8.7779937,7.0574466 9.7326615,6.3436554 10.276258,4.8805204 9.7326615,4.1109178 6.1778718,4.5009157 Z"
+ id="path1177" />
+ </g>
+ <g
+ inkscape:label="Capa 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline;opacity:1"
+ sodipodi:insensitive="true">
+ <g
+ id="g1481"
+ transform="matrix(0.01850365,0,0,0.01824053,1.5356497,-1.2454454)">
+ <g
+ inkscape:label="Image"
+ id="g830"
+ style="display:none;opacity:1">
+ <image
+ width="696.6618"
+ height="985.07983"
+ preserveAspectRatio="none"
+ style="image-rendering:optimizeSpeed"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+gAAAWGCAYAAAAcjY/0AAAACXBIWXMAADXTAAA10wEMIUN3AAAA B3RJTUUH5AMeFSExccvdCgAAIABJREFUeJzs3Xl83PV97/v3bxbNSCNrl7yMx+s4YGOMjTzYjLGd mIMzEGhZ0kKBljRtgSaFkJySntKQk5w4t7nNuU3vOb23hXNOcnqT9qa5N8staXFCSxsIDsaYGDBe sAy2ZSTbsrVY1jrL7/7xG1mLtcyMfrPq9eQxWJ75zff3ndHImvd8vosEAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [...]
+ id="image832" />
+ </g>
+ <g
+ id="layer45"
+ inkscape:label="bracitoplc 2"
+ style="display:inline">
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1712"
+ width="13.140327"
+ height="54.751366"
+ x="555.72638"
+ y="753.92633" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1714"
+ width="13.140317"
+ height="54.203869"
+ x="555.72638"
+ y="699.72247" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1721"
+ width="13.961588"
+ height="47.359943"
+ x="555.72638"
+ y="652.36255" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1723"
+ width="12.866549"
+ height="47.907455"
+ x="569.68799"
+ y="651.815" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1725"
+ width="13.687866"
+ height="54.203857"
+ x="568.8667"
+ y="699.72247" />
+ <rect
+ style="fill:#767479;fill-opacity:0.996078;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1727"
+ width="13.687866"
+ height="54.751343"
+ x="568.8667"
+ y="753.92633" />
+ </g>
+ <g
+ id="layer47"
+ inkscape:label="bracitoplc 4"
+ style="display:inline">
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828"
+ sodipodi:type="arc"
+ sodipodi:cx="575.69299"
+ sodipodi:cy="659.0755"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 578.11268,659.0755 a 2.4196913,2.564873 0 0 1 -2.40082,2.5648 2.4196913,2.564873 0 0 1 -2.43826,-2.5248 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828-6"
+ sodipodi:type="arc"
+ sodipodi:cx="572.78937"
+ sodipodi:cy="803.04718"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 575.20906,803.04718 a 2.4196913,2.564873 0 0 1 -2.40083,2.5648 2.4196913,2.564873 0 0 1 -2.43826,-2.5248 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ <path
+ style="display:inline;fill:#acacb8;fill-opacity:0.992157;stroke:#432c33;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path7828-6-9"
+ sodipodi:type="arc"
+ sodipodi:cx="561.36841"
+ sodipodi:cy="802.36963"
+ sodipodi:rx="2.4196913"
+ sodipodi:ry="2.564873"
+ sodipodi:start="0"
+ sodipodi:end="6.2519963"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 563.7881,802.36963 a 2.4196913,2.564873 0 0 1 -2.40083,2.56479 2.4196913,2.564873 0 0 1 -2.43826,-2.52479 2.4196913,2.564873 0 0 1 2.3628,-2.60417 2.4196913,2.564873 0 0 1 2.47511,2.48419" />
+ </g>
+ <g
+ id="layer46"
+ inkscape:label="bracitoplc 3"
+ style="display:inline">
+ <path
+ style="fill:#9d9eab;fill-opacity:0.996078;stroke:#432c33;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 580.77512,652.91004 9.44461,1.77942 0.13688,27.23881 -9.44461,4.92762 7.93895,1.09503 -1.09503,23.81684 -7.52831,0.27376 z"
+ id="path1763" />
+ <path
+ style="fill:#939d4d;fill-opacity:0.992157;stroke:#432c33;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 578.9957,808.13017 7.52831,-6.70704 v -14.78287 l -6.84392,-4.24323 7.80207,-0.13688 0.27376,-22.72182 -8.62334,-0.27376 z"
+ id="path1765" />
+ <rect
+ style="fill:#939d4d;fill-opacity:0.992157;stroke:#432c33;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1789"
+ width="8.6233397"
+ height="47.496811"
+ x="579.13257"
+ y="711.76776" />
+ </g>
+ <g
+ id="layer35"
+ inkscape:label="bracitoplc 1"
+ style="display:inline">
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1687"
+ width="138.26697"
+ height="114.77483"
+ x="425.67212"
+ y="619.44098" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1689"
+ width="42.706066"
+ height="10.40276"
+ x="439.65347"
+ y="734.21582" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1691"
+ width="42.706074"
+ height="11.497789"
+ x="482.35953"
+ y="734.21582" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1693"
+ width="41.611038"
+ height="96.909912"
+ x="439.65347"
+ y="744.61859" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1695"
+ width="43.801086"
+ height="95.81488"
+ x="481.26453"
+ y="745.71362" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1697"
+ width="13.414075"
+ height="106.49141"
+ x="525.06561"
+ y="735.03711" />
+ <rect
+ style="fill:#757378;fill-opacity:1;stroke:#432d34;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect1699"
+ width="15.877909"
+ height="102.93256"
+ x="538.47968"
+ y="735.03711" />
+ </g>
+ <g
+ id="layer48"
+ inkscape:label="bracitoplc 5"
+ style="display:inline">
+ <rect
+ style="fill:#6d9ed8;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14676"
+ width="31.552776"
+ height="10.646642"
+ x="435.73804"
+ y="632.60413" />
+ <rect
+ style="fill:#d3c9b7;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14678"
+ width="4.6458073"
+ height="5.4201088"
+ x="437.28662"
+ y="645.18652" />
+ <rect
+ style="fill:#f56a9e;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14680"
+ width="4.6458073"
+ height="16.647476"
+ x="437.28662"
+ y="655.25244" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14682"
+ width="4.8393826"
+ height="11.420943"
+ x="437.48019"
+ y="677.51361" />
+ <rect
+ style="fill:#191928;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14684"
+ width="7.9365878"
+ height="11.614519"
+ x="440.57742"
+ y="699.58118" />
+ <rect
+ style="fill:#191928;fill-opacity:1;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14686"
+ width="7.9365878"
+ height="11.808094"
+ x="440.771"
+ y="716.61578" />
+ <rect
+ style="fill:#9fbfc1;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14688"
+ width="8.7108889"
+ height="61.944099"
+ x="487.03549"
+ y="637.83063" />
+ <rect
+ style="fill:#72a2b1;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14690"
+ width="5.2265334"
+ height="11.227368"
+ x="487.42264"
+ y="715.45435" />
+ <rect
+ style="fill:#4e4d53;fill-opacity:0.996078;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14692"
+ width="7.1622868"
+ height="10.646642"
+ x="526.52484"
+ y="701.51691" />
+ <rect
+ style="fill:#4d4c52;fill-opacity:1;stroke:#432d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ id="rect14694"
+ width="6.775136"
+ height="9.4851904"
+ x="545.10809"
+ y="701.71051" />
+ </g>
+ <g
+ id="layer49"
+ inkscape:label="bracitoplc 6"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#432c33;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 480.6475,733.45686 479.48605,617.8924"
+ id="path33186" />
+ <path
+ style="fill:none;stroke:#422d34;stroke-width:3.4723;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 521.10445,618.08707 0.96846,116.53014"
+ id="path33188" />
+ <path
+ style="fill:none;stroke:#432c33;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 541.8173,735.19904 0.38715,-116.72592"
+ id="path33190" />
+ </g>
+ <g
+ id="layer50"
+ inkscape:label="bracitoplc 7"
+ style="display:inline">
+ <rect
+ style="fill:#acacb8;fill-opacity:0.996078;stroke:#422d34;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36118"
+ width="11.808094"
+ height="41.037968"
+ x="495.16565"
+ y="766.17108" />
+ <rect
+ style="fill:#acacb8;fill-opacity:1;stroke:#422d34;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36120"
+ width="7.549437"
+ height="41.812267"
+ x="526.71844"
+ y="762.29956" />
+ <rect
+ style="fill:#acacb8;fill-opacity:1;stroke:#422d34;stroke-width:1.0613;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect36120-1"
+ width="7.549437"
+ height="47.095997"
+ x="541.91406"
+ y="762.04877" />
+ <rect
+ style="fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396"
+ width="3.7518525"
+ height="13.356678"
+ x="530.37915"
+ y="762.42542" />
+ <rect
+ style="fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3"
+ width="3.7518525"
+ height="13.356678"
+ x="545.71167"
+ y="762.04877" />
+ <rect
+ style="display:inline;fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3-0"
+ width="3.7518525"
+ height="13.356678"
+ x="528.73328"
+ y="786.12146"
+ inkscape:transform-center-x="-15.877896"
+ inkscape:transform-center-y="-23.679966" />
+ <rect
+ style="display:inline;fill:#422d34;fill-opacity:1;stroke:#422d34;stroke-width:0.927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect38396-3-0-9"
+ width="3.7518525"
+ height="13.356678"
+ x="543.72144"
+ y="789.26965"
+ inkscape:transform-center-x="-15.877896"
+ inkscape:transform-center-y="-23.679966" />
+ </g>
+ <g
+ id="layer51"
+ inkscape:label="bracitoplc 8">
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="692.67322" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="688.22467" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="683.77612" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="679.32758" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="674.87903" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="670.43048" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="665.98193" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="661.53339" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="657.08484" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="652.63629" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="648.18774" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-8"
+ width="3.6272781"
+ height="4.4485483"
+ x="528.0769"
+ y="643.7392" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-7"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="693.17474" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="688.7262" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="684.27765" />
+ <rect
+ style="fill:#a5b17b;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-8"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="679.8291" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-6"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="675.38055" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="670.93201" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="666.48346" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-0"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="662.03491" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-2"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="657.58636" />
+ <rect
+ style="fill:#a5b17b;fill-opacity:1;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-4"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="653.13782" />
+ <rect
+ style="fill:#a6b27c;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-9"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="648.68927" />
+ <rect
+ style="fill:#d2c8b6;fill-opacity:0.996078;stroke:#422d34;stroke-width:1.027;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect40699-4-3-3-1-9-3-6-4-0-5-8-1"
+ width="3.6272781"
+ height="4.4485483"
+ x="547.7467"
+ y="644.24072" />
+ </g>
+ <g
+ id="layer12"
+ inkscape:label="piernas1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 303.67005,695.87776 c 0,0 8.17142,20.65132 10.53645,31.4521 3.12408,14.26726 4.49063,28.95763 4.71781,43.56116 0.0425,2.73357 -0.62904,8.17755 -0.62904,8.17755 0,0 -13.5481,8.85046 -20.91565,12.10906 -2.21358,0.97904 -6.91946,2.20164 -6.91946,2.20164 0,0 -4.25625,-0.25265 -5.9759,0.78631 -1.86725,1.12814 -2.87795,3.35789 -3.77425,5.34685 -1.21716,2.70097 -2.89417,5.81127 -2.04439,8.64933 0.74456,2.48665 3.27563,4.32412 5.66138,5.34686 4.5353,1.94422 10.4375,0.95612 15.568 [...]
+ id="path45804"
+ sodipodi:nodetypes="csscscsssssscsccc" />
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 349.74737,702.16818 8.96385,72.02531 c 0,0 1.1094,6.66922 3.30248,9.5929 2.73079,3.64053 7.23484,4.9864 11.32275,6.13316 9.2398,2.59198 28.14963,-0.78631 28.14963,-0.78631 0,0 7.49833,-5.59383 8.80659,-10.06467 0.91855,-3.13907 0.53128,-6.91577 -1.10082,-9.75015 -1.00971,-1.75352 -2.94495,-3.00961 -4.87508,-3.617 -1.75081,-0.55096 -3.72827,-0.30668 -5.50412,0.15726 -4.80939,1.25645 -8.57615,5.12018 -13.20988,6.91947 -2.6787,1.04015 -5.47589,1.91194 -8.33481,2.20164 -3.708 [...]
+ id="path45806"
+ sodipodi:nodetypes="ccsscssssssscsssccc" />
+ </g>
+ <g
+ id="layer13"
+ inkscape:label="piernas2"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 296.59332,813.27273 c -1.65123,-1.49398 -2.14474,-1.41645 -2.3724,-5.09025 0,0 0.98475,-2.852 3.1587,-5.15134 l -0.80374,5.75966 0.72511,4.16741 z"
+ id="path50785"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 283.80717,811.40996 c -1.09189,-1.9407 -1.5845,-2.02376 -0.63475,-5.57997 0,0 1.83877,-2.39219 4.62994,-3.88295 l -2.58967,5.20704 -0.63462,4.18214 z"
+ id="path50785-5"
+ sodipodi:nodetypes="cccccc"
+ inkscape:transform-center-x="1.2111362"
+ inkscape:transform-center-y="0.54705423" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 406.70034,784.46583 c -0.51381,-2.16669 -0.20814,-2.56182 -3.31794,-4.53103 0,0 -2.97366,-0.51087 -6.03585,0.28661 l 5.43453,2.07014 3.30274,2.64292 z"
+ id="path50785-7"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1.00157;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.42874,777.16475 c -0.51381,-2.16669 -0.20814,-2.56182 -3.31794,-4.53103 0,0 -2.97366,-0.51087 -6.03585,0.28661 l 5.43453,2.07014 3.30274,2.64292 z"
+ id="path50785-7-0"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ <g
+ id="layer8"
+ inkscape:label="cola1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 266.43514,668.97904 c 0,0 -35.74884,34.3707 -51.59679,53.37598 -7.82609,9.38525 -14.93118,19.40333 -21.3504,29.8016 -5.01676,8.12647 -10.13103,16.36002 -13.34399,25.35359 -4.4804,12.54132 -6.29825,18.70817 -6.2272,32.02559 0.0413,7.73538 1.21731,22.30215 3.1136,29.8016 3.25519,12.87359 11.11999,38.25279 11.11999,38.25279 l 5.7824,33.35999 8.896,-16.4576 18.6816,48.48319 -6.2272,-42.70079 c 0,0 24.6715,21.78542 39.58719,28.0224 16.39477,6.85546 34.77126,7.94088 52.48639,9. [...]
+ id="path26360"
+ sodipodi:nodetypes="cssssscccccssssssssssssccsssssscsscc" />
+ </g>
+ <g
+ id="layer9"
+ inkscape:label="cola2"
+ style="display:inline">
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 352.28151,872.69739 c 0,0 7.44415,4.85397 10.2304,8.2288 1.81572,2.19929 3.29625,4.79864 4.0032,7.5616 1.30484,5.0997 0.91579,10.57227 0.2224,15.79039 -0.782,5.88496 -2.57092,11.661 -4.8928,17.1248 -2.31244,5.4416 -10.15408,16.28915 -10.15408,16.28915 0,0 30.85563,-3.23121 45.07087,-7.17076 13.95855,-3.86841 26.07208,-13.03889 40.03199,-16.90239 7.14369,-1.97707 14.72383,-1.79375 22.0176,-3.1136 7.09741,-1.28432 14.47159,-1.8928 21.12799,-4.6704 16.52917,-6.89734 32.61892 [...]
+ id="path30974"
+ sodipodi:nodetypes="csssscsssssssssscccccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 295.79193,876.25579 c 0,0 0.86685,2.27962 1.7792,5.3376 0.97587,3.27088 0.88529,6.84558 0.4448,10.23039 -0.93197,7.16143 -2.93554,14.374 -6.4496,20.6832 -4.29611,7.71331 -17.3472,20.01599 -17.3472,20.01599 -18.29893,-1.24213 -29.41982,-9.37518 -40.47679,-17.56959 l -5.1152,-3.5584 c 0,0 14.80505,-2.82191 19.3488,-4.8928 5.26384,-2.39908 10.73722,-4.88001 14.9008,-8.896 3.24121,-3.12632 6.06377,-7.02353 7.33919,-11.34239 1.82667,-6.18552 -0.2224,-15.7904 -0.2224,-15.7904 l [...]
+ id="path30976"
+ sodipodi:nodetypes="cssscccsssccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 173.91676,809.9806 c 0,0 6.53772,7.07804 10.8976,8.6736 7.10409,2.59984 22.68479,0.6672 22.68479,0.6672 l 20.01599,-6.0048 4.6704,15.3456 c 0,0 -2.92583,10.40351 -5.78239,14.9008 -2.36154,3.71794 -5.42281,7.16682 -9.1184,9.56319 -5.01672,3.25305 -10.99731,5.06684 -16.9024,6.0048 -5.5663,0.88415 -16.90239,-0.4448 -16.90239,-0.4448 l -3.1136,-9.5632 -5.1152,-19.12639 z"
+ id="path30978"
+ sodipodi:nodetypes="cscccssscccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 186.37115,764.83342 c 0,0 2.61472,6.12608 4.8928,8.45119 3.70148,3.77789 8.5302,6.61323 13.5664,8.2288 4.6723,1.49883 9.79676,1.60842 14.6784,1.112 4.83236,-0.49141 14.01119,-4.0032 14.01119,-4.0032 l 8.6736,-16.01279 c 0,0 -3.5584,0.2224 -7.784,0 -4.2256,-0.2224 -13.59615,1.11289 -19.57119,-1.5568 -3.9257,-1.75403 -7.03587,-5.26626 -9.3408,-8.896 -1.88504,-2.96851 -3.336,-10.008 -3.336,-10.008 z"
+ id="path30980"
+ sodipodi:nodetypes="csssccssscc" />
+ </g>
+ <g
+ id="layer11"
+ inkscape:label="cola3"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 213.28155,724.35663 c 1.31933,2.2684 3.06616,4.67929 7.8952,8.11759 5.15226,3.05071 10.30453,4.25128 15.45679,3.4472 -3.89287,-1.51625 -7.70178,-3.36833 -11.00879,-7.228 -4.65549,-4.19699 -3.58085,-7.57539 -4.448,-11.23119 z"
+ id="path40775"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 228.57154,708.45503 4.0588,5.6156 c 4.42518,4.67147 3.92725,4.15725 5.56,5.5044 4.59015,4.00912 10.45844,3.96209 16.0684,3.892 -3.57693,-2.13133 -9.02839,-4.26267 -10.7308,-6.394 -0.7713,-0.89985 -4.23439,-5.78656 -6.3384,-8.618 -1.12088,-1.50842 -3.3916,-4.5036 -3.3916,-4.5036 z"
+ id="path43167"
+ sodipodi:nodetypes="cccccscc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 242.24407,693.48199 c 1.31933,2.2684 3.06616,4.67929 7.8952,8.11759 5.15226,3.05071 10.30453,4.25128 15.45679,3.4472 -3.89287,-1.51625 -7.70178,-3.36833 -11.00879,-7.228 -4.65549,-4.19699 -3.58085,-7.57539 -4.448,-11.23119 z"
+ id="path40775-6"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:2.20844;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 255.92442,678.49794 c 0.76194,2.01697 1.84443,4.20907 5.23803,7.664 3.69756,3.18742 7.6251,4.88104 11.80188,4.95614 -2.41828,-1.84402 -5.67527,-3.8023 -7.8123,-7.38345 -3.16198,-4.04309 -1.89165,-6.61971 -2.1233,-9.6933 z"
+ id="path40775-3"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ <g
+ id="layer42"
+ inkscape:label="brazos"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 251.17189,538.75344 c -10.30848,7.4695 -21.90306,14.08159 -30.25013,22.85869 0.93037,8.39579 11.48929,15.65882 17.93107,23.40621 l 2.87445,15.05663 6.02265,7.93895 -3.8326,-27.78632 -9.03397,-12.31906 12.45593,-9.03397 z"
+ id="path106114"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <g
+ id="layer43"
+ inkscape:label="brazos 1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 229.81886,606.09762 -1.64254,-3.8326 c 0,0 5.02138,-4.18315 7.93894,-3.83259 4.98818,0.59936 11.63467,9.58149 11.63467,9.58149 l -0.27376,10.67651 c 0,0 -16.95316,1.72375 -24.36435,-1.64254 -2.34995,-1.06739 -4.90487,-2.95792 -5.47514,-5.47513 -1.05857,-4.67255 4.79074,-13.55097 4.79074,-13.55097 0,0 4.88203,-7.88988 8.21271,-6.70704 2.76577,0.98222 1.77942,8.62334 1.77942,8.62334"
+ id="path108592"
+ sodipodi:nodetypes="ccaccaacac" />
+ </g>
+ <g
+ id="layer44"
+ inkscape:label="brazos 2"
+ style="display:none;opacity:1">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.96038,558.17441 c 0,0 10.7989,2.96383 12.96955,7.45265 5.79413,11.98202 -5.90405,39.48936 -5.90405,39.48936 0,0 4.54276,2.00875 6.19441,3.77472 1.76439,1.88651 3.63847,4.28954 3.58115,6.87192 -0.0314,1.41627 -2.12933,3.67793 -2.12933,3.67793 l -6.19441,3.87151 -10.84022,-43.45766 z"
+ id="path109612"
+ sodipodi:nodetypes="cacaacccc" />
+ </g>
+ <g
+ id="layer34"
+ inkscape:label="bracitoplc">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 404.95955,523.81479 c 0,0 7.56997,8.77919 10.84022,13.55028 14.94151,21.79874 39.87651,68.52566 39.87651,68.52566 h 13.55028 l 9.09804,0.38715 c 0,0 7.39921,5.48435 7.35586,9.48519 -0.0333,3.07341 -5.80726,7.16228 -5.80726,7.16228 h -6.38799 l -3.67793,-4.45223 c 0,0 6.30824,4.95935 5.22654,7.93659 -0.69013,1.8995 -3.80845,2.04074 -5.80726,1.74218 -4.14173,-0.61864 -10.45307,-6.96871 -10.45307,-6.96871 l -10.64664,-8.13017 -32.32708,-38.32791 z"
+ id="path1012"
+ sodipodi:nodetypes="cacccacccaacccc" />
+ </g>
+ <g
+ id="layer1-0"
+ inkscape:label="cuerpo1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:5.91496;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 274.89137,499.14486 c 0,0 -12.68668,21.84593 -16.98413,33.65375 -5.48792,15.07878 -10.30664,30.83258 -11.00824,46.86363 -0.96332,22.01137 3.20928,44.28601 9.43563,65.42037 2.34659,7.96513 5.39306,16.00563 10.3792,22.64552 7.32006,9.7479 17.01388,17.99725 27.67784,23.90359 9.02196,4.9969 19.35356,7.67485 29.56498,9.12111 11.62794,1.64688 23.84306,2.2592 35.22635,-0.62904 8.81758,-2.23725 17.12692,-6.8826 24.21812,-12.58084 7.77455,-6.24736 13.87649,-14.51702 19.18579,-22.9 [...]
+ id="path948"
+ sodipodi:nodetypes="csssssssssssssccc" />
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="cuerpo2"
+ style="display:inline">
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#67464f;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.992157"
+ d="m 254.76202,547.89562 c 0,0 6.01284,-0.6026 9.12112,0.62904 5.46166,2.16415 11.75134,1.01913 17.61317,0.62904 4.98734,-0.33189 14.78249,-2.51617 14.78249,-2.51617 0,0 -5.50262,-3.48901 -8.17755,-5.34685 -2.03224,-1.41147 -4.23666,-2.64338 -5.97589,-4.4033 -2.90413,-2.93868 -5.53439,-6.29888 -7.23399,-10.06467 -1.54841,-3.43081 -1.57944,-7.36261 -2.51617,-11.00824 -0.56983,-2.21771 -1.88712,-6.60494 -1.88712,-6.60494 z"
+ id="path4530"
+ sodipodi:nodetypes="csscsssscc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 249.10065,603.56584 c 0,0 16.74071,-2.54379 24.53264,-5.66138 5.5423,-2.2175 10.58478,-5.60871 15.41153,-9.12111 4.86456,-3.53992 13.5244,-11.9518 13.5244,-11.9518 0,0 -5.45796,-0.18457 -8.17755,0 -4.64498,0.31525 -9.18421,1.79268 -13.83892,1.88713 -6.63346,0.1346 -13.58445,0.39398 -19.81482,-1.88713 -4.31495,-1.57982 -11.32276,-7.86302 -11.32276,-7.86302 l -2.83069,12.26632 z"
+ id="path8585"
+ sodipodi:nodetypes="csscsssccc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#6b4852;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 398.34087,536.88738 c 0,0 -4.40524,8.31835 -8.3348,10.3792 -6.46951,3.39293 -21.85922,1.5726 -21.85922,1.5726 l 7.86303,9.59289 c 0,0 8.07129,2.72998 12.26632,2.83069 4.42008,0.10611 9.28625,-0.0431 13.05262,-2.35891 2.51854,-1.54854 5.14278,-4.12726 5.34686,-7.07672 0.39362,-5.68889 -8.33481,-14.93975 -8.33481,-14.93975 z m -33.49649,42.77486"
+ id="path11029"
+ sodipodi:nodetypes="csccsssc" />
+ <path
+ style="fill:#a86971;fill-opacity:1;stroke:#6b4953;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 410.44993,571.95648 5.81864,17.92769 c 0,0 -3.66745,1.821 -5.66138,2.04439 -6.77165,0.75866 -13.92872,-0.065 -20.2866,-2.51617 -4.42369,-1.70546 -11.63728,-8.17754 -11.63728,-8.17754 l 11.00823,-0.47179 c 0,0 9.85612,-0.66712 14.15345,-2.83069 2.6519,-1.33514 6.60494,-5.97589 6.60494,-5.97589 z"
+ id="path11483"
+ sodipodi:nodetypes="ccssccsc" />
+ </g>
+ <g
+ id="layer3"
+ inkscape:label="cuerpo3"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 339.60472,521.75027 -0.2224,71.39039 28.24479,25.35359 20.9056,-23.79679 c 0,0 1.15878,-20.29151 -0.4448,-30.2464 -1.53253,-9.51383 -8.6736,-27.57759 -8.6736,-27.57759 l -6.2272,-13.344 z"
+ id="path15367"
+ sodipodi:nodetypes="ccccsccc" />
+ </g>
+ <g
+ id="layer4"
+ inkscape:label="cuerpo4"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path17570-8"
+ sodipodi:type="arc"
+ sodipodi:cx="643.40137"
+ sodipodi:cy="363.7131"
+ sodipodi:rx="2.4238381"
+ sodipodi:ry="7.0955071"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 645.82521,363.7131 a 2.4238381,7.0955071 0 0 1 -2.38763,7.09472 2.4238381,7.0955071 0 0 1 -2.45897,-6.88273 2.4238381,7.0955071 0 0 1 2.31416,-7.30037 2.4238381,7.0955071 0 0 1 2.52811,6.66461 l -2.41951,0.42377 z"
+ transform="matrix(0.88968208,0.45658055,-0.54212471,0.84029804,0,0)" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path18346"
+ sodipodi:type="arc"
+ sodipodi:cx="383.65356"
+ sodipodi:cy="587.5553"
+ sodipodi:rx="1.4546597"
+ sodipodi:ry="1.3760295"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 385.10822,587.5553 a 1.4546597,1.3760295 0 0 1 -1.43292,1.37587 1.4546597,1.3760295 0 0 1 -1.47575,-1.33476 1.4546597,1.3760295 0 0 1 1.38884,-1.41576 1.4546597,1.3760295 0 0 1 1.51724,1.29247 l -1.45207,0.0822 z" />
+ </g>
+ <g
+ id="layer7"
+ inkscape:label="cuerpo5"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 291.89993,633.39505 c 0,0 3.89054,-1.12226 5.8936,-1.3344 3.17022,-0.33576 7.6637,-2.44906 9.5632,0.1112 0.71293,0.96093 -0.27054,2.49938 -1.0008,3.4472 -0.79147,1.02727 -2.05095,1.8274 -3.336,2.0016 -2.05856,0.27905 -6.0048,-1.668 -6.0048,-1.668 l -1.2232,-0.8896"
+ id="path22026"
+ sodipodi:nodetypes="csssscc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 277.44393,673.42704 c 0,0 0.96236,-3.33842 2.3352,-4.1144 1.25889,-0.71157 3.07074,-0.77887 4.5036,-0.5838 0.75716,0.10308 1.59414,0.64314 2.0572,1.251 0.94367,1.23875 0.34538,3.1816 -0.1112,4.6704 -0.54263,1.7694 -3.0024,4.6704 -3.0024,4.6704"
+ id="path22028"
+ sodipodi:nodetypes="cssssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 335.82392,667.42224 c 0,0 0.76468,-4.17048 2.1128,-5.6712 0.94161,-1.04819 2.40947,-1.56667 3.7808,-1.8904 1.98413,-0.46839 4.12867,-0.4546 6.116,0 1.16358,0.26617 2.97066,0.39053 3.2248,1.5568 0.35872,1.64617 -1.74518,3.08621 -3.2248,3.892 -1.37686,0.74983 -4.6704,0.556 -4.6704,0.556"
+ id="path22030"
+ sodipodi:nodetypes="csssssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 318.92152,681.21104 5.1152,-0.1112 c 0,0 1.84002,0.0173 2.0016,-0.6672 0.13248,-0.5612 -1.3344,-1.112 -1.3344,-1.112 l -3.2248,-1.112"
+ id="path22032"
+ sodipodi:nodetypes="ccscc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 380.41511,671.42544 8.2288,-4.448 c 0,0 2.08613,-0.60007 2.5576,0.1112 1.11458,1.68146 -0.9049,4.05547 -2.1128,5.6712 -0.44388,0.59375 -1.7792,1.3344 -1.7792,1.3344"
+ id="path22034"
+ sodipodi:nodetypes="ccssc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:2.89134;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 395.7607,615.60305 c 0,0 -0.76638,2.41373 0,3.1136 0.90696,0.82825 2.59389,0.25922 3.6696,-0.3336 1.22718,-0.6763 2.89206,-1.9753 2.5576,-3.336 -0.27313,-1.1112 -1.75804,-1.52103 -2.79908,-1.99601 -1.07172,-0.48898 -4.56151,0.0484 -4.56151,0.0484"
+ id="path22036"
+ sodipodi:nodetypes="cssssc" />
+ </g>
+ <g
+ id="layer5"
+ inkscape:label="cuerpo6"
+ style="display:inline">
+ <path
+ style="fill:#47353a;fill-opacity:1;stroke:#48353a;stroke-width:1.00476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 254.95538,649.80043 c 0,0 18.44089,3.8226 27.8543,4.71782 12.13083,1.15364 24.37576,0.90865 36.55876,0.62904 12.56559,-0.28839 25.19664,-0.16575 37.66662,-1.72987 9.51549,-1.19353 18.94306,-3.2207 28.17083,-5.81864 11.3354,-3.19131 33.23524,-11.9518 33.23524,-11.9518 l 3.16526,-24.21812 c 0,0 -5.37313,2.11683 -8.07141,3.14521 -8.41679,3.20784 -16.29513,7.11271 -24.68904,10.37919 -7.5347,2.93213 -15.28512,6.11555 -23.10642,8.17755 -14.45191,3.81009 -29.53062,5.2585 -44.471 [...]
+ id="path18608"
+ sodipodi:nodetypes="cssssccssssscccc" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:label="cuerpo7"
+ style="display:inline">
+ <rect
+ style="fill:#47353a;fill-opacity:1;stroke:#8f8381;stroke-width:6.67087;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect21069"
+ width="36.327179"
+ height="16.826874"
+ x="277.61121"
+ y="659.9422"
+ transform="rotate(-4.2348532)" />
+ </g>
+ <g
+ id="layer14"
+ inkscape:label="cabeza1"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#694650;stroke-width:4.0252;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 217.0195,218.90663 -38.37156,-11.32276 c 0,0 -58.46937,0.0343 -67.93654,13.83893 -6.96054,10.14957 -1.00939,27.41604 3.14521,39.00061 5.34747,14.91071 26.73429,38.37156 26.73429,38.37156 l 12.26632,11.00823 c 0,0 -1.4636,16.46148 -3.14521,24.53264 -1.75948,8.44492 -7.23399,24.84716 -7.23399,24.84716 l -16.35509,18.55675 23.58908,7.5485 -35.54088,20.12934 44.97651,7.86303 -25.79073,12.89536 c 0,0 48.88224,30.62342 74.22696,44.34747 21.44031,11.60983 42.86475,23.62943 65.73 [...]
+ id="path57316"
+ sodipodi:nodetypes="ccssccsccccccsscccccccccsscccccssccssssscc" />
+ </g>
+ <g
+ id="layer36"
+ inkscape:label="SOMBRAS 3"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 155.53776,308.75262 c -2.62623,17.54433 -4.84338,37.94961 -11.32415,52.36212 l -13.84064,15.48602 c 0,0 26.42303,8.22696 25.26158,8.22696 -1.16145,0 -33.97247,19.26074 -33.97247,19.26074 l 45.4902,8.32374 -28.93951,14.13099 52.5557,31.55278 -16.77414,-15.94078 -14.48827,-14.93448 25.93909,-20.51898 c 0,0 -17.22335,1.62206 -24.19692,-2.51648 -3.03217,-1.79947 -6.21244,-5.19132 -6.00083,-8.71089 0.4856,-8.07682 16.06675,-18.19608 16.06675,-18.19608 0,0 -10.57214,-1.63693 -1 [...]
+ id="path65911"
+ sodipodi:nodetypes="cccscccccccaacaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 480.45392,261.32667 c -20.50896,7.18066 -48.63851,54.13462 -62.33125,87.10889 -8.68146,20.90633 -11.00017,44.34101 -11.22737,66.97706 -0.22256,22.17337 9.67877,65.8156 9.67877,65.8156 l 10.45306,1.5486 2.32291,7.35586 -2.32291,7.74302 -16.26032,10.06591 -11.22737,8.51732 -2.71005,5.42011 19.74468,-1.93576 8.51731,-9.29161 17.03463,-18.97038 -0.58072,-22.7451 c 0,0 8.48676,-5.08539 12.77596,-7.54944 10.30639,-5.9208 16.16505,-16.08504 22.26116,-25.8423 4.83237,-7.73455 16. [...]
+ id="path65913"
+ sodipodi:nodetypes="caacccccccccccsscccccccccccc" />
+ </g>
+ <g
+ id="layer15"
+ inkscape:label="ojjos 1"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 202.55154,385.28825 c 0,0 21.31315,24.22071 33.33923,34.91183 10.68757,9.50119 22.05463,18.37662 34.28279,25.79073 10.82678,6.56443 22.60415,11.46424 34.28279,16.35509 11.62446,4.86816 23.18495,10.41378 35.54087,12.89536 6.3803,1.28143 12.9973,1.19081 19.50031,0.94356 3.37856,-0.12846 7.12276,0.40814 10.06467,-1.25808 6.95287,-3.93793 10.95952,-11.85453 14.78249,-18.87126 5.52024,-10.13193 9.52298,-21.31327 11.32275,-32.71019 1.63567,-10.35778 0.15288,-20.99516 -0.62904,- [...]
+ id="path61200"
+ sodipodi:nodetypes="csssssssssssssssssc" />
+ </g>
+ <g
+ id="layer16"
+ inkscape:label="ojos2"
+ style="display:inline">
+ <path
+ style="fill:#744a54;fill-opacity:1;stroke:#744a54;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 269.22999,399.4417 c 0,0 4.78954,-16.35662 9.12111,-23.58908 3.5524,-5.93148 8.66074,-10.81211 13.52441,-15.72605 4.024,-4.0656 8.08471,-8.22771 12.89536,-11.32276 5.80107,-3.73227 12.06628,-7.36317 18.87126,-8.49207 5.50596,-0.9134 11.88204,0.48822 16.66961,1.57261 3.1747,0.71907 6.80808,0.46276 9.62921,-1.16114 1.83406,-1.05573 3.72411,-3.8021 4.30187,-5.83792 0.76057,-2.67998 -0.13185,-6.00728 -1.93576,-8.13017 -3.03403,-3.57053 -12.96954,-5.42011 -12.96954,-5.42011 0, [...]
+ id="path63630"
+ sodipodi:nodetypes="csssssssscssssssssssssccssssc" />
+ </g>
+ <g
+ id="layer17"
+ inkscape:label="ojos3"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 274.48979,398.95871 c 0,0 4.13955,-13.53875 7.74301,-19.5511 3.69512,-6.16529 8.67339,-11.55954 13.93742,-16.4539 5.61443,-5.22015 11.78528,-10.00631 18.58323,-13.55028 3.87217,-2.01868 8.03099,-3.20496 12.38882,-3.48435 4.47055,-0.28662 8.94731,0.42084 13.16312,1.93575 4.67217,1.6789 9.27383,3.88306 13.16313,6.96871 5.69678,4.51965 10.43724,10.30824 14.32457,16.4539 5.34455,8.44943 9.47328,17.81483 12.00167,27.4877 1.14796,4.39173 1.35502,13.55027 1.35502,13.55027 0,0 -6 [...]
+ id="path67428"
+ sodipodi:nodetypes="csssssssscsssssc" />
+ </g>
+ <g
+ id="layer18"
+ inkscape:label="ojos4"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 314.3663,350.17773 c -2.33914,1.61419 -4.73085,3.26325 -6.58156,5.42011 -3.61747,4.21589 -6.41804,9.18135 -8.51731,14.32458 -1.85701,4.5497 -2.78357,9.46071 -3.48436,14.32457 -0.58037,4.02809 -0.89055,8.13736 -0.58072,12.19524 0.37091,4.85783 2.90363,14.32458 2.90363,14.32458 0,0 1.44908,3.64045 2.41969,4.30705 0.84954,0.58346 12.02736,3.85876 18.34125,5.27492 5.96771,1.33852 11.80171,1.92363 17.76054,2.22612 5.54352,0.28141 15.97871,1.26633 21.9708,-0.19357 5.91594,-1.44 [...]
+ id="path70242"
+ sodipodi:nodetypes="ssssscssssscsssssssss" />
+ </g>
+ <g
+ id="layer19"
+ inkscape:label="ojos5"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:2.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 353.55558,353.9808 c 0,0 -4.55113,-0.32472 -6.28147,0.0684 -1.67452,0.38048 -4.20397,1.26512 -5.94615,2.91051 -1.74218,1.64539 -5.42224,4.70379 -7.7977,8.22007 -2.59931,3.84763 -4.20108,8.36707 -5.32332,12.87276 -1.30037,5.2209 -1.7468,10.69 -1.54861,16.06675 0.12661,3.43465 0.6825,6.89315 1.74218,10.1627 1.35237,4.1726 3.2043,8.27764 5.80726,11.8081 1.92315,2.60843 7.11389,6.92032 7.11389,6.92032 3.177,0.77776 6.67504,0.27133 10.01753,0.38714 3.85537,-0.17036 7.71075,-0. [...]
+ id="path78492"
+ sodipodi:nodetypes="csssssssccccsccccc" />
+ </g>
+ <g
+ id="layer20"
+ inkscape:label="ojos6"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path80803"
+ sodipodi:type="arc"
+ sodipodi:cx="341.92657"
+ sodipodi:cy="373.2132"
+ sodipodi:rx="5.347518"
+ sodipodi:ry="5.6136842"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 347.27409,373.2132 a 5.347518,5.6136842 0 0 1 -5.26763,5.61305 5.347518,5.6136842 0 0 1 -5.42502,-5.44534 5.347518,5.6136842 0 0 1 5.10554,-5.77576 5.347518,5.6136842 0 0 1 5.57757,5.27277 l -5.33798,0.33528 z" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 345.96747,382.04507 c -0.52605,-0.045 -0.91728,0.20181 -1.25824,0.60493 -0.32711,0.38674 -0.57973,0.90602 -0.48394,1.40341 0.11562,0.60036 0.41803,1.26055 0.94368,1.5728 0.49971,0.29684 1.2174,0.32248 1.74218,0.0726 0.46315,-0.22053 0.78564,-0.73883 0.91948,-1.23404 0.1313,-0.48582 0.11184,-1.08287 -0.16937,-1.50021 -0.35899,-0.53276 -1.05371,-0.86471 -1.69379,-0.91949 z"
+ id="path81104"
+ sodipodi:nodetypes="ssssssss" />
+ </g>
+ <g
+ id="layer21"
+ inkscape:label="ojos7"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 502.61754,353.96758 c 0,0 1.23515,-9.40721 0.27375,-13.9616 -1.20579,-5.71213 -3.84306,-11.24202 -7.39143,-15.8779 -4.13306,-5.39977 -9.53449,-10.07454 -15.60414,-13.14032 -6.28235,-3.17321 -13.49898,-4.64989 -20.53176,-4.92763 -5.26172,-0.2078 -10.8125,0.28 -15.60414,2.46382 -5.42213,2.47117 -10.07094,6.76236 -13.68784,11.49778 -4.75835,6.22987 -7.4632,13.8877 -9.85525,21.35303 -2.83428,8.84549 -4.10372,18.1523 -5.20138,27.37569 -1.3172,11.06813 -2.05038,22.25956 -1.6425 [...]
+ id="path84123"
+ sodipodi:nodetypes="cssssssssssccsssc" />
+ </g>
+ <g
+ id="layer22"
+ inkscape:label="ojos8"
+ style="display:inline">
+ <path
+ style="fill:#744a54;fill-opacity:1;stroke:#744a54;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 467.02915,310.714 c 0,0 -6.24469,0.99641 -8.76022,2.73757 -6.61529,4.57888 -14.85131,19.0261 -14.85131,19.0261 0,0 6.33033,-0.28027 9.30773,0.61595 5.8607,1.76412 11.3072,5.11014 15.94634,9.10242 4.18588,3.60222 7.80207,8.34958 10.26588,13.00344 2.46381,4.65387 4.31278,7.5869 5.33826,11.77155 0.98972,4.03874 1.18667,8.32814 0.68439,12.45593 -0.56484,4.64194 -1.21069,9.74233 -4.10635,13.41409 -4.78742,6.07056 -12.84614,8.80197 -19.98425,11.77154 -7.31589,3.04353 -15.22762, [...]
+ id="path87132"
+ sodipodi:nodetypes="cacaasaaaassssscaac" />
+ </g>
+ <g
+ id="layer23"
+ inkscape:label="ojos9"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.19753,340.00598 -7.39143,66.79667 c 0,0 9.0644,0.38848 13.55096,-0.13688 9.01468,-1.05559 18.10479,-2.70863 26.55441,-6.02265 6.87021,-2.69456 19.16298,-11.08715 19.16298,-11.08715 0,0 2.14811,-8.97556 2.19005,-13.55097 0.0414,-4.51657 -0.35645,-9.17521 -1.91629,-13.41408 -2.83271,-7.6979 -7.10724,-15.24819 -13.14033,-20.80552 -3.40731,-3.13862 -7.84064,-5.24818 -12.31906,-6.43329 -3.66335,-0.96942 -7.60932,-0.94494 -11.36091,-0.41063 -5.32799,0.75882 -15.33038,5.0645 [...]
+ id="path92268"
+ sodipodi:nodetypes="ccaacaaaaac" />
+ </g>
+ <g
+ id="layer24"
+ inkscape:label="ojos10"
+ style="display:inline">
+ <path
+ style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.47129,339.73222 26.82817,62.55344 c 8.51952,-3.52914 12.42628,-5.36693 15.5357,-6.91236 l 2.39537,-11.97686 c 1.66485,-8.14938 2.74407,-14.1317 -0.61595,-26.07534 -0.48453,-2.7093 -3.97116,-11.17671 -5.88577,-13.41409 -3.35252,-3.79435 -7.44261,-6.87827 -13.34565,-8.48646 l -7.93895,-0.75283 z"
+ id="path95549"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <g
+ id="layer25"
+ inkscape:label="ojos11"
+ style="display:inline">
+ <path
+ style="fill:#48353a;fill-opacity:1;stroke:#48353a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 426.94726,339.56284 -6.45677,56.97393 c 0,0 1.14877,4.63212 2.53225,6.50172 1.27054,1.71698 5.03029,3.96948 5.03029,3.96948 3.5926,0.125 7.90171,-0.19696 11.12136,-0.78705 4.01508,-0.77266 9.69122,-2.02184 14.4749,-3.28509 0.61056,-0.16123 1.81363,-0.54751 1.81363,-0.54751 0,0 4.30506,-5.7163 5.81734,-8.93132 2.02395,-4.30279 3.36692,-8.94581 4.24323,-13.6194 0.79648,-4.24783 1.24029,-8.6274 0.88971,-12.93501 -0.25855,-3.1768 -1.06849,-6.32428 -2.19006,-9.30773 -1.76325,- [...]
+ id="path99061"
+ sodipodi:nodetypes="ccaccacaaaaaaaac" />
+ </g>
+ <g
+ id="layer26"
+ inkscape:label="ojos12"
+ style="display:inline">
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.0252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path80803-0"
+ sodipodi:type="arc"
+ sodipodi:cx="433.45966"
+ sodipodi:cy="364.8652"
+ sodipodi:rx="3.9689827"
+ sodipodi:ry="4.0279403"
+ sodipodi:start="0"
+ sodipodi:end="6.2234252"
+ sodipodi:arc-type="slice"
+ d="m 437.42864,364.8652 a 3.9689827,4.0279403 0 0 1 -3.90969,4.02749 3.9689827,4.0279403 0 0 1 -4.02651,-3.90715 3.9689827,4.0279403 0 0 1 3.78939,-4.14423 3.9689827,4.0279403 0 0 1 4.13972,3.78333 l -3.96189,0.24056 z"
+ inkscape:transform-center-x="5.6407799"
+ inkscape:transform-center-y="0.9722915" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.685875px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 427.15746,373.80187 c -0.36481,-0.0305 -0.63612,0.13689 -0.87257,0.41035 -0.22685,0.26234 -0.40204,0.6146 -0.33561,0.952 0.0802,0.40725 0.2899,0.85509 0.65443,1.06691 0.34654,0.20136 0.84425,0.21875 1.20818,0.0492 0.32119,-0.1496 0.54483,-0.50119 0.63764,-0.83711 0.0911,-0.32956 0.0776,-0.73457 -0.11745,-1.01767 -0.24896,-0.3614 -0.73073,-0.58657 -1.17462,-0.62373 z"
+ id="path81104-5"
+ sodipodi:nodetypes="ssssssss" />
+ </g>
+ <g
+ id="layer10"
+ inkscape:label="nariz4"
+ style="display:inline">
+ <path
+ style="fill:#f4eae0;fill-opacity:1;stroke:#f4eae0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 437.09305,464.77432 6.19441,12.77597 -1.35503,17.03463 -18.97038,17.2282 -4.06508,6.38798 -13.47938,5.16188 -7.86302,-0.31452 -9.12111,-13.83893 -3.21859,-31.85282 19.74468,-13.55027 z"
+ id="path944" />
+ </g>
+ <g
+ id="layer29"
+ inkscape:label="nariz3"
+ style="display:inline">
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 398.72682,507.13452 5.84558,-4.80659 1.03256,-3.50877 14.44067,-2.70335 c 0,0 -0.65017,2.29272 -0.51329,2.29272 0.13688,0 2.7522,1.30613 2.7522,1.30613 l -3.36815,2.04739 -13.55097,4.41433 -6.57016,1.5741 z"
+ id="path121669" />
+ </g>
+ <g
+ id="layer27"
+ inkscape:label="nariz1"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 330.43305,494.19777 16.4539,15.29244 c 0,0 10.35541,11.75749 17.42178,14.32458 6.91404,2.51175 14.87381,1.73059 22.06759,0.19357 4.99773,-1.06782 13.93742,-6.38798 13.93742,-6.38798 l 4.64581,-6.38799"
+ id="path103332"
+ sodipodi:nodetypes="ccaacc" />
+ <path
+ style="fill:none;stroke:#684650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.996078"
+ d="m 410.76681,511.42597 12.19524,0.38715 c 0,0 7.71212,-4.99359 11.03379,-8.13016 2.49884,-2.35959 5.00722,-4.88155 6.58156,-7.93659 1.49843,-2.90773 2.21151,-6.22833 2.51648,-9.48519 0.33174,-3.54276 -0.0128,-7.17083 -0.7743,-10.64664 -0.58994,-2.69265 -2.90363,-7.74302 -2.90363,-7.74302 l -2.3229,-3.0972"
+ id="path103334"
+ sodipodi:nodetypes="ccaaaacc" />
+ <path
+ style="fill:none;stroke:#694650;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 392.18358,521.49188 c 0,0 9.02373,1.69497 13.55027,1.35503 3.38647,-0.25432 6.98431,-0.72983 9.87234,-2.51648 3.19022,-1.9736 7.35586,-8.51731 7.35586,-8.51731"
+ id="path103336"
+ sodipodi:nodetypes="caac" />
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 397.21654,500.68254 c 0,0 1.56844,-2.31284 2.80684,-2.71006 1.67703,-0.53792 4.20555,-0.66075 5.22653,0.77431 0.70428,0.98992 -0.67751,3.58114 -0.67751,3.58114 l -6.96871,5.42011 c 0,0 -7.10496,0.97495 -9.29162,-1.25824 -2.58985,-2.64496 -2.18162,-7.44905 -1.25824,-11.0338 0.75029,-2.91278 2.86558,-5.49222 5.22653,-7.35586 3.24944,-2.56498 7.3859,-4.38916 11.51774,-4.6458 1.63241,-0.10139 3.1146,1.41541 4.74259,1.25824 2.42726,-0.23433 4.15668,-2.93618 6.58156,-3.194 3.10 [...]
+ id="path103338"
+ sodipodi:nodetypes="caaccaaaaaaaaccacc" />
+ <path
+ style="fill:#f7b2c7;fill-opacity:1;stroke:#67464f;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 397.60369,507.74804 c 0,0 3.22164,1.4085 4.93617,1.45181 2.48761,0.0628 5.10779,-0.49153 7.25907,-1.74218 1.22343,-0.71124 2.90363,-3.0972 2.90363,-3.0972 0,0 0.33123,2.3459 1.25824,2.71005 1.58926,0.62429 3.42269,-0.85254 4.74259,-1.93575 1.67391,-1.37374 3.58115,-5.42011 3.58115,-5.42011 v 0"
+ id="path103340"
+ sodipodi:nodetypes="caacaacc" />
+ </g>
+ <g
+ id="layer37"
+ inkscape:label="sombra5"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#dad2d1;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 410.69422,513.43431 8.42052,0.29037 c -0.89939,1.28114 -1.55467,3.28485 -6.17021,5.80726 -6.91095,1.97763 -10.46171,1.62023 -13.62286,0.99207 l 2.3229,-1.33083 4.98457,-6.79933 5.81974,-6.8762 0.39353,1.12069 c 0.37206,0.43706 0.38352,1.01034 1.71098,1.08647 2.01068,-0.18971 2.20166,-0.657 2.9771,-1.03514 0,0 1.51372,-1.1186 2.13873,-1.81364 0.90858,-1.01039 1.60235,-2.20024 2.29271,-3.37063 1.05872,-1.79486 2.82312,-5.57779 2.82312,-5.57779 0,0 1.21845,-0.77832 1.77942,- [...]
+ id="path78067"
+ sodipodi:nodetypes="ccccccccccaacaaaaaaaaaaaaaaaccccccccccc"
+ clip-path="url(#clipPath81911)" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 412.26067,462.13575 2.66801,18.91099 1.45181,-0.12098 c 0,0 1.5728,0.0726 1.63329,0.0726 0.0605,0 1.45182,0.18148 1.50021,0.18148 0.0484,0 0.7864,0.18147 0.7864,0.18147 l 1.597,0.49604 0.87109,0.41135 0.83479,0.43554 0.7864,0.54443 0.84689,0.68962 1.42762,1.47601 1.19775,1.69378 0.67751,1.50021 0.39925,1.70588 v 1.04047 l -0.18148,0.7985 -0.38715,0.738 -0.7259,0.87109 -0.93158,0.8106 -1.34293,0.94368 -0.5846,0.41111 -2.65779,5.22677 -1.17355,2.00834 -1.00417,1.39133 -0.66 [...]
+ id="path82108"
+ sodipodi:nodetypes="cccssccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+ </g>
+ <g
+ id="layer28"
+ inkscape:label="nariz2"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#684650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 426.39801,475.54195 c -0.75398,0.59916 -1.35987,1.76916 -1.06466,2.68585 0.4259,1.32251 2.13044,2.42705 3.50855,2.25032 1.5569,-0.19965 3.24382,-1.8913 3.19399,-3.46016 -0.0308,-0.96934 -1.1804,-1.71605 -2.10513,-2.00835 -1.1355,-0.35893 -2.60041,-0.20856 -3.53275,0.53234 z"
+ id="path103438"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#67464f;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.992157"
+ d="m 430.82605,486.45475 c -0.65127,0.89445 -0.76426,2.38207 -0.16938,3.31498 0.61281,0.96104 2.06309,1.5551 3.1698,1.28244 0.94459,-0.23272 1.55756,-1.31089 1.88736,-2.22612 0.47581,-1.3204 1.11149,-3.42001 -0.0484,-4.21026 -1.42613,-0.97165 -3.82362,0.44391 -4.83938,1.83896 z"
+ id="path103440"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694750;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 369.92242,501.94078 c -1.74253,0.11096 -3.65435,0.98243 -4.64581,2.41969 -0.94074,1.36374 -1.53205,3.57979 -0.58073,4.93617 1.5413,2.19757 5.2778,2.63962 7.8398,1.83896 1.28636,-0.40201 2.59478,-1.65764 2.71006,-3.00041 0.18604,-2.16706 -1.79343,-4.14886 -3.48436,-5.5169 -0.50786,-0.41089 -1.18702,-0.71902 -1.83896,-0.67751 z"
+ id="path103342"
+ sodipodi:nodetypes="aaaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 370.74511,482.34128 c -1.06402,0.75907 -1.98064,2.33168 -1.59699,3.58114 0.32323,1.05268 1.70828,1.66608 2.80684,1.74218 1.549,0.1073 3.78147,-0.40979 4.25865,-1.88736 0.44213,-1.36905 -0.89961,-3.06587 -2.17772,-3.72633 -0.97829,-0.50553 -2.39433,-0.34916 -3.29078,0.29037 z"
+ id="path103388"
+ sodipodi:nodetypes="aaaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.64582,486.0676 c -0.36057,1.41343 1.2673,3.22088 2.71005,3.43596 1.39859,0.2085 3.28975,-1.0191 3.48436,-2.41969 0.1609,-1.15792 -1.09054,-2.43233 -2.22612,-2.71005 -1.39705,-0.34166 -3.61279,0.30019 -3.96829,1.69378 z"
+ id="path103390"
+ sodipodi:nodetypes="aaaaa" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.06308,514.48996 c 0,0 0.92034,-2.35683 1.98414,-2.66166 1.36499,-0.39114 3.41207,0.24216 3.9683,1.5486 0.44477,1.04465 -0.58195,2.27156 -1.30664,3.1456 -0.35696,0.43053 -1.40342,0.91948 -1.40342,0.91948"
+ id="path103392"
+ sodipodi:nodetypes="caaac" />
+ </g>
+ <g
+ id="layer31"
+ inkscape:label="SOMBRAS"
+ style="display:inline">
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 547.81813,821.92077 -14.71173,6.58156 c 0,0 -20.04642,9.4511 -20.13183,18.58323 -0.0401,4.28964 9.8648,4.6531 9.29162,8.90446 -1.22993,9.12259 -40.07226,7.0871 -40.65082,18.58323 -0.23206,4.6112 16.368,3.85278 12.38882,6.19441 -8.7326,5.13888 -115.3747,51.08568 -115.37088,51.10388 22.3368,-2.2537 41.71738,-14.30148 55.55041,-19.96007 11.32914,-1.74424 22.65827,-2.80865 33.98741,-5.52947 14.55542,-1.8339 26.06489,-10.97808 38.99618,-16.70988 18.06089,-13.95357 25.08208,-25 [...]
+ id="path949"
+ sodipodi:nodetypes="ccassscccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 445.3366,835.93267 c 0,0 -16.17886,14.32145 -25.27818,20.05735 -15.42858,9.72566 -49.16813,24.00334 -49.16813,24.00334 -4.44886,2.75522 -5.38193,1.67502 -5.87368,0.11339 l -7.23844,-6.64798 c 18.35192,-6.49248 36.75539,-13.2943 55.46787,-21.95016 z"
+ id="path951"
+ sodipodi:nodetypes="caccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 272.35476,872.90958 c 0,0 0.57084,7.71915 0.10249,11.53601 -0.2354,1.91841 -1.45182,5.61369 -1.45182,5.61369 l 25.1648,1.88735 c 0.47994,-2.9835 0.36177,-4.37206 0.49764,-6.43805 -0.55144,-2.5936 -1.0986,-5.18806 -2.27941,-7.65579 0,0 -5.84602,-0.64508 -8.71988,-1.24687 -4.50803,-0.94399 -13.31382,-3.69634 -13.31382,-3.69634 z"
+ id="path953"
+ sodipodi:nodetypes="caccccac" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 226.28954,815.53279 c 0,0 -7.95288,2.68162 -12.00168,3.7747 -3.38519,0.91392 -10.25948,2.32291 -10.25948,2.32291 0,0 1.3589,13.85165 3.48435,20.4222 1.2834,3.96745 5.5169,11.22737 5.5169,11.22737 5.56183,-2.04316 6.86738,-4.39034 9.00125,-6.67835 3.87527,-4.01314 6.35463,-11.0035 9.00125,-17.2282 z"
+ id="path955"
+ sodipodi:nodetypes="cacacccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 220.99255,764.33128 -8.78502,16.50455 c 2.97496,0.55016 6.51461,0.25328 10.21418,-0.28348 2.48336,-0.80195 1.67568,-0.38328 9.9428,-3.33373 l 6.71642,-12.83266 -8.92023,0.16037 z"
+ id="path957"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <g
+ id="layer32"
+ inkscape:label="SOMBRAS 1"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 298.02413,877.42421 c 2.73354,7.81873 1.97618,9.48503 2.11154,13.52964 l 35.91107,-2.05603 25.81194,-4.66526 c -2.00278,-2.61499 -5.49159,-5.52718 -9.30134,-8.50356 l -23.63967,3.7249 z"
+ id="path960"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 232.36854,834.45015 c -1.72206,4.96881 -3.87893,9.57529 -6.69495,13.63246 -2.98321,3.45811 -6.32185,6.34751 -10.21656,8.34723 0,0 7.00444,12.3255 12.18753,16.98196 6.62044,5.94777 14.88148,10.07695 23.22904,13.16312 5.05634,1.86938 15.87318,3.0972 15.87318,3.0972 1.94325,-2.09404 3.81964,-10.11169 1.67265,-19.47249 -5.17626,-1.71992 -8.96515,-3.76359 -15.4165,-9.5638 z"
+ id="path962"
+ sodipodi:nodetypes="cccaacccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 210.58644,784.48054 c 0,0 -4.33631,9.886 -5.54524,15.11465 -1.37844,5.96186 -1.88391,18.2605 -1.88391,18.2605 3.64141,0.81129 13.27584,-3.06759 20.71256,-5.22654 0,0 -0.53922,-8.93795 0.1721,-13.32147 0.97292,-5.99566 5.53836,-17.36022 5.53836,-17.36022 0,0 -6.69889,2.0907 -10.1627,2.51648 -2.92174,0.35915 -8.83117,0.0166 -8.83117,0.0166 z"
+ id="path964"
+ sodipodi:nodetypes="caccacac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 222.12767,760.75097 c 2.04496,0.68598 14.10806,0.16978 21.88374,0.16808 35.976,-34.5304 40.26607,-47.39531 50.90058,-65.11259 -10.98778,-6.04029 -18.83771,-12.86789 -24.97123,-19.16397 0,0 5.48103,10.16148 4.93618,15.58282 -1.5279,15.20293 -12.85105,28.0321 -22.26116,40.07009 -8.56139,10.95226 -30.48811,28.45557 -30.48811,28.45557 z"
+ id="path966"
+ sodipodi:nodetypes="ccccaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 320.27035,703.64625 c 0,0 11.9013,8.35426 14.61494,14.71173 4.09221,9.58716 0.7743,31.26241 0.7743,31.26241 0,0 2.56105,-10.59133 3.38757,-15.96996 1.43253,-9.32234 2.71005,-28.16521 2.71005,-28.16521 -7.31232,-0.0128 -14.43105,-0.80008 -21.48686,-1.83897 z"
+ id="path968"
+ sodipodi:nodetypes="cacacc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 352.50064,704.8077 5.90405,48.10347 c 0,0 -0.49128,-14.99406 0.67751,-22.35795 1.11707,-7.03805 2.1625,-14.51487 6.00083,-20.51898 2.90655,-4.54658 7.55844,-7.88631 12.19525,-10.64664 2.5438,-1.51434 8.32374,-3.09721 8.32374,-3.09721 1.71361,-2.54812 2.03574,-5.32816 2.22611,-8.13016 0,0 -10.62032,8.20645 -16.64747,11.03379 -5.88629,2.76125 -18.68002,5.61368 -18.68002,5.61368 z"
+ id="path1083"
+ sodipodi:nodetypes="ccaaaccac" />
+ </g>
+ <g
+ id="layer33"
+ inkscape:label="SOMBRAS 2"
+ style="display:inline">
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 311.69279,694.98153 c 0,0 21.20519,4.69219 31.9133,4.0926 8.86972,-0.49666 17.88896,-2.46095 25.89066,-6.31989 7.44831,-3.59207 13.96971,-9.14786 19.60849,-15.19636 7.11032,-7.62698 12.69856,-16.69142 17.38356,-26.0069 1.90749,-3.79279 4.28047,-11.99548 4.28047,-11.99548 0,0 -10.47172,4.15202 -15.81432,5.92586 -5.7265,1.9013 -17.38356,5.04789 -17.38356,5.04789 0,0 -3.26415,8.74334 -6.08337,12.37291 -7.32531,9.43088 -16.67786,17.69547 -27.23881,23.26933 -9.94266,5.24753 -3 [...]
+ id="path37537"
+ sodipodi:nodetypes="caaaacacaac" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 315.02567,516.1685 c 0,0 8.11408,7.52388 11.63467,11.77154 3.8928,4.69674 10.40275,15.05663 10.40275,15.05663 l 0.13689,-19.09454 c -7.39144,-2.48908 -14.78288,-4.89781 -22.17431,-7.73363 z"
+ id="path37541"
+ sodipodi:nodetypes="caccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 396.60521,531.49889 0.65016,2.05317 c -0.50841,1.64487 -1.38541,3.23708 -2.53224,4.79074 -1.27909,1.80275 -2.59144,3.6166 -4.14057,5.50936 -3.42223,2.80405 -3.85636,2.02238 -5.16716,2.29271 -3.92172,-11.13692 -3.3389,-8.6049 -4.89341,-12.55859 l 6.09109,2.87445 z"
+ id="path37788"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 387.05794,550.69608 c 5.24841,-0.82446 8.96129,-4.92956 11.66889,-9.64993 3.16683,3.47899 4.59204,7.02643 6.57016,10.50542 -1.83514,2.1826 -3.46722,4.59796 -5.64624,5.7489 -4.67848,2.29176 -7.33873,1.6093 -10.36853,1.47144 -0.61183,-2.95115 -1.43945,-5.47069 -2.22428,-8.07583 z"
+ id="path37790"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:1;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 390.52954,563.38467 c 2.56922,-0.0156 5.13266,-0.0269 8.70898,-0.79778 2.48973,-0.6753 4.1443,-2.3528 6.03498,-3.74696 l 3.51875,12.25975 c -2.74256,2.86412 -5.43184,5.58839 -7.1618,5.79445 -3.13945,0.87612 -6.28817,1.74297 -10.18427,1.86244 -0.12873,-10.02199 -0.57481,-11.37611 -0.91664,-15.3719 z"
+ id="path37792"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#96636a;fill-opacity:1;stroke:#96636a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 391.30116,587.75591 c 3.51978,1.44667 7.46595,2.19057 12.07952,2.36115 3.84475,0.13634 7.83163,0.52185 10.60809,-1.30034 l -4.1748,-13.68784 c 0,0 -5.03409,3.74951 -7.80207,5.20138 -0.79345,0.41618 -1.63058,0.76807 -2.49803,0.99237 -2.68337,0.69386 -8.24692,1.0608 -8.24692,1.0608 z"
+ id="path37794"
+ sodipodi:nodetypes="ccccaacc" />
+ <path
+ style="fill:#dad2d1;fill-opacity:0.996364;stroke:#dad2d1;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 391.30117,591.79383 c 0,0 -0.78111,10.57858 -0.95815,15.87788 -0.17521,5.2442 -0.10266,15.74103 -0.10266,15.74103 l 25.80158,-10.4712 c 0,0 0.68403,-7.53051 0.47908,-11.29247 -0.16885,-3.0992 -1.40301,-9.20507 -1.40301,-9.20507 0,0 -2.47918,1.04873 -3.79837,1.19769 -6.1974,0.69982 -18.64969,-1.50567 -18.64969,-1.50567 z"
+ id="path37796"
+ sodipodi:nodetypes="caccacasc" />
+ </g>
+ <g
+ id="layer38"
+ inkscape:label="SOMBRAS 4"
+ style="display:inline">
+ <path
+ style="fill:#908482;fill-opacity:1;stroke:#908482;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 174.79851,270.03756 17.80892,-21.68044 -11.03379,-6.19441 -19.74468,-0.19357 c 0,0 8.05542,8.61931 10.36719,13.92401 1.91521,4.39475 2.60236,14.14441 2.60236,14.14441 z"
+ id="path84668"
+ sodipodi:nodetypes="ccccac" />
+ <path
+ style="fill:#908482;fill-opacity:1;stroke:#908482;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 491.94102,223.45401 9.64993,-7.25455 9.78681,-1.23191 -3.90104,27.581 -5.0645,-4.51699 -10.40276,-14.23535 z"
+ id="path84798" />
+ </g>
+ <g
+ id="layer39"
+ inkscape:label="orejas"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 195.39394,245.83363 c 0,0 -3.45588,-4.19123 -5.7489,-5.54357 -2.13818,-1.26102 -4.66627,-1.79943 -7.11768,-2.19005 -2.56868,-0.40932 -5.20686,-0.31168 -7.80207,-0.13688 -2.85536,0.19231 -5.66572,0.81707 -8.48646,1.30034 -3.50152,0.59991 -10.47119,1.98474 -10.47119,1.98474 l -10.40276,2.12161 c -0.81574,0.68439 -1.30941,1.36879 0.75283,2.05318 v 0 l 8.07582,-0.0684 13.00345,0.13684 c 0,0 5.16735,-0.31374 7.73363,-0.0685 2.17787,0.20818 4.41163,0.46408 6.43329,1.30035 1.946 [...]
+ id="path87054"
+ sodipodi:nodetypes="caaaaccccccaaasaacscccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 487.49247,220.16893 21.14772,-6.6386 7.04924,-1.9163 c 0,0 0.34428,6.95974 -0.0684,10.40275 -0.50773,4.23597 -1.40696,8.47572 -2.94289,12.45594 -1.25722,3.25796 -5.0645,9.17086 -5.0645,9.17086 l -0.20532,0.88971 4.38011,10.40276 c 0,0 0.27376,2.66913 0,2.73757 -0.27375,0.0684 -5.47513,-1.43723 -5.47513,-1.43723 l 0.0684,-3.28508 -5.68045,-18.34171 4.85918,6.84392 0.61596,-0.13688 4.10635,-18.41014 c 0,0 1.47984,-5.02104 -0.0684,-6.57017 -1.46762,-1.46845 -4.20331,-0.52774 [...]
+ id="path92311"
+ sodipodi:nodetypes="cccaacccsccccccaaaacc" />
+ </g>
+ <g
+ id="layer30"
+ inkscape:label="casco1"
+ style="display:inline">
+ <path
+ style="fill:#ffe300;fill-opacity:0.996078;stroke:#694650;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 144.79433,311.2691 439.41595,-26.7134 -30.97204,-7.74301 -28.262,-11.61451 c -14.77268,-6.07097 -33.64256,-17.60462 -41.03797,-33.68211 -5.07051,-11.0232 0.14051,-24.43766 0.77431,-36.39216 0.49741,-9.38182 -5.60961,-18.05537 -10.06592,-26.32624 -7.23676,-13.43137 -15.48728,-26.83463 -26.71339,-37.16646 -8.5558,-7.87423 -30.24588,-8.00899 -42.58657,-17.03463 -8.36237,-6.116 -11.35719,-17.921827 -19.74468,-24.003335 -11.77674,-8.538948 -26.13513,-14.92456 -40.65082,-15.873 [...]
+ id="path1910"
+ sodipodi:nodetypes="cccsasasaaaacaaccaac" />
+ </g>
+ <g
+ id="layer40"
+ inkscape:label="casco2"
+ style="display:inline">
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#ccb500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 257.33142,117.37324 c 0,0 14.66769,-3.34433 21.83211,-1.9163 11.50806,2.29381 31.20828,16.28853 31.20828,16.28853 -7.95406,-11.30046 -14.11739,-19.76237 -22.23496,-30.4088 -3.0627,1.22517 -10.9099,4.15792 -10.82118,4.4019 -0.36669,-0.45836 -13.96143,6.97356 -19.98425,11.63467 z"
+ id="path94173"
+ sodipodi:nodetypes="cacccc" />
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#ccb500;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.996078"
+ d="m 410.77212,118.81046 c 0,0 8.43736,17.37195 11.77155,26.41754 3.44769,9.35353 6.18704,18.45001 9.03397,27.10192 2.73472,8.31091 7.39144,25.18563 7.39144,25.18563 0,0 -1.64913,-34.41237 -5.20138,-51.19252 -1.03392,-4.88403 -2.39479,-9.78348 -4.65387,-14.23536 -0.81364,-1.60341 -3.1482,-4.38011 -3.1482,-4.38011 z"
+ id="path94175"
+ sodipodi:nodetypes="csscaacc" />
+ <path
+ style="fill:#cbb400;fill-opacity:1;stroke:#cbb400;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 334.66772,259.11084 114.1566,-6.9808 c -19.16051,-2.69367 -30.65772,-5.90983 -57.55737,-8.07583 -21.52187,3.24857 -37.73931,10.03343 -56.59923,15.05663 z"
+ id="path94177"
+ sodipodi:nodetypes="cccc" />
+ </g>
+ <g
+ id="layer41"
+ inkscape:label="casco3"
+ style="display:inline">
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 304.28072,264.85973 164.66473,-10.95027 -75.55689,-0.82127 z"
+ id="path94180" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 286.87072,99.523031 21.20439,28.623829 26.42303,26.81018 -23.32583,-29.52024 z"
+ id="path94182"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 381.34336,95.819779 c 0,0 8.10743,9.275991 11.61452,14.324571 5.94104,8.55232 10.85071,17.78486 15.87317,26.90697 5.59522,10.16239 15.87318,30.97205 15.87318,30.97205 l 16.64748,37.55361 c 0,0 -3.51333,-11.34761 -5.22654,-17.03463 -3.61001,-11.98342 -6.33752,-24.25485 -10.64664,-36.00501 -4.9536,-13.50755 -17.42178,-39.48936 -17.42178,-39.48936 L 397.99084,98.916983 Z"
+ id="path94184"
+ sodipodi:nodetypes="caaccaaccc" />
+ <path
+ style="fill:#694650;fill-opacity:1;stroke:#694650;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 368.06606,84.180225 c 0,0 6.39675,3.886923 9.10241,6.433285 1.61991,1.524537 4.17489,5.206269 4.17489,5.206269 l 16.64748,3.097204 -8.77707,-10.082892 -13.89316,-8.897097 z"
+ id="path94186"
+ sodipodi:nodetypes="caccccc" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/pom.xml b/plc4j/integrations/apache-hop/plc4x-hop-transformer/pom.xml
new file mode 100644
index 0000000000..e707e0d206
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-apache-hop</artifactId>
+ <version>0.11.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4x-hop-transform</artifactId>
+ <packaging>jar</packaging>
+ <name>PLC4J: Integrations: Apache Hop: Transform</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>8</source>
+ <target>8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.jandex</groupId>
+ <artifactId>jandex-maven-plugin</artifactId>
+ <version>1.0.8</version>
+ <executions>
+ <execution>
+ <id>make-index</id>
+ <goals>
+ <goal>jandex</goal>
+ </goals>
+ <!-- phase is 'process-classes by default' -->
+ <configuration>
+ <!-- Nothing needed here for simple cases -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <ignoredDependencies>
+ <dependency>io.netty:netty-common:jar:4.1.89.Final</dependency>
+ <dependency>io.netty:netty-all:jar:4.1.89.Final</dependency>
+ <dependency>commons-lang:commons-lang:jar:2.6</dependency>
+ <dependency>xml-apis:xml-apis:jar:1.4.01</dependency>
+ <dependency>org.apache.plc4x:plc4j-spi:jar:${project.version}</dependency>
+ <dependency>com.fasterxml.jackson.core:jackson-annotations:jar:2.14.2</dependency>
+ </ignoredDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-core</artifactId>
+ <version>${hop.version}</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-engine</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hop</groupId>
+ <artifactId>hop-ui</artifactId>
+ <version>${hop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ <version>${netty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>plc4j-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>hop-plc4x-metadata</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
+ <version>3.114.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>plc4j-driver-s7</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.12.0</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEvent.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEvent.java
new file mode 100644
index 0000000000..e87262ec01
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEvent.java
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xevent;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.hop.core.CheckResult;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginException;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.RowDataUtil;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
+import org.apache.hop.pipeline.transform.ITransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xWrapperConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
+import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
+import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.s7.events.S7ModeEvent;
+import org.apache.plc4x.java.s7.readwrite.ModeTransitionType;
+
+/**
+ * Transform That contains the basic skeleton needed to create your own plugin
+ *
+ */
+public class Plc4xEvent extends BaseTransform<Plc4xEventMeta, Plc4xEventData> implements ITransform {
+
+ public static String FIELD_MODE_EVENT = "MODE";
+ public static String FIELD_USER_EVENT = "USR";
+ public static String FIELD_SYS_EVENT = "SYS";
+ public static String FIELD_ALARM_EVENT = "ALM";
+
+
+ private static final Class<?> PKG = Plc4xEvent.class; // Needed by Translator
+
+ private Plc4xConnection connmeta = null;
+ private Plc4xWrapperConnection connwrapper = null;
+ private PlcReadRequest readRequest = null;
+ private PlcConsumerRegistration registerMode = null;
+ private PlcConsumerRegistration registerUser = null;
+ private PlcConsumerRegistration registerSys = null;
+ private PlcConsumerRegistration registerAlarm = null;
+ private PlcSubscriptionRequest subsbuild = null;
+ private PlcSubscriptionResponse subresponse = null;
+
+ private static final ReentrantLock lock = new ReentrantLock();
+
+ private static final String dummy = "dummy";
+
+ public Plc4xEvent(TransformMeta transformMeta, Plc4xEventMeta meta, Plc4xEventData data, int copyNr, PipelineMeta pipelineMeta,
+ Pipeline pipeline ) {
+ super( transformMeta, meta, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ /*
+ * Including Date and Time field for every row
+ *
+ * @param meta Meta data from user dialog
+ * @param remarks Error registers
+ * @param origin transform instance name
+ */
+ public static final RowMetaAndData buildRow(
+ Plc4xEventMeta meta, List<ICheckResult> remarks, String origin) throws HopPluginException {
+ IRowMeta rowMeta = new RowMeta();
+ Object[] rowData = RowDataUtil.allocateRowData(2);
+ int index = 0;
+
+ return new RowMetaAndData(rowMeta, rowData);
+ }
+
+ /*
+ * 1. Block the other instances by means of a lock.
+ * 2. Try to locate an existing connection.
+ * 3. If it doesn't exist, it tries to take control of the routine to
+ * create an instance of PlcConnection and his wrapper.
+ * 4. Register the connection wrapper for global access.
+ * 5. If the connection to the PLC is made, then it creates the query
+ * and executes it.
+ *
+ */
+ @Override
+ public boolean processRow() throws HopException {
+ Object[] r = getRow(); // Get row from input rowset & set row busy!
+ setLogLevel(LogLevel.DEBUG);
+
+ if ((!meta.isNeverEnding() && data.rowsWritten >= data.rowLimit) && !isStopped()) {
+ setOutputDone(); // signal end to receiver(s)
+ return false;
+ }
+
+ lock.lock(); //(01)
+ try {
+ IHopMetadataProvider metaprovider = getMetadataProvider();
+ connmeta = metaprovider.getSerializer(Plc4xConnection.class).load(meta.getConnection());
+ if (connwrapper == null) {
+ connwrapper = (Plc4xWrapperConnection) getPipeline().getExtensionDataMap().get(meta.getConnection()); //(02)
+ if (connwrapper != null) connwrapper.retain();
+ };
+
+ if (connmeta == null){
+ logError(
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.Log.SetMetadata",
+ meta.getConnection()));
+ }
+
+ if ((connmeta != null) && (connwrapper == null)){
+ readRequest = null;
+ try{
+ PlcConnection conn = new DefaultPlcDriverManager().getConnection(connmeta.getUrl()); //(03)
+ if (conn.isConnected()) {
+ connwrapper = new Plc4xWrapperConnection(conn);
+ getPipeline().getExtensionDataMap().put(meta.getConnection(), connwrapper); //(04)
+ }
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Unable to create connection to PLC. " + ex.getMessage());
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+
+ if ((connmeta != null) && (connwrapper != null)){
+ if (connwrapper.getConnection().isConnected()){
+ if (readRequest == null){
+ final PlcSubscriptionRequest.Builder subscription = connwrapper.getConnection().subscriptionRequestBuilder(); //(05)
+ if (meta.isModeEvent()) subscription.addEventTagAddress(FIELD_MODE_EVENT, FIELD_MODE_EVENT);
+ if (meta.isUserEvent()) subscription.addEventTagAddress(FIELD_USER_EVENT, FIELD_USER_EVENT);
+ if (meta.isSysEvent()) subscription.addEventTagAddress(FIELD_SYS_EVENT, FIELD_SYS_EVENT);
+ if (meta.isAlarmEvent()) subscription.addEventTagAddress(FIELD_ALARM_EVENT, FIELD_ALARM_EVENT);
+
+ subsbuild = subscription.build();
+
+ }
+ try {
+ subresponse = subsbuild.execute().get();
+
+ if (meta.isModeEvent() && subresponse.getResponseCode(FIELD_MODE_EVENT) == PlcResponseCode.OK) {
+ registerMode =
+ subresponse
+ .getSubscriptionHandle(FIELD_MODE_EVENT)
+ .register(msg -> {
+ System.out.println("******** S7ModeEvent ********");
+ Map<String, Object> map = ((S7ModeEvent) msg).getMap();
+ map.forEach((x, y) -> {
+ System.out.println(x + " : " + y);
+ });
+ short currentmode = (short)
+ map.get(S7ModeEvent.Fields.CURRENT_MODE.name());
+ System.out.println("CURRENT_MODE MSG: " + ModeTransitionType.enumForValue(currentmode).name());
+ System.out.println("****************************");
+ });
+ }
+
+ if (meta.isUserEvent() && subresponse.getResponseCode(FIELD_USER_EVENT) == PlcResponseCode.OK) {
+ registerUser =
+ subresponse
+ .getSubscriptionHandle(FIELD_USER_EVENT)
+ .register(msg -> {
+ System.out.println("******** S7ModeEvent ********");
+ Map<String, Object> map = ((S7ModeEvent) msg).getMap();
+ map.forEach((x, y) -> {
+ System.out.println(x + " : " + y);
+ });
+ short currentmode = (short)
+ map.get(S7ModeEvent.Fields.CURRENT_MODE.name());
+ System.out.println("CURRENT_MODE MSG: " + ModeTransitionType.enumForValue(currentmode).name());
+ System.out.println("****************************");
+ });
+ }
+
+ if (meta.isSysEvent() && subresponse.getResponseCode(FIELD_SYS_EVENT) == PlcResponseCode.OK) {
+ registerSys =
+ subresponse
+ .getSubscriptionHandle(FIELD_SYS_EVENT)
+ .register(msg -> {
+ System.out.println("******** S7ModeEvent ********");
+ Map<String, Object> map = ((S7ModeEvent) msg).getMap();
+ map.forEach((x, y) -> {
+ System.out.println(x + " : " + y);
+ });
+ short currentmode = (short)
+ map.get(S7ModeEvent.Fields.CURRENT_MODE.name());
+ System.out.println("CURRENT_MODE MSG: " + ModeTransitionType.enumForValue(currentmode).name());
+ System.out.println("****************************");
+ });
+ }
+
+ if (meta.isAlarmEvent() && subresponse.getResponseCode(FIELD_ALARM_EVENT) == PlcResponseCode.OK) {
+ registerAlarm =
+ subresponse
+ .getSubscriptionHandle(FIELD_ALARM_EVENT)
+ .register(msg -> {
+ System.out.println("******** S7ModeEvent ********");
+ Map<String, Object> map = ((S7ModeEvent) msg).getMap();
+ map.forEach((x, y) -> {
+ System.out.println(x + " : " + y);
+ });
+ short currentmode = (short)
+ map.get(S7ModeEvent.Fields.CURRENT_MODE.name());
+ System.out.println("CURRENT_MODE MSG: " + ModeTransitionType.enumForValue(currentmode).name());
+ System.out.println("****************************");
+ });
+ }
+
+ } catch (Exception ex) {
+ setErrors(1L);
+ logError("Unable read from PLC. " + ex.getMessage());
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC is not connected.");
+ setOutputDone();
+ return false;
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC connection don't exist.");
+ setOutputDone();
+ return false;
+ }
+
+
+ r = data.outputRowMeta.cloneRow(data.outputRowData);
+ logBasic("Tamano de los datos: " + r.length);
+ data.prevDate = data.rowDate;
+ data.rowDate = new Date();
+
+
+ putRow(data.outputRowMeta, r ); // return your data
+ data.rowsWritten++;
+ return true;
+ }
+
+
+ @Override
+ public boolean init() {
+ try {
+ if(super.init()){
+ // Determine the number of rows to generate...
+ data.rowLimit = Const.toLong(resolve(meta.getRowLimit()), -1L);
+
+ if (data.rowLimit < 0L) { // Unable to parse
+ logError(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Wrong.RowLimit.Number"));
+ return false; // fail
+ }
+
+ // Create a row (constants) with all the values in it...
+ List<ICheckResult> remarks = new ArrayList<>(); // stores the errors...
+ RowMetaAndData outputRow = buildRow(meta, remarks, getTransformName());
+ if (!remarks.isEmpty()) {
+ for (int i = 0; i < remarks.size(); i++) {
+ CheckResult cr = (CheckResult) remarks.get(i);
+ logError(cr.getText());
+ }
+ return false;
+ }
+
+ data.outputRowData = outputRow.getData();
+ data.outputRowMeta = outputRow.getRowMeta();
+
+ return true;
+ }
+ return false;
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Error initializing transform", ex);
+ return false;
+ }
+ }
+
+ /*
+ * Here, must perform the cleaning of any resource, main of the connection to
+ * the associated PLC.
+ */
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ logBasic("Cleanup. Release connection.");
+ if (connwrapper != null)
+ connwrapper.release();
+ }
+
+
+ /*
+ * Here, must perform the cleaning of any resource.
+ * 1. Check if we have reference to wrapper.
+ * 2. Release de reference to object.
+ * 3. The lastone remove the global reference to connection wrapper.
+ * 4. Clear local references.
+ */
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (connwrapper != null) {
+ logBasic("Dispose. Release connection: " + connwrapper.refCnt());
+ connwrapper.release();
+ if (!connwrapper.getConnection().isConnected()){
+ getPipeline().getExtensionDataMap().remove(meta.getConnection());
+ }
+ connwrapper = null;
+ readRequest = null;
+
+ }
+ }
+
+
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventData.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventData.java
new file mode 100644
index 0000000000..ebadf2111b
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventData.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xevent;
+
+import org.apache.plc4x.hop.transforms.plc4xoutput.*;
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import java.util.Date;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.pipeline.transform.BaseTransformData;
+import org.apache.hop.pipeline.transform.ITransformData;
+
+
+public class Plc4xEventData extends BaseTransformData implements ITransformData {
+
+ //The Plc4xConnection metadata
+ public String connection;
+
+ public IRowMeta outputRowMeta;
+ public Object[] outputRowData;
+
+ public long rowLimit;
+ public long rowsWritten;
+ public Date rowDate;
+ public Date prevDate;
+ public long delay;
+
+
+
+ /**
+ * Default constructor for SampleData.
+ */
+ public Plc4xEventData() {
+ super();
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventDialog.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventDialog.java
new file mode 100644
index 0000000000..ea369b5cb7
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventDialog.java
@@ -0,0 +1,663 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xevent;
+
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.PipelinePreviewFactory;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformDialog;
+import org.apache.hop.ui.core.ConstUi;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.dialog.EnterNumberDialog;
+import org.apache.hop.ui.core.dialog.EnterTextDialog;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.dialog.PreviewRowsDialog;
+import org.apache.hop.ui.core.widget.MetaSelectionLine;
+import org.apache.hop.ui.core.widget.TableView;
+import org.apache.hop.ui.core.widget.TextVar;
+import org.apache.hop.ui.pipeline.dialog.PipelinePreviewProgressDialog;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.apache.hop.ui.util.SwtSvgImageUtil;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class Plc4xEventDialog extends BaseTransformDialog implements ITransformDialog {
+ private static final Class<?> PKG = Plc4xEventDialog.class; // Needed by Translator
+
+ private MetaSelectionLine<Plc4xConnection> wConnection;
+
+ private Label wlLimit;
+ private TextVar wLimit;
+
+ private Button wNeverEnding;
+
+ private Button wModeEvent;
+ private Button wUserEvent;
+ private Button wSysEvent;
+ private Button wAlarmEvent;
+
+ private Label wlMaxwait;
+ private TextVar wMaxwait;
+
+ private Label wlInterval;
+ private TextVar wInterval;
+
+ private Label wlRowTimeField;
+ private TextVar wRowTimeField;
+
+ private Label wlLastTimeField;
+ private TextVar wLastTimeField;
+
+ private TableView wFields;
+
+ private final Plc4xEventMeta input;
+
+ public Plc4xEventDialog(Shell parent, IVariables variables , Object in, PipelineMeta pipelineMeta, String sname ) {
+ super( parent, variables, (BaseTransformMeta) in, pipelineMeta, sname );
+ input = (Plc4xEventMeta) in;
+ }
+
+ @Override
+ public String open() {
+ Shell parent = getParent();
+
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN);
+ props.setLook(shell);
+ setShellImage(shell, input);
+
+ ModifyListener lsMod = e -> input.setChanged();
+ changed = input.hasChanged();
+
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.DialogTitle"));
+
+ int middle = props.getMiddlePct();
+ int margin = props.getMargin();
+
+ // Filename line
+ wlTransformName = new Label(shell, SWT.RIGHT);
+ wlTransformName.setText(BaseMessages.getString(PKG, "System.Label.TransformName"));
+ props.setLook(wlTransformName);
+ fdlTransformName = new FormData();
+ fdlTransformName.left = new FormAttachment(0, 0);
+ fdlTransformName.right = new FormAttachment(middle, -margin);
+ fdlTransformName.top = new FormAttachment(0, margin);
+ wlTransformName.setLayoutData(fdlTransformName);
+
+ wTransformName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wTransformName.setText(transformName);
+ props.setLook(wTransformName);
+ wTransformName.addModifyListener(lsMod);
+ fdTransformName = new FormData();
+ fdTransformName.left = new FormAttachment(middle, 0);
+ fdTransformName.top = new FormAttachment(0, margin);
+ fdTransformName.right = new FormAttachment(100, 0);
+ wTransformName.setLayoutData(fdTransformName);
+
+ // Connection line
+ wConnection =
+ new MetaSelectionLine<>(
+ variables,
+ metadataProvider,
+ Plc4xConnection.class,
+ shell,
+ SWT.NONE,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Label"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Tooltip"));
+ FormData fdConnection = new FormData();
+ fdConnection.left = new FormAttachment(0, 0);
+ fdConnection.right = new FormAttachment(100, 0);
+ fdConnection.top = new FormAttachment(wTransformName, margin);
+ wConnection.setLayoutData(fdConnection);
+ props.setLook(wConnection);
+ try {
+ wConnection.fillItems();
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "Error listing Cassandra connection metadata objects", e);
+ }
+
+ Control lastControl = wConnection;
+
+ wlLimit = new Label(shell, SWT.RIGHT);
+ wlLimit.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Limit.Label"));
+ props.setLook(wlLimit);
+ FormData fdlLimit = new FormData();
+ fdlLimit.left = new FormAttachment(0, 0);
+ fdlLimit.right = new FormAttachment(middle, -margin);
+ fdlLimit.top = new FormAttachment(lastControl, margin);
+ wlLimit.setLayoutData(fdlLimit);
+ wLimit = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLimit);
+ wLimit.addModifyListener(lsMod);
+ FormData fdLimit = new FormData();
+ fdLimit.left = new FormAttachment(middle, 0);
+ fdLimit.top = new FormAttachment(lastControl, margin);
+ fdLimit.right = new FormAttachment(100, 0);
+ wLimit.setLayoutData(fdLimit);
+ lastControl = wLimit;
+
+ /********************
+ * Never Ending
+ ********************/
+ Label wlNeverEnding = new Label(shell, SWT.RIGHT);
+ wlNeverEnding.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlNeverEnding);
+ FormData fdlNeverEnding = new FormData();
+ fdlNeverEnding.left = new FormAttachment(0, 0);
+ fdlNeverEnding.right = new FormAttachment(middle, -margin);
+ fdlNeverEnding.top = new FormAttachment(lastControl, margin);
+ wlNeverEnding.setLayoutData(fdlNeverEnding);
+ wNeverEnding = new Button(shell, SWT.CHECK);
+ props.setLook(wNeverEnding);
+ wNeverEnding.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+
+ FormData fdNeverEnding = new FormData();
+ fdNeverEnding.left = new FormAttachment(middle, 0);
+ fdNeverEnding.top = new FormAttachment(wlNeverEnding, 0, SWT.CENTER);
+ fdNeverEnding.right = new FormAttachment(100, 0);
+ wNeverEnding.setLayoutData(fdNeverEnding);
+ lastControl = wlNeverEnding;
+
+ /********************
+ * Mode Events
+ ********************/
+ Label wlModeEvent = new Label(shell, SWT.RIGHT);
+ wlModeEvent.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlModeEvent);
+ FormData fdlModeEvent = new FormData();
+ fdlModeEvent.left = new FormAttachment(0, 0);
+ fdlModeEvent.right = new FormAttachment(middle, -margin);
+ fdlModeEvent.top = new FormAttachment(lastControl, margin);
+ wlModeEvent.setLayoutData(fdlModeEvent);
+ wModeEvent = new Button(shell, SWT.CHECK);
+ props.setLook(wModeEvent);
+ wModeEvent.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+
+ FormData fdModeEvent = new FormData();
+ fdModeEvent.left = new FormAttachment(middle, 0);
+ fdModeEvent.top = new FormAttachment(wlModeEvent, 0, SWT.CENTER);
+ fdModeEvent.right = new FormAttachment(100, 0);
+ wModeEvent.setLayoutData(fdModeEvent);
+ lastControl = wlModeEvent;
+
+ /********************
+ * User Events
+ ********************/
+ Label wlUserEvent = new Label(shell, SWT.RIGHT);
+ wlUserEvent.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlUserEvent);
+ FormData fdlUserEvent = new FormData();
+ fdlUserEvent.left = new FormAttachment(0, 0);
+ fdlUserEvent.right = new FormAttachment(middle, -margin);
+ fdlUserEvent.top = new FormAttachment(lastControl, margin);
+ wlUserEvent.setLayoutData(fdlUserEvent);
+ wUserEvent = new Button(shell, SWT.CHECK);
+ props.setLook(wUserEvent);
+ wUserEvent.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+
+ FormData fdUserEvent = new FormData();
+ fdUserEvent.left = new FormAttachment(middle, 0);
+ fdUserEvent.top = new FormAttachment(wlUserEvent, 0, SWT.CENTER);
+ fdUserEvent.right = new FormAttachment(100, 0);
+ wUserEvent.setLayoutData(fdUserEvent);
+ lastControl = wlUserEvent;
+
+ /********************
+ * Sys Events
+ ********************/
+ Label wlSysEvent = new Label(shell, SWT.RIGHT);
+ wlSysEvent.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlSysEvent);
+ FormData fdlSysEvent = new FormData();
+ fdlSysEvent.left = new FormAttachment(0, 0);
+ fdlSysEvent.right = new FormAttachment(middle, -margin);
+ fdlSysEvent.top = new FormAttachment(lastControl, margin);
+ wlSysEvent.setLayoutData(fdlSysEvent);
+ wSysEvent = new Button(shell, SWT.CHECK);
+ props.setLook(wSysEvent);
+ wSysEvent.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+
+ FormData fdSysEvent = new FormData();
+ fdSysEvent.left = new FormAttachment(middle, 0);
+ fdSysEvent.top = new FormAttachment(wlSysEvent, 0, SWT.CENTER);
+ fdSysEvent.right = new FormAttachment(100, 0);
+ wSysEvent.setLayoutData(fdSysEvent);
+ lastControl = wlSysEvent;
+
+ /********************
+ * Alarm Events
+ ********************/
+ Label wlAlarmEvent = new Label(shell, SWT.RIGHT);
+ wlAlarmEvent.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlAlarmEvent);
+ FormData fdlAlarmEvent = new FormData();
+ fdlAlarmEvent.left = new FormAttachment(0, 0);
+ fdlAlarmEvent.right = new FormAttachment(middle, -margin);
+ fdlAlarmEvent.top = new FormAttachment(lastControl, margin);
+ wlAlarmEvent.setLayoutData(fdlAlarmEvent);
+ wAlarmEvent = new Button(shell, SWT.CHECK);
+ props.setLook(wAlarmEvent);
+ wAlarmEvent.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+
+ FormData fdAlarmEvent = new FormData();
+ fdAlarmEvent.left = new FormAttachment(middle, 0);
+ fdAlarmEvent.top = new FormAttachment(wlAlarmEvent, 0, SWT.CENTER);
+ fdAlarmEvent.right = new FormAttachment(100, 0);
+ wAlarmEvent.setLayoutData(fdAlarmEvent);
+ lastControl = wlAlarmEvent;
+
+
+ wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, e -> ok());
+
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, e -> cancel());
+
+ setButtonPositions(new Button[] {wOk, wCancel}, margin, null);
+
+ /*
+
+ wlMaxwait = new Label(shell, SWT.RIGHT);
+ wlMaxwait.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Maxwait.Label"));
+ props.setLook(wlMaxwait);
+ FormData fdlMaxwait = new FormData();
+ fdlMaxwait.left = new FormAttachment(0, 0);
+ fdlMaxwait.right = new FormAttachment(middle, -margin);
+ fdlMaxwait.top = new FormAttachment(lastControl, margin);
+ wlMaxwait.setLayoutData(fdlMaxwait);
+ wMaxwait = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wMaxwait);
+ wMaxwait.addModifyListener(lsMod);
+ FormData fdMaxwait = new FormData();
+ fdMaxwait.left = new FormAttachment(middle, 0);
+ fdMaxwait.top = new FormAttachment(lastControl, margin);
+ fdMaxwait.right = new FormAttachment(100, 0);
+ wMaxwait.setLayoutData(fdMaxwait);
+ lastControl = wMaxwait;
+
+ wlInterval = new Label(shell, SWT.RIGHT);
+ wlInterval.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Interval.Label"));
+ props.setLook(wlInterval);
+ FormData fdlInterval = new FormData();
+ fdlInterval.left = new FormAttachment(0, 0);
+ fdlInterval.right = new FormAttachment(middle, -margin);
+ fdlInterval.top = new FormAttachment(lastControl, margin);
+ wlInterval.setLayoutData(fdlInterval);
+ wInterval = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wInterval);
+ wInterval.addModifyListener(lsMod);
+ FormData fdInterval = new FormData();
+ fdInterval.left = new FormAttachment(middle, 0);
+ fdInterval.top = new FormAttachment(lastControl, margin);
+ fdInterval.right = new FormAttachment(100, 0);
+ wInterval.setLayoutData(fdInterval);
+ lastControl = wInterval;
+
+
+ wlRowTimeField = new Label(shell, SWT.RIGHT);
+ wlRowTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.RowTimeField.Label"));
+ props.setLook(wlRowTimeField);
+ FormData fdlRowTimeField = new FormData();
+ fdlRowTimeField.left = new FormAttachment(0, 0);
+ fdlRowTimeField.right = new FormAttachment(middle, -margin);
+ fdlRowTimeField.top = new FormAttachment(lastControl, margin);
+ wlRowTimeField.setLayoutData(fdlRowTimeField);
+ wRowTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wRowTimeField);
+ wRowTimeField.addModifyListener(lsMod);
+ FormData fdRowTimeField = new FormData();
+ fdRowTimeField.left = new FormAttachment(middle, 0);
+ fdRowTimeField.top = new FormAttachment(lastControl, margin);
+ fdRowTimeField.right = new FormAttachment(100, 0);
+ wRowTimeField.setLayoutData(fdRowTimeField);
+ lastControl = wRowTimeField;
+
+ wlLastTimeField = new Label(shell, SWT.RIGHT);
+ wlLastTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.LastTimeField.Label"));
+ props.setLook(wlLastTimeField);
+ FormData fdlLastTimeField = new FormData();
+ fdlLastTimeField.left = new FormAttachment(0, 0);
+ fdlLastTimeField.right = new FormAttachment(middle, -margin);
+ fdlLastTimeField.top = new FormAttachment(lastControl, margin);
+ wlLastTimeField.setLayoutData(fdlLastTimeField);
+ wLastTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLastTimeField);
+ wLastTimeField.addModifyListener(lsMod);
+ FormData fdLastTimeField = new FormData();
+ fdLastTimeField.left = new FormAttachment(middle, 0);
+ fdLastTimeField.top = new FormAttachment(lastControl, margin);
+ fdLastTimeField.right = new FormAttachment(100, 0);
+ wLastTimeField.setLayoutData(fdLastTimeField);
+ lastControl = wLastTimeField;
+
+ wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, e -> ok());
+ wPreview = new Button(shell, SWT.PUSH);
+ wPreview.setText(BaseMessages.getString(PKG, "System.Button.Preview"));
+ wPreview.addListener(SWT.Selection, e -> preview());
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, e -> cancel());
+
+ setButtonPositions(new Button[] {wOk, wPreview, wCancel}, margin, null);
+
+ Label wlFields = new Label(shell, SWT.NONE);
+ wlFields.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Label"));
+ props.setLook(wlFields);
+ FormData fdlFields = new FormData();
+ fdlFields.left = new FormAttachment(0, 0);
+ fdlFields.top = new FormAttachment(lastControl, margin);
+ wlFields.setLayoutData(fdlFields);
+ lastControl = wlFields;
+
+ final int nrFields = input.getFields().size();
+
+ ColumnInfo[] colinf =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Name"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Item"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Type"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ ValueMetaFactory.getValueMetaNames()),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Format"),
+ ColumnInfo.COLUMN_TYPE_FORMAT,
+ 2),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Length"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Precision"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Currency"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Decimal"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Group"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Value"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.SetEmptyString"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ new String[] {
+ BaseMessages.getString(PKG, "System.Combo.Yes"),
+ BaseMessages.getString(PKG, "System.Combo.No")
+ })
+ };
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
+ colinf,
+ nrFields,
+ lsMod,
+ props);
+
+ FormData fdFields = new FormData();
+ fdFields.left = new FormAttachment(0, 0);
+ fdFields.top = new FormAttachment(lastControl, margin);
+ fdFields.right = new FormAttachment(100, 0);
+ fdFields.bottom = new FormAttachment(wOk, -2 * margin);
+ wFields.setLayoutData(fdFields);
+
+ lsResize =
+ event -> {
+ Point size = shell.getSize();
+ wFields.setSize(size.x - 10, size.y - 50);
+ wFields.table.setSize(size.x - 10, size.y - 50);
+ wFields.redraw();
+ };
+ */
+
+ //shell.addListener(SWT.Resize, lsResize);
+
+ getData();
+ input.setChanged(changed);
+
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return transformName;
+ };
+
+
+ public void setActive() {
+ boolean neverEnding = wNeverEnding.getSelection();
+
+ wlLimit.setEnabled(!neverEnding);
+ wLimit.setEnabled(!neverEnding);
+ }
+
+
+
+ private Image getImage() {
+ return SwtSvgImageUtil.getImage( shell.getDisplay(), getClass().getClassLoader(), "plc4x_toddy_read.svg", ConstUi.LARGE_ICON_SIZE,
+ ConstUi.LARGE_ICON_SIZE );
+ }
+
+ /**
+ * Copy information from the meta-data input to the dialog fields.
+ *
+ */
+ public void getData() {
+ if (isDebug()) {
+ logDebug("getting fields info...");
+ }
+ if (input.getConnection() == null) {
+ wConnection.setText("");
+ } else {
+ wConnection.setText(input.getConnection());
+ }
+
+ wLimit.setText(input.getRowLimit());
+ wNeverEnding.setSelection(input.isNeverEnding());
+
+
+ setActive();
+
+ wTransformName.selectAll();
+ wTransformName.setFocus();
+ }
+
+ /**
+ * Stores the information from the dialog box in meta-data.
+ *
+ * @param meta
+ */
+ private void getInfo( Plc4xEventMeta meta) throws HopException {
+ meta.setConnection(wConnection.getText());
+ meta.setRowLimit(wLimit.getText());
+ meta.setNeverEnding(wNeverEnding.getSelection());
+
+ }
+
+ /**
+ * Cancel the dialog.
+ */
+ private void cancel() {
+ transformName = null;
+ input.setChanged( changed );
+ dispose();
+ }
+
+ private void ok() {
+ if (Utils.isEmpty(wTransformName.getText())) {
+ return;
+ }
+
+ transformName = wTransformName.getText(); // return value
+ try {
+ getInfo(new Plc4xEventMeta()); // to see if there is an exception
+ getInfo(input); // to put the content on the input structure for real if all is well.
+ dispose();
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ }
+ }
+
+
+ /**
+ * Preview the data generated by this transform. This generates a pipeline using this transform &
+ * a dummy and previews it.
+ */
+ private void preview() {
+ Plc4xEventMeta oneMeta = new Plc4xEventMeta();
+ try {
+ getInfo(oneMeta);
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ return;
+ }
+
+ PipelineMeta previewMeta =
+ PipelinePreviewFactory.generatePreviewPipeline(
+ pipelineMeta.getMetadataProvider(), oneMeta, wTransformName.getText());
+
+ EnterNumberDialog numberDialog =
+ new EnterNumberDialog(
+ shell,
+ props.getDefaultPreviewSize(),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Message"));
+ int previewSize = numberDialog.open();
+ if (previewSize > 0) {
+ PipelinePreviewProgressDialog progressDialog =
+ new PipelinePreviewProgressDialog(
+ shell,
+ variables,
+ previewMeta,
+ new String[] {wTransformName.getText()},
+ new int[] {previewSize});
+ progressDialog.open();
+
+ Pipeline pipeline = progressDialog.getPipeline();
+ String loggingText = progressDialog.getLoggingText();
+
+ if (!progressDialog.isCancelled()) {
+ if (pipeline.getResult() != null && pipeline.getResult().getNrErrors() > 0) {
+ EnterTextDialog etd =
+ new EnterTextDialog(
+ shell,
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Message"),
+ loggingText,
+ true);
+ etd.setReadOnly();
+ etd.open();
+ }
+ }
+
+ PreviewRowsDialog prd =
+ new PreviewRowsDialog(
+ shell,
+ variables,
+ SWT.NONE,
+ wTransformName.getText(),
+ progressDialog.getPreviewRowsMeta(wTransformName.getText()),
+ progressDialog.getPreviewRows(wTransformName.getText()),
+ loggingText);
+ prd.open();
+ }
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventMeta.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventMeta.java
new file mode 100644
index 0000000000..207adb7824
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xevent/Plc4xEventMeta.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xevent;
+
+import java.util.ArrayList;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.core.exception.HopTransformException;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+
+import java.util.List;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.pipeline.transform.ITransformIOMeta;
+import org.apache.hop.pipeline.transform.TransformIOMeta;
+
+/**
+ * Meta data for the sample transform.
+ */
+@Transform(
+ id = "plc4x-event",
+ name = "i18n::Plc4x.Read.Name",
+ description = "i18n::Plc4x.Read.Description",
+ image = "plc4x_event.svg",
+ categoryDescription = "i18n:org.apache.plc4x.hop.transforms.plc4xevent:Plc4x.Category.plc4x",
+ documentationUrl = "https://plc4x.apache.org/users/integrations/apache-hop.html"
+)
+public class Plc4xEventMeta extends BaseTransformMeta implements ITransformMeta {
+
+ private static final Class<?> PKG = Plc4xEventMeta.class; // Needed by Translator
+
+
+ @HopMetadataProperty(
+ key = "connection",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.Connection")
+ private String connection;
+
+ @HopMetadataProperty(
+ key = "limit",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.RowLimit")
+ private String rowLimit;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean neverEnding;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean modeEvent;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean userEvent;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean sysEvent;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean alarmEvent;
+
+
+ public Plc4xEventMeta() {
+ rowLimit = "10";
+ neverEnding = false;
+ modeEvent = false;
+ userEvent = false;
+ sysEvent = false;
+ alarmEvent = false;
+
+ }
+
+ public Plc4xEventMeta(Plc4xEventMeta m) {
+ this.connection = m.connection;
+ this.neverEnding = m.neverEnding;
+ this.modeEvent = m.modeEvent;
+ this.userEvent = m.userEvent;
+ this.sysEvent = m.sysEvent;
+ this.alarmEvent = m.alarmEvent;
+ }
+
+ @Override
+ public Plc4xEventMeta clone() {
+ return new Plc4xEventMeta(this);
+ }
+
+
+
+ @Override
+ public void getFields( IRowMeta inputRowMeta, String name, IRowMeta[] info, TransformMeta nextTransform,
+ IVariables variables, IHopMetadataProvider metadataProvider ) throws HopTransformException {
+ try {
+ List<ICheckResult> remarks = new ArrayList<>();
+ RowMetaAndData rowMetaAndData = Plc4xEvent.buildRow(this, remarks, name);
+ if (!remarks.isEmpty()) {
+ StringBuilder stringRemarks = new StringBuilder();
+ for (ICheckResult remark : remarks) {
+ stringRemarks.append(remark.toString()).append(Const.CR);
+ }
+ throw new HopTransformException(stringRemarks.toString());
+ }
+ for (IValueMeta valueMeta : rowMetaAndData.getRowMeta().getValueMetaList()) {
+ valueMeta.setOrigin(name);
+ }
+ inputRowMeta.mergeRowMeta(rowMetaAndData.getRowMeta());
+ } catch (Exception e) {
+ throw new HopTransformException(e);
+ }
+ }
+
+ public Plc4xEvent createTransform(TransformMeta transformMeta, Plc4xEventData data, int copyNr,
+ PipelineMeta pipelineMeta, Pipeline pipeline ) {
+ return new Plc4xEvent( transformMeta, this, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Plc4xEventData getTransformData() {
+ return new Plc4xEventData();
+ }
+
+ @Override
+ public void setDefault() {
+ //default values when creating a new transform
+ }
+
+
+ /**
+ * Returns the Input/Output metadata for this transform.
+ * The generator transform only produces output, does not accept input!
+ * TransformIOMeta(inputAcceptor, outputProducer, inputOptional, outputDynamic, inputDynamic)
+ */
+ @Override
+ public ITransformIOMeta getTransformIOMeta() {
+ return new TransformIOMeta(false, true, false, false, false, false);
+ }
+
+ /**
+ * Gets Plc4xConnection metadata name.
+ *
+ * @return value of intervalInMs
+ */
+ public String getConnection() {
+ return connection;
+ }
+
+ /** @param connection */
+ public void setConnection(String connection) {
+ this.connection = connection;
+ }
+
+ public String getRowLimit() {
+ return rowLimit;
+ }
+
+ /** @param connection */
+ public void setRowLimit(String rowLimit) {
+ this.rowLimit = rowLimit;
+ }
+
+ /**
+ * Gets neverEnding
+ *
+ * @return value of neverEnding
+ */
+ public boolean isNeverEnding() {
+ return neverEnding;
+ }
+
+ /** @param neverEnding The neverEnding to set */
+ public void setNeverEnding(boolean neverEnding) {
+ this.neverEnding = neverEnding;
+ }
+
+ public boolean isModeEvent() {
+ return neverEnding;
+ }
+
+ public void setModeEvent(boolean modeEvent) {
+ this.modeEvent = modeEvent;
+ }
+
+ public boolean isUserEvent() {
+ return neverEnding;
+ }
+
+ public void setUserEvent(boolean userEvent) {
+ this.userEvent = userEvent;
+ }
+
+ public boolean isSysEvent() {
+ return sysEvent;
+ }
+
+ public void setSysEvent(boolean sysEvent) {
+ this.sysEvent = sysEvent;
+ }
+
+ public boolean isAlarmEvent() {
+ return alarmEvent;
+ }
+
+ public void setAlarmEvent(boolean alarmEvent) {
+ this.alarmEvent = alarmEvent;
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xRead.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xRead.java
new file mode 100644
index 0000000000..7b1832c16d
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xRead.java
@@ -0,0 +1,446 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xinput;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hop.core.CheckResult;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginException;
+import org.apache.hop.core.exception.HopValueException;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.RowDataUtil;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.StringUtil;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
+import org.apache.hop.pipeline.transform.ITransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.apache.plc4x.hop.transforms.util.Plc4xPlcField;
+import org.apache.plc4x.hop.transforms.util.Plc4xWrapperConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+
+/**
+ * Transform That contains the basic skeleton needed to create your own plugin
+ *
+ */
+public class Plc4xRead extends BaseTransform<Plc4xReadMeta, Plc4xReadData> implements ITransform {
+
+ private static final Class<?> PKG = Plc4xRead.class; // Needed by Translator
+
+ private Plc4xConnection connmeta = null;
+ private Plc4xWrapperConnection connwrapper = null;
+ private PlcReadRequest readRequest = null;
+ private PlcReadResponse readResponse = null;
+ private int maxwait = 0;
+ private static final ReentrantLock lock = new ReentrantLock();
+
+ private static final String dummy = "dummy";
+
+ private Map<String, Integer> index = new HashMap();
+ private Map<String, Plc4xPlcField> plcfields = new HashMap();
+
+ public Plc4xRead(TransformMeta transformMeta, Plc4xReadMeta meta, Plc4xReadData data, int copyNr, PipelineMeta pipelineMeta,
+ Pipeline pipeline ) {
+ super( transformMeta, meta, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ /*
+ * Including Date and Time field for every row
+ *
+ * @param meta Meta data from user dialog
+ * @param remarks Error registers
+ * @param origin transform instance name
+ */
+ public static final RowMetaAndData buildRow(
+ Plc4xReadMeta meta, List<ICheckResult> remarks, String origin) throws HopPluginException {
+ IRowMeta rowMeta = new RowMeta();
+ Object[] rowData = RowDataUtil.allocateRowData(meta.getFields().size() + 2);
+ int index = 0;
+
+ if (!Utils.isEmpty(meta.getRowTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getRowTimeField()));
+ rowData[index++] = null;
+ }
+
+ if (!Utils.isEmpty(meta.getLastTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getLastTimeField()));
+ rowData[index++] = null;
+ }
+
+ for (Plc4xGeneratorField field : meta.getFields()) {
+ int typeString = ValueMetaFactory.getIdForValueMeta(field.getType());
+ if (StringUtils.isNotEmpty(field.getType())) {
+ System.out.println("typeString: " + typeString);
+ IValueMeta valueMeta =
+ ValueMetaFactory.createValueMeta(field.getName(), typeString); // build a
+ // value!
+ valueMeta.setLength(field.getLength());
+ valueMeta.setPrecision(field.getPrecision());
+ valueMeta.setConversionMask(field.getFormat());
+ valueMeta.setCurrencySymbol(field.getCurrency());
+ valueMeta.setGroupingSymbol(field.getGroup());
+ valueMeta.setDecimalSymbol(field.getDecimal());
+ valueMeta.setOrigin(origin);
+
+ IValueMeta stringMeta = ValueMetaFactory.cloneValueMeta(valueMeta, IValueMeta.TYPE_STRING);
+
+ if (field.isSetEmptyString()) {
+ // Set empty string
+ rowData[index] = StringUtil.EMPTY_STRING;
+ } else {
+ String stringValue = field.getValue();
+
+ // If the value is empty: consider it to be NULL.
+ if (Utils.isEmpty(stringValue)) {
+ rowData[index] = null;
+
+ if (valueMeta.getType() == IValueMeta.TYPE_NONE) {
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ }
+ } else {
+ // Convert the data from String to the specified type ...
+ //
+ try {
+ System.out.println("stringValue: " + stringValue);
+ rowData[index] = valueMeta.convertData(stringMeta, stringValue);
+ } catch (HopValueException e) {
+ switch (valueMeta.getType()) {
+ case IValueMeta.TYPE_NUMBER:
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Number",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_DATE:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Date",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_INTEGER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Integer",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_BIGNUMBER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.BigNumber",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_TIMESTAMP:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Timestamp",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ default:
+ // Boolean and binary don't throw errors normally, so it's probably an unspecified
+ // error problem...
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+ }
+ }
+ }
+ }
+
+ // Now add value to the row!
+ // This is in fact a copy from the fields row, but now with data.
+ rowMeta.addValueMeta(valueMeta);
+ index++;
+ }
+ }
+
+ return new RowMetaAndData(rowMeta, rowData);
+ }
+
+ /*
+ * 1. Block the other instances by means of a lock.
+ * 2. Try to locate an existing connection.
+ * 3. If it doesn't exist, it tries to take control of the routine to
+ * create an instance of PlcConnection and his wrapper.
+ * 4. Register the connection wrapper for global access.
+ * 5. If the connection to the PLC is made, then it creates the query
+ * and executes it.
+ *
+ */
+ @Override
+ public boolean processRow() throws HopException {
+ Object[] r = getRow(); // Get row from input rowset & set row busy!
+ setLogLevel(LogLevel.DEBUG);
+
+ if ((!meta.isNeverEnding() && data.rowsWritten >= data.rowLimit) && !isStopped()) {
+ setOutputDone(); // signal end to receiver(s)
+ return false;
+ }
+
+ if (first) {
+ index.clear();
+ plcfields.clear();
+ //This performs a minimal check on the user item.
+ //It guarantees that the rates are within those managed by Plc4x.
+ meta.getFields().forEach((f) ->{
+ plcfields.put(f.getName(),Plc4xPlcField.of(f.getItem()));
+ });
+ first = false;
+ }
+
+ lock.lock(); //(01)
+ try {
+ IHopMetadataProvider metaprovider = getMetadataProvider();
+ connmeta = metaprovider.getSerializer(Plc4xConnection.class).load(meta.getConnection());
+ if (connwrapper == null) {
+ connwrapper = (Plc4xWrapperConnection) getPipeline().getExtensionDataMap().get(meta.getConnection()); //(02)
+ if (connwrapper != null) connwrapper.retain();
+ };
+
+ if (connmeta == null){
+ logError(
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.Log.SetMetadata",
+ meta.getConnection()));
+ }
+
+ if ((connmeta != null) && (connwrapper == null)){
+ readRequest = null;
+ try{
+ PlcConnection conn = new DefaultPlcDriverManager().getConnection(connmeta.getUrl()); //(03)
+ if (conn.isConnected()) {
+ connwrapper = new Plc4xWrapperConnection(conn);
+ getPipeline().getExtensionDataMap().put(meta.getConnection(), connwrapper); //(04)
+ }
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Unable to create connection to PLC. " + ex.getMessage());
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+
+ if ((connmeta != null) && (connwrapper != null)){
+ if (connwrapper.getConnection().isConnected()){
+ if (readRequest == null){
+ PlcReadRequest.Builder builder = connwrapper.getConnection().readRequestBuilder(); //(05)
+ for (Plc4xGeneratorField field: meta.getFields()){
+ builder.addTagAddress(field.getName(), field.getItem());
+ }
+ readRequest = builder.build();
+ }
+ try {
+ maxwait = Integer.parseInt(meta.getMaxwaitInMs());
+ maxwait = (maxwait<100)?100:maxwait;
+ readResponse = readRequest.execute().get(maxwait, TimeUnit.MILLISECONDS);
+
+ for (Plc4xGeneratorField field: meta.getFields()){
+ field.setValue(readResponse.getString(field.getName()));
+ }
+ } catch (Exception ex) {
+ setErrors(1L);
+ logError("Unable read from PLC. " + ex.getMessage());
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC is not connected.");
+ setOutputDone();
+ return false;
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC connection don't exist.");
+ setOutputDone();
+ return false;
+ }
+
+ //
+ int interval = Integer.parseInt(meta.getIntervalInMs());
+
+ try {
+ Thread.sleep(interval);
+ } catch (InterruptedException ex) {
+ setErrors(1L);
+ logError(ex.getMessage());
+ }
+
+ r = data.outputRowMeta.cloneRow(data.outputRowData);
+ logBasic("Tamano de los datos: " + r.length);
+ data.prevDate = data.rowDate;
+ data.rowDate = new Date();
+ int index = 0;
+ if (!Utils.isEmpty(meta.getRowTimeField())) {
+ r[index++] = data.rowDate;
+ }
+ if (!Utils.isEmpty(meta.getLastTimeField())) {
+ r[index++] = data.prevDate;
+ }
+ for (Plc4xGeneratorField field: meta.getFields()){
+ if (field.getType().equalsIgnoreCase("Boolean")){
+ r[index++] = Boolean.parseBoolean(field.getValue());
+ } else if (field.getType().equalsIgnoreCase("Number")){
+ r[index++] = Double.parseDouble(field.getValue());
+ } else if (field.getType().equalsIgnoreCase("Integer")){
+ r[index++] = Integer.parseInt(field.getValue());
+ }
+ }
+ putRow(data.outputRowMeta, r ); // return your data
+ data.rowsWritten++;
+ return true;
+ }
+
+
+ @Override
+ public boolean init() {
+ try {
+ if(super.init()){
+ // Determine the number of rows to generate...
+ data.rowLimit = Const.toLong(resolve(meta.getRowLimit()), -1L);
+ data.rowsWritten = 0L;
+ data.delay = Const.toLong(resolve(meta.getIntervalInMs()), -1L);
+
+ if (data.rowLimit < 0L) { // Unable to parse
+ logError(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Wrong.RowLimit.Number"));
+ return false; // fail
+ }
+
+ // Create a row (constants) with all the values in it...
+ List<ICheckResult> remarks = new ArrayList<>(); // stores the errors...
+ RowMetaAndData outputRow = buildRow(meta, remarks, getTransformName());
+ if (!remarks.isEmpty()) {
+ for (int i = 0; i < remarks.size(); i++) {
+ CheckResult cr = (CheckResult) remarks.get(i);
+ logError(cr.getText());
+ }
+ return false;
+ }
+
+ data.outputRowData = outputRow.getData();
+ data.outputRowMeta = outputRow.getRowMeta();
+
+ return true;
+ }
+ return false;
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Error initializing transform", ex);
+ return false;
+ }
+ }
+
+ /*
+ * Here, must perform the cleaning of any resource, main of the connection to
+ * the associated PLC.
+ */
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ logBasic("Cleanup. Release connection.");
+ if (connwrapper != null)
+ connwrapper.release();
+ }
+
+
+ /*
+ * Here, must perform the cleaning of any resource.
+ * 1. Check if we have reference to wrapper.
+ * 2. Release de reference to object.
+ * 3. The lastone remove the global reference to connection wrapper.
+ * 4. Clear local references.
+ */
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (connwrapper != null) {
+ logBasic("Dispose. Release connection: " + connwrapper.refCnt());
+ connwrapper.release();
+ if (!connwrapper.getConnection().isConnected()){
+ getPipeline().getExtensionDataMap().remove(meta.getConnection());
+ }
+ connwrapper = null;
+ readRequest = null;
+
+ }
+ }
+
+
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadData.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadData.java
new file mode 100644
index 0000000000..98b5889f0a
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadData.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xinput;
+
+import java.util.Date;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.pipeline.transform.BaseTransformData;
+import org.apache.hop.pipeline.transform.ITransformData;
+
+
+public class Plc4xReadData extends BaseTransformData implements ITransformData {
+
+ //The Plc4xConnection metadata
+ public String connection;
+
+ public IRowMeta outputRowMeta;
+ public Object[] outputRowData;
+
+ public long rowLimit;
+ public long rowsWritten;
+ public Date rowDate;
+ public Date prevDate;
+ public long delay;
+
+
+
+ /**
+ * Default constructor for SampleData.
+ */
+ public Plc4xReadData() {
+ super();
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadDialog.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadDialog.java
new file mode 100644
index 0000000000..a736e418da
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadDialog.java
@@ -0,0 +1,600 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xinput;
+
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.PipelinePreviewFactory;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformDialog;
+import org.apache.hop.ui.core.ConstUi;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.dialog.EnterNumberDialog;
+import org.apache.hop.ui.core.dialog.EnterTextDialog;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.dialog.PreviewRowsDialog;
+import org.apache.hop.ui.core.widget.ColumnInfo;
+import org.apache.hop.ui.core.widget.MetaSelectionLine;
+import org.apache.hop.ui.core.widget.TableView;
+import org.apache.hop.ui.core.widget.TextVar;
+import org.apache.hop.ui.pipeline.dialog.PipelinePreviewProgressDialog;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.apache.hop.ui.util.SwtSvgImageUtil;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+public class Plc4xReadDialog extends BaseTransformDialog implements ITransformDialog {
+ private static final Class<?> PKG = Plc4xReadDialog.class; // Needed by Translator
+
+ private MetaSelectionLine<Plc4xConnection> wConnection;
+
+ private Label wlLimit;
+ private TextVar wLimit;
+
+ private Button wNeverEnding;
+
+ private Label wlMaxwait;
+ private TextVar wMaxwait;
+
+ private Label wlInterval;
+ private TextVar wInterval;
+
+ private Label wlRowTimeField;
+ private TextVar wRowTimeField;
+
+ private Label wlLastTimeField;
+ private TextVar wLastTimeField;
+
+ private TableView wFields;
+
+ private final Plc4xReadMeta input;
+
+ public Plc4xReadDialog(Shell parent, IVariables variables , Object in, PipelineMeta pipelineMeta, String sname ) {
+ super( parent, variables, (BaseTransformMeta) in, pipelineMeta, sname );
+ input = (Plc4xReadMeta) in;
+ }
+
+ @Override
+ public String open() {
+ Shell parent = getParent();
+
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN);
+ props.setLook(shell);
+ setShellImage(shell, input);
+
+ ModifyListener lsMod = e -> input.setChanged();
+ changed = input.hasChanged();
+
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.DialogTitle"));
+
+ int middle = props.getMiddlePct();
+ int margin = props.getMargin();
+
+ // Filename line
+ wlTransformName = new Label(shell, SWT.RIGHT);
+ wlTransformName.setText(BaseMessages.getString(PKG, "System.Label.TransformName"));
+ props.setLook(wlTransformName);
+ fdlTransformName = new FormData();
+ fdlTransformName.left = new FormAttachment(0, 0);
+ fdlTransformName.right = new FormAttachment(middle, -margin);
+ fdlTransformName.top = new FormAttachment(0, margin);
+ wlTransformName.setLayoutData(fdlTransformName);
+
+ wTransformName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wTransformName.setText(transformName);
+ props.setLook(wTransformName);
+ wTransformName.addModifyListener(lsMod);
+ fdTransformName = new FormData();
+ fdTransformName.left = new FormAttachment(middle, 0);
+ fdTransformName.top = new FormAttachment(0, margin);
+ fdTransformName.right = new FormAttachment(100, 0);
+ wTransformName.setLayoutData(fdTransformName);
+
+ // Connection line
+ wConnection =
+ new MetaSelectionLine<>(
+ variables,
+ metadataProvider,
+ Plc4xConnection.class,
+ shell,
+ SWT.NONE,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Label"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Tooltip"));
+ FormData fdConnection = new FormData();
+ fdConnection.left = new FormAttachment(0, 0);
+ fdConnection.right = new FormAttachment(100, 0);
+ fdConnection.top = new FormAttachment(wTransformName, margin);
+ wConnection.setLayoutData(fdConnection);
+ props.setLook(wConnection);
+ try {
+ wConnection.fillItems();
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "Error listing Cassandra connection metadata objects", e);
+ }
+
+ Control lastControl = wConnection;
+
+ wlLimit = new Label(shell, SWT.RIGHT);
+ wlLimit.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Limit.Label"));
+ props.setLook(wlLimit);
+ FormData fdlLimit = new FormData();
+ fdlLimit.left = new FormAttachment(0, 0);
+ fdlLimit.right = new FormAttachment(middle, -margin);
+ fdlLimit.top = new FormAttachment(lastControl, margin);
+ wlLimit.setLayoutData(fdlLimit);
+ wLimit = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLimit);
+ wLimit.addModifyListener(lsMod);
+ FormData fdLimit = new FormData();
+ fdLimit.left = new FormAttachment(middle, 0);
+ fdLimit.top = new FormAttachment(lastControl, margin);
+ fdLimit.right = new FormAttachment(100, 0);
+ wLimit.setLayoutData(fdLimit);
+ lastControl = wLimit;
+
+ Label wlNeverEnding = new Label(shell, SWT.RIGHT);
+ wlNeverEnding.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlNeverEnding);
+ FormData fdlNeverEnding = new FormData();
+ fdlNeverEnding.left = new FormAttachment(0, 0);
+ fdlNeverEnding.right = new FormAttachment(middle, -margin);
+ fdlNeverEnding.top = new FormAttachment(lastControl, margin);
+ wlNeverEnding.setLayoutData(fdlNeverEnding);
+ wNeverEnding = new Button(shell, SWT.CHECK);
+ props.setLook(wNeverEnding);
+ wNeverEnding.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+ FormData fdNeverEnding = new FormData();
+ fdNeverEnding.left = new FormAttachment(middle, 0);
+ fdNeverEnding.top = new FormAttachment(wlNeverEnding, 0, SWT.CENTER);
+ fdNeverEnding.right = new FormAttachment(100, 0);
+ wNeverEnding.setLayoutData(fdNeverEnding);
+ lastControl = wlNeverEnding;
+
+ wlMaxwait = new Label(shell, SWT.RIGHT);
+ wlMaxwait.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Maxwait.Label"));
+ props.setLook(wlMaxwait);
+ FormData fdlMaxwait = new FormData();
+ fdlMaxwait.left = new FormAttachment(0, 0);
+ fdlMaxwait.right = new FormAttachment(middle, -margin);
+ fdlMaxwait.top = new FormAttachment(lastControl, margin);
+ wlMaxwait.setLayoutData(fdlMaxwait);
+ wMaxwait = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wMaxwait);
+ wMaxwait.addModifyListener(lsMod);
+ FormData fdMaxwait = new FormData();
+ fdMaxwait.left = new FormAttachment(middle, 0);
+ fdMaxwait.top = new FormAttachment(lastControl, margin);
+ fdMaxwait.right = new FormAttachment(100, 0);
+ wMaxwait.setLayoutData(fdMaxwait);
+ lastControl = wMaxwait;
+
+ wlInterval = new Label(shell, SWT.RIGHT);
+ wlInterval.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Interval.Label"));
+ props.setLook(wlInterval);
+ FormData fdlInterval = new FormData();
+ fdlInterval.left = new FormAttachment(0, 0);
+ fdlInterval.right = new FormAttachment(middle, -margin);
+ fdlInterval.top = new FormAttachment(lastControl, margin);
+ wlInterval.setLayoutData(fdlInterval);
+ wInterval = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wInterval);
+ wInterval.addModifyListener(lsMod);
+ FormData fdInterval = new FormData();
+ fdInterval.left = new FormAttachment(middle, 0);
+ fdInterval.top = new FormAttachment(lastControl, margin);
+ fdInterval.right = new FormAttachment(100, 0);
+ wInterval.setLayoutData(fdInterval);
+ lastControl = wInterval;
+
+ /*
+ wlRowTimeField = new Label(shell, SWT.RIGHT);
+ wlRowTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.RowTimeField.Label"));
+ props.setLook(wlRowTimeField);
+ FormData fdlRowTimeField = new FormData();
+ fdlRowTimeField.left = new FormAttachment(0, 0);
+ fdlRowTimeField.right = new FormAttachment(middle, -margin);
+ fdlRowTimeField.top = new FormAttachment(lastControl, margin);
+ wlRowTimeField.setLayoutData(fdlRowTimeField);
+ wRowTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wRowTimeField);
+ wRowTimeField.addModifyListener(lsMod);
+ FormData fdRowTimeField = new FormData();
+ fdRowTimeField.left = new FormAttachment(middle, 0);
+ fdRowTimeField.top = new FormAttachment(lastControl, margin);
+ fdRowTimeField.right = new FormAttachment(100, 0);
+ wRowTimeField.setLayoutData(fdRowTimeField);
+ lastControl = wRowTimeField;
+
+ wlLastTimeField = new Label(shell, SWT.RIGHT);
+ wlLastTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.LastTimeField.Label"));
+ props.setLook(wlLastTimeField);
+ FormData fdlLastTimeField = new FormData();
+ fdlLastTimeField.left = new FormAttachment(0, 0);
+ fdlLastTimeField.right = new FormAttachment(middle, -margin);
+ fdlLastTimeField.top = new FormAttachment(lastControl, margin);
+ wlLastTimeField.setLayoutData(fdlLastTimeField);
+ wLastTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLastTimeField);
+ wLastTimeField.addModifyListener(lsMod);
+ FormData fdLastTimeField = new FormData();
+ fdLastTimeField.left = new FormAttachment(middle, 0);
+ fdLastTimeField.top = new FormAttachment(lastControl, margin);
+ fdLastTimeField.right = new FormAttachment(100, 0);
+ wLastTimeField.setLayoutData(fdLastTimeField);
+ lastControl = wLastTimeField;
+ */
+ wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, e -> ok());
+ wPreview = new Button(shell, SWT.PUSH);
+ wPreview.setText(BaseMessages.getString(PKG, "System.Button.Preview"));
+ wPreview.addListener(SWT.Selection, e -> preview());
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, e -> cancel());
+
+ setButtonPositions(new Button[] {wOk, wPreview, wCancel}, margin, null);
+
+ Label wlFields = new Label(shell, SWT.NONE);
+ wlFields.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Label"));
+ props.setLook(wlFields);
+ FormData fdlFields = new FormData();
+ fdlFields.left = new FormAttachment(0, 0);
+ fdlFields.top = new FormAttachment(lastControl, margin);
+ wlFields.setLayoutData(fdlFields);
+ lastControl = wlFields;
+
+ final int nrFields = input.getFields().size();
+
+ ColumnInfo[] colinf =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Name"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Item"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Type"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ ValueMetaFactory.getValueMetaNames()),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Format"),
+ ColumnInfo.COLUMN_TYPE_FORMAT,
+ 2),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Length"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Precision"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Currency"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Decimal"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Group"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Value"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.SetEmptyString"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ new String[] {
+ BaseMessages.getString(PKG, "System.Combo.Yes"),
+ BaseMessages.getString(PKG, "System.Combo.No")
+ })
+ };
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
+ colinf,
+ nrFields,
+ lsMod,
+ props);
+
+ FormData fdFields = new FormData();
+ fdFields.left = new FormAttachment(0, 0);
+ fdFields.top = new FormAttachment(lastControl, margin);
+ fdFields.right = new FormAttachment(100, 0);
+ fdFields.bottom = new FormAttachment(wOk, -2 * margin);
+ wFields.setLayoutData(fdFields);
+
+ lsResize =
+ event -> {
+ Point size = shell.getSize();
+ wFields.setSize(size.x - 10, size.y - 50);
+ wFields.table.setSize(size.x - 10, size.y - 50);
+ wFields.redraw();
+ };
+ shell.addListener(SWT.Resize, lsResize);
+
+ getData();
+ input.setChanged(changed);
+
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return transformName;
+ };
+
+ @Override
+ public void setActive() {
+ boolean neverEnding = wNeverEnding.getSelection();
+
+ wlLimit.setEnabled(!neverEnding);
+ wLimit.setEnabled(!neverEnding);
+
+ //wlInterval.setEnabled(neverEnding);
+ //wInterval.setEnabled(neverEnding);
+
+ //wlRowTimeField.setEnabled(neverEnding);
+ //wRowTimeField.setEnabled(neverEnding);
+
+ //wlLastTimeField.setEnabled(neverEnding);
+ //wLastTimeField.setEnabled(neverEnding);
+ }
+
+
+
+ private Image getImage() {
+ return SwtSvgImageUtil.getImage( shell.getDisplay(), getClass().getClassLoader(), "plc4x_toddy_read.svg", ConstUi.LARGE_ICON_SIZE,
+ ConstUi.LARGE_ICON_SIZE );
+ }
+
+ /**
+ * Copy information from the meta-data input to the dialog fields.
+ *
+ */
+ public void getData() {
+ if (isDebug()) {
+ logDebug("getting fields info...");
+ }
+ if (input.getConnection() == null) {
+ wConnection.setText("");
+ } else {
+ wConnection.setText(input.getConnection());
+ }
+
+ wLimit.setText(input.getRowLimit());
+ wNeverEnding.setSelection(input.isNeverEnding());
+ wMaxwait.setText(Const.NVL(input.getMaxwaitInMs(), ""));
+ wInterval.setText(Const.NVL(input.getIntervalInMs(), ""));
+ // wRowTimeField.setText(Const.NVL(input.getRowTimeField(), ""));
+ //wLastTimeField.setText(Const.NVL(input.getLastTimeField(), ""));
+
+ for (int i = 0; i < input.getFields().size(); i++) {
+ Plc4xGeneratorField field = input.getFields().get(i);
+ TableItem item = wFields.table.getItem(i);
+ int col = 1;
+ item.setText(col++, Const.NVL(field.getName(), ""));
+
+ item.setText(col++, Const.NVL(field.getItem(), ""));
+
+ String type = field.getType();
+ String format = field.getFormat();
+ String length = field.getLength() < 0 ? "" : ("" + field.getLength());
+ String prec = field.getPrecision() < 0 ? "" : ("" + field.getPrecision());
+
+ String curr = field.getCurrency();
+ String group = field.getGroup();
+ String decim = field.getDecimal();
+ String def = field.getValue();
+
+ item.setText(col++, Const.NVL(type, ""));
+ item.setText(col++, Const.NVL(format, ""));
+ item.setText(col++, Const.NVL(length, ""));
+ item.setText(col++, Const.NVL(prec, ""));
+ item.setText(col++, Const.NVL(curr, ""));
+ item.setText(col++, Const.NVL(decim, ""));
+ item.setText(col++, Const.NVL(group, ""));
+ item.setText(col++, Const.NVL(def, ""));
+ item.setText(
+ col++,
+ field.isSetEmptyString()
+ ? BaseMessages.getString(PKG, "System.Combo.Yes")
+ : BaseMessages.getString(PKG, "System.Combo.No"));
+ }
+
+ wFields.setRowNums();
+ wFields.optWidth(true);
+
+ setActive();
+
+ wTransformName.selectAll();
+ wTransformName.setFocus();
+ }
+
+ /**
+ * Stores the information from the dialog box in meta-data.
+ *
+ * @param meta
+ */
+ private void getInfo( Plc4xReadMeta meta) throws HopException {
+ meta.setConnection(wConnection.getText());
+ meta.setRowLimit(wLimit.getText());
+ meta.setNeverEnding(wNeverEnding.getSelection());
+ meta.setMaxwaitInMs(wMaxwait.getText());
+ meta.setIntervalInMs(wInterval.getText());
+ //meta.setRowTimeField(wRowTimeField.getText());
+ //meta.setLastTimeField(wLastTimeField.getText());
+
+ meta.getFields().clear();
+
+ // CHECKSTYLE:Indentation:OFF
+ for (TableItem item : wFields.getNonEmptyItems()) {
+ Plc4xGeneratorField field = new Plc4xGeneratorField();
+ field.setName(item.getText(1));
+ field.setItem(item.getText(2));
+ field.setFormat(item.getText(4));
+ field.setLength(Const.toInt(item.getText(5), -1));
+ field.setPrecision(Const.toInt(item.getText(6), -1));
+ field.setCurrency(item.getText(7));
+ field.setDecimal(item.getText(8));
+ field.setGroup(item.getText(9));
+ field.setValue(field.isSetEmptyString() ? "" : item.getText(10));
+ field.setSetEmptyString(
+ BaseMessages.getString(PKG, "System.Combo.Yes").equalsIgnoreCase(item.getText(11)));
+ field.setType(field.isSetEmptyString() ? "String" : item.getText(3));
+
+ meta.getFields().add(field);
+ }
+ }
+
+ /**
+ * Cancel the dialog.
+ */
+ private void cancel() {
+ transformName = null;
+ input.setChanged( changed );
+ dispose();
+ }
+
+ private void ok() {
+ if (Utils.isEmpty(wTransformName.getText())) {
+ return;
+ }
+
+ transformName = wTransformName.getText(); // return value
+ try {
+ getInfo(new Plc4xReadMeta()); // to see if there is an exception
+ getInfo(input); // to put the content on the input structure for real if all is well.
+ dispose();
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ }
+ }
+
+
+ /**
+ * Preview the data generated by this transform. This generates a pipeline using this transform &
+ * a dummy and previews it.
+ */
+ private void preview() {
+ Plc4xReadMeta oneMeta = new Plc4xReadMeta();
+ try {
+ getInfo(oneMeta);
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ return;
+ }
+
+ PipelineMeta previewMeta =
+ PipelinePreviewFactory.generatePreviewPipeline(
+ pipelineMeta.getMetadataProvider(), oneMeta, wTransformName.getText());
+
+ EnterNumberDialog numberDialog =
+ new EnterNumberDialog(
+ shell,
+ props.getDefaultPreviewSize(),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Message"));
+ int previewSize = numberDialog.open();
+ if (previewSize > 0) {
+ PipelinePreviewProgressDialog progressDialog =
+ new PipelinePreviewProgressDialog(
+ shell,
+ variables,
+ previewMeta,
+ new String[] {wTransformName.getText()},
+ new int[] {previewSize});
+ progressDialog.open();
+
+ Pipeline pipeline = progressDialog.getPipeline();
+ String loggingText = progressDialog.getLoggingText();
+
+ if (!progressDialog.isCancelled()) {
+ if (pipeline.getResult() != null && pipeline.getResult().getNrErrors() > 0) {
+ EnterTextDialog etd =
+ new EnterTextDialog(
+ shell,
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Message"),
+ loggingText,
+ true);
+ etd.setReadOnly();
+ etd.open();
+ }
+ }
+
+ PreviewRowsDialog prd =
+ new PreviewRowsDialog(
+ shell,
+ variables,
+ SWT.NONE,
+ wTransformName.getText(),
+ progressDialog.getPreviewRowsMeta(wTransformName.getText()),
+ progressDialog.getPreviewRows(wTransformName.getText()),
+ loggingText);
+ prd.open();
+ }
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadMeta.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadMeta.java
new file mode 100644
index 0000000000..3946c9a310
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xinput/Plc4xReadMeta.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xinput;
+
+import java.util.ArrayList;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.core.exception.HopTransformException;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+
+import java.util.List;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.pipeline.transform.ITransformIOMeta;
+import org.apache.hop.pipeline.transform.TransformIOMeta;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+
+/**
+ * Meta data for the sample transform.
+ */
+@Transform(
+ id = "plc4x-read",
+ name = "i18n::Plc4x.Read.Name",
+ description = "i18n::Plc4x.Read.Description",
+ image = "plc4x_read.svg",
+ categoryDescription = "i18n:org.apache.plc4x.hop.transforms.plc4xinput:Plc4x.Category.plc4x",
+ documentationUrl = "https://plc4x.apache.org/users/integrations/apache-calcite.html"
+)
+public class Plc4xReadMeta extends BaseTransformMeta implements ITransformMeta {
+
+ private static final Class<?> PKG = Plc4xReadMeta.class; // Needed by Translator
+
+
+ @HopMetadataProperty(
+ key = "connection",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.Connection")
+ private String connection;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean neverEnding;
+
+ @HopMetadataProperty(
+ key = "maxwait_in_ms",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.MaxwaitInMs")
+ private String maxwaitInMs;
+
+ @HopMetadataProperty(
+ key = "interval_in_ms",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.IntervalInMs")
+ private String intervalInMs;
+
+ @HopMetadataProperty(
+ key = "row_time_field",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.RowTimeField")
+ private String rowTimeField;
+
+ @HopMetadataProperty(
+ key = "last_time_field",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.LastTimeField")
+ private String lastTimeField;
+
+ @HopMetadataProperty(
+ key = "limit",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.RowLimit")
+ private String rowLimit;
+
+ @HopMetadataProperty(
+ groupKey = "fields",
+ key = "field",
+ injectionGroupDescription = "Plc4x.Read.Meta.Injection.Fields",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.Fields")
+ private List<Plc4xGeneratorField> fields;
+
+ public Plc4xReadMeta() {
+ fields = new ArrayList<>();
+
+ rowLimit = "10";
+ neverEnding = false;
+ maxwaitInMs = "1000";
+ intervalInMs = "5000";
+ rowTimeField = "now";
+ lastTimeField = "last";
+ }
+
+ public Plc4xReadMeta(Plc4xReadMeta m) {
+ this.connection = m.connection;
+ this.neverEnding = m.neverEnding;
+ this.intervalInMs = m.intervalInMs;
+ this.rowTimeField = m.rowTimeField;
+ this.lastTimeField = m.lastTimeField;
+ this.rowLimit = m.rowLimit;
+ this.fields = new ArrayList<>();
+ for (Plc4xGeneratorField field : m.fields) {
+ this.fields.add(new Plc4xGeneratorField(field));
+ }
+ }
+
+ @Override
+ public Plc4xReadMeta clone() {
+ return new Plc4xReadMeta(this);
+ }
+
+
+
+ @Override
+ public void getFields( IRowMeta inputRowMeta, String name, IRowMeta[] info, TransformMeta nextTransform,
+ IVariables variables, IHopMetadataProvider metadataProvider ) throws HopTransformException {
+ try {
+ logBasic("PASO 1");
+ List<ICheckResult> remarks = new ArrayList<>();
+ RowMetaAndData rowMetaAndData = Plc4xRead.buildRow(this, remarks, name);
+ logBasic("PASO 2");
+ if (!remarks.isEmpty()) {
+ logBasic("PASO 3");
+ StringBuilder stringRemarks = new StringBuilder();
+ for (ICheckResult remark : remarks) {
+ logBasic("PASO 3x: " + remark.toString());
+ stringRemarks.append(remark.toString()).append(Const.CR);
+ }
+ logBasic("PASO 3.1");
+ throw new HopTransformException(stringRemarks.toString());
+ }
+ logBasic("PASO 4");
+ for (IValueMeta valueMeta : rowMetaAndData.getRowMeta().getValueMetaList()) {
+ valueMeta.setOrigin(name);
+ }
+ logBasic("PASO 5");
+ inputRowMeta.mergeRowMeta(rowMetaAndData.getRowMeta());
+ } catch (Exception e) {
+ throw new HopTransformException(e);
+ }
+ }
+
+
+ public Plc4xRead createTransform(TransformMeta transformMeta, Plc4xReadData data, int copyNr,
+ PipelineMeta pipelineMeta, Pipeline pipeline ) {
+ return new Plc4xRead( transformMeta, this, data, copyNr, pipelineMeta, pipeline );
+ }
+
+
+ public Plc4xReadData getTransformData() {
+ return new Plc4xReadData();
+ }
+
+/*
+ @Override
+ public void loadXml( Node transformNode, IHopMetadataProvider metadataProvider ) throws HopXmlException {
+ //load the saved values from the transformnode
+ String sampleValue = XmlHandler.getTagValue( transformNode, "sampleValue" );
+
+ }
+*/
+ @Override
+ public void setDefault() {
+ //default values when creating a new transform
+ }
+
+
+ /**
+ * Returns the Input/Output metadata for this transform.
+ * The generator transform only produces output, does not accept input!
+ * TransformIOMeta(inputAcceptor, outputProducer, inputOptional, outputDynamic, inputDynamic)
+ */
+ @Override
+ public ITransformIOMeta getTransformIOMeta() {
+ return new TransformIOMeta(false, true, false, false, false, false);
+ }
+
+ /**
+ * Gets Plc4xConnection metadata name.
+ *
+ * @return value of intervalInMs
+ */
+ public String getConnection() {
+ return connection;
+ }
+
+ /** @param connection */
+ public void setConnection(String connection) {
+ this.connection = connection;
+ }
+
+
+ /**
+ * Gets neverEnding
+ *
+ * @return value of neverEnding
+ */
+ public boolean isNeverEnding() {
+ return neverEnding;
+ }
+
+ /** @param neverEnding The neverEnding to set */
+ public void setNeverEnding(boolean neverEnding) {
+ this.neverEnding = neverEnding;
+ }
+
+ /**
+ * Gets intervalInMs
+ *
+ * @return value of intervalInMs
+ */
+ public String getMaxwaitInMs() {
+ return maxwaitInMs;
+ }
+
+ /** @param intervalInMs The intervalInMs to set */
+ public void setMaxwaitInMs(String maxwaitInMs) {
+ this.maxwaitInMs = maxwaitInMs;
+ }
+
+ /**
+ * Gets intervalInMs
+ *
+ * @return value of intervalInMs
+ */
+ public String getIntervalInMs() {
+ return intervalInMs;
+ }
+
+ /** @param intervalInMs The intervalInMs to set */
+ public void setIntervalInMs(String intervalInMs) {
+ this.intervalInMs = intervalInMs;
+ }
+
+ /**
+ * Gets rowTimeField
+ *
+ * @return value of rowTimeField
+ */
+ public String getRowTimeField() {
+ return rowTimeField;
+ }
+
+ /** @param rowTimeField The rowTimeField to set */
+ public void setRowTimeField(String rowTimeField) {
+ this.rowTimeField = rowTimeField;
+ }
+
+ /**
+ * Gets lastTimeField
+ *
+ * @return value of lastTimeField
+ */
+ public String getLastTimeField() {
+ return lastTimeField;
+ }
+
+ /** @param lastTimeField The lastTimeField to set */
+ public void setLastTimeField(String lastTimeField) {
+ this.lastTimeField = lastTimeField;
+ }
+
+ /**
+ * Gets rowLimit
+ *
+ * @return value of rowLimit
+ */
+ public String getRowLimit() {
+ return rowLimit;
+ }
+
+ /** @param rowLimit The rowLimit to set */
+ public void setRowLimit(String rowLimit) {
+ this.rowLimit = rowLimit;
+ }
+
+ /**
+ * Gets fields
+ *
+ * @return value of fields
+ */
+ public List<Plc4xGeneratorField> getFields() {
+ return fields;
+ }
+
+ /** @param fields The fields to set */
+ public void setFields(List<Plc4xGeneratorField> fields) {
+ this.fields = fields;
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWrite.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWrite.java
new file mode 100644
index 0000000000..2381564a75
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWrite.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xoutput;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hop.core.CheckResult;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginException;
+import org.apache.hop.core.exception.HopValueException;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.RowDataUtil;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.StringUtil;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
+import org.apache.hop.pipeline.transform.ITransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.apache.plc4x.hop.transforms.util.Plc4xPlcField;
+import org.apache.plc4x.hop.transforms.util.Plc4xWrapperConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+
+/**
+ * Transform That contains the basic skeleton needed to create your own plugin
+ *
+ */
+public class Plc4xWrite extends BaseTransform<Plc4xWriteMeta, Plc4xWriteData> implements ITransform {
+
+ private static final Class<?> PKG = Plc4xWrite.class; // Needed by Translator
+
+ private Plc4xConnection connmeta = null;
+ private Plc4xWrapperConnection connwrapper = null;
+ private PlcWriteRequest writeRequest = null;
+ private PlcWriteRequest.Builder builder = null;
+ private PlcWriteResponse writeResponse = null;
+
+ private static final ReentrantLock lock = new ReentrantLock();
+
+ private static final String dummy = "dummy";
+
+ private Map<String, Integer> index = new HashMap();
+ private Map<String, Plc4xPlcField> plcfields = new HashMap();
+
+ public Plc4xWrite(TransformMeta transformMeta, Plc4xWriteMeta meta, Plc4xWriteData data, int copyNr, PipelineMeta pipelineMeta,
+ Pipeline pipeline ) {
+ super( transformMeta, meta, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ /*
+ * Including Date and Time field for every row
+ *
+ * @param meta Meta data from user dialog
+ * @param remarks Error registers
+ * @param origin transform instance name
+ */
+ public static final RowMetaAndData buildRow(
+ Plc4xWriteMeta meta, List<ICheckResult> remarks, String origin) throws HopPluginException {
+ IRowMeta rowMeta = new RowMeta();
+ Object[] rowData = RowDataUtil.allocateRowData(meta.getFields().size() + 2);
+ int index = 0;
+
+ if (!Utils.isEmpty(meta.getRowTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getRowTimeField()));
+ rowData[index++] = null;
+ }
+
+ if (!Utils.isEmpty(meta.getLastTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getLastTimeField()));
+ rowData[index++] = null;
+ }
+
+ for (Plc4xGeneratorField field : meta.getFields()) {
+ int typeString = ValueMetaFactory.getIdForValueMeta(field.getType());
+ if (StringUtils.isNotEmpty(field.getType())) {
+ System.out.println("typeString: " + typeString);
+ IValueMeta valueMeta =
+ ValueMetaFactory.createValueMeta(field.getName(), typeString); // build a
+ // value!
+ valueMeta.setLength(field.getLength());
+ valueMeta.setPrecision(field.getPrecision());
+ valueMeta.setConversionMask(field.getFormat());
+ valueMeta.setCurrencySymbol(field.getCurrency());
+ valueMeta.setGroupingSymbol(field.getGroup());
+ valueMeta.setDecimalSymbol(field.getDecimal());
+ valueMeta.setOrigin(origin);
+
+ IValueMeta stringMeta = ValueMetaFactory.cloneValueMeta(valueMeta, IValueMeta.TYPE_STRING);
+
+ if (field.isSetEmptyString()) {
+ // Set empty string
+ rowData[index] = StringUtil.EMPTY_STRING;
+ } else {
+ String stringValue = field.getValue();
+
+ // If the value is empty: consider it to be NULL.
+ if (Utils.isEmpty(stringValue)) {
+ rowData[index] = null;
+
+ if (valueMeta.getType() == IValueMeta.TYPE_NONE) {
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ }
+ } else {
+ // Convert the data from String to the specified type ...
+ //
+ try {
+ System.out.println("stringValue: " + stringValue);
+ rowData[index] = valueMeta.convertData(stringMeta, stringValue);
+ } catch (HopValueException e) {
+ switch (valueMeta.getType()) {
+ case IValueMeta.TYPE_NUMBER:
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Number",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_DATE:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Date",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_INTEGER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Integer",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_BIGNUMBER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.BigNumber",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_TIMESTAMP:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Timestamp",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ default:
+ // Boolean and binary don't throw errors normally, so it's probably an unspecified
+ // error problem...
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+ }
+ }
+ }
+ }
+
+ // Now add value to the row!
+ // This is in fact a copy from the fields row, but now with data.
+ rowMeta.addValueMeta(valueMeta);
+ index++;
+ }
+ }
+
+ return new RowMetaAndData(rowMeta, rowData);
+ }
+
+ /*
+ * 1. Stores the indexes of the incoming fields from the user's selection.
+ * It is only done during the first cycle.
+ * 2. Block the other instances by means of a lock.
+ * 3. Try to locate an existing connection.
+ * 4. If it doesn't exist, it tries to take control of the routine to
+ * create an instance of PlcConnection and his wrapper.
+ * 5. Register the connection wrapper for global access.
+ * 6. If the connection to the PLC is made, then it creates the query
+ * and executes it.
+ *
+ */
+ @Override
+ public boolean processRow() throws HopException {
+ final Object[] r = getRow(); // Get row from input rowset & set row busy!
+
+ if (r == null) {
+ setOutputDone();
+ return false;
+ }
+
+ data.outputRowMeta = getInputRowMeta();
+
+
+ if (first) {
+ index.clear();
+ plcfields.clear();
+ meta.getFields().forEach((f) ->{
+ Integer i = getInputRowMeta().indexOfValue(f.getName()); //(01)
+ if (i>=0) {
+ index.put(f.getName(), i);
+ plcfields.put(f.getName(),Plc4xPlcField.of(f.getItem()));
+ }
+ });
+ first = false;
+ }
+
+ IRowMeta inputRowMeta = getInputRowMeta();
+
+ setLogLevel(LogLevel.DEBUG);
+
+ if ((!meta.isNeverEnding() && data.rowsWritten >= data.rowLimit) && !isStopped()) {
+ setOutputDone(); // signal end to receiver(s)
+ return false;
+ }
+
+ lock.lock(); //(01)
+ try {
+ IHopMetadataProvider metaprovider = getMetadataProvider();
+ connmeta = metaprovider.getSerializer(Plc4xConnection.class).load(meta.getConnection());
+ if (connwrapper == null) {
+ connwrapper = (Plc4xWrapperConnection) getPipeline().getExtensionDataMap().get(meta.getConnection()); //(02)
+ if (connwrapper != null) connwrapper.retain();
+ };
+
+ if (connmeta == null){
+ logError(
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.Log.SetMetadata",
+ meta.getConnection()));
+ }
+
+ if ((connmeta != null) && (connwrapper == null)){
+ writeRequest = null;
+ try{
+ PlcConnection conn = new DefaultPlcDriverManager().getConnection(connmeta.getUrl()); //(03)
+ if (conn.isConnected()) {
+ connwrapper = new Plc4xWrapperConnection(conn);
+ getPipeline().getExtensionDataMap().put(meta.getConnection(), connwrapper); //(04)
+ }
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Unable to create connection to PLC. " + ex.getMessage());
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+
+ if ((connmeta != null) && (connwrapper != null)){
+ if (connwrapper.getConnection().isConnected()){
+
+ builder = null;
+ builder = connwrapper.getConnection().writeRequestBuilder(); //(05)
+ Integer i;
+ for (Plc4xGeneratorField field: meta.getFields()){
+ i = index.get(field.getName());
+ if (i != null) {
+ //From Input Type
+ if (inputRowMeta.getValueMeta(i).getTypeDesc().
+ equalsIgnoreCase(field.getType()))
+ switch(inputRowMeta.getValueMeta(i).getType()) {
+ case IValueMeta.TYPE_BOOLEAN:
+ case IValueMeta.TYPE_INTEGER:
+ case IValueMeta.TYPE_NUMBER:
+ case IValueMeta.TYPE_BIGNUMBER:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ r[i]);
+ break;
+ case IValueMeta.TYPE_DATE:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ Double.parseDouble(inputRowMeta.getString(r, i)));
+ break;
+ case IValueMeta.TYPE_TIMESTAMP:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ Double.parseDouble(inputRowMeta.getString(r, i)));
+ break;
+ case IValueMeta.TYPE_INET:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ Double.parseDouble(inputRowMeta.getString(r, i)));
+ break;
+ case IValueMeta.TYPE_STRING:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ Double.parseDouble(inputRowMeta.getString(r, i)));
+ break;
+ case IValueMeta.TYPE_SERIALIZABLE:
+ builder.addTagAddress(field.getName(),
+ field.getItem(),
+ Double.parseDouble(inputRowMeta.getString(r, i)));
+ break;
+
+ }
+ //field.setValue(inputRowMeta.getString(r, i));
+ };
+ }
+
+ writeRequest = builder.build();
+
+ try {
+ int maxwait = Integer.parseInt(meta.getMaxwaitInMs());
+ maxwait = (maxwait<100)?100:maxwait;
+ writeResponse = writeRequest.execute().get(maxwait, TimeUnit.MILLISECONDS);
+
+ index.forEach((n,y)->{
+ System.out.println("Resultado: " + writeResponse.getResponseCode(n));
+ });
+
+ } catch (Exception ex) {
+ setErrors(1L);
+ logError("Unable read from PLC. " + ex.getMessage());
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC is not connected.");
+ setOutputDone();
+ return false;
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC connection don't exist.");
+ setOutputDone();
+ return false;
+ }
+
+
+ putRow(data.outputRowMeta, r); // return your data
+ data.rowsWritten++;
+ return true;
+ }
+
+
+ @Override
+ public boolean init() {
+ try {
+ if(super.init()){
+ // Determine the number of rows to generate...
+ data.rowLimit = Const.toLong(resolve(meta.getRowLimit()), -1L);
+ data.rowsWritten = 0L;
+ data.delay = Const.toLong(resolve(meta.getIntervalInMs()), -1L);
+
+ if (data.rowLimit < 0L) { // Unable to parse
+ logError(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Wrong.RowLimit.Number"));
+ return false; // fail
+ }
+
+ // Create a row (constants) with all the values in it...
+ List<ICheckResult> remarks = new ArrayList<>(); // stores the errors...
+ RowMetaAndData outputRow = buildRow(meta, remarks, getTransformName());
+ if (!remarks.isEmpty()) {
+ for (int i = 0; i < remarks.size(); i++) {
+ CheckResult cr = (CheckResult) remarks.get(i);
+ logError(cr.getText());
+ }
+ return false;
+ }
+
+ data.outputRowData = outputRow.getData();
+ data.outputRowMeta = outputRow.getRowMeta();
+
+ return true;
+ }
+ return false;
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Error initializing transform", ex);
+ return false;
+ }
+ }
+
+ /*
+ * Here, must perform the cleaning of any resource, main of the connection to
+ * the associated PLC.
+ */
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ logBasic("Cleanup. Release connection.");
+ if (connwrapper != null)
+ connwrapper.release();
+ }
+
+
+ /*
+ * Here, must perform the cleaning of any resource.
+ * 1. Check if we have reference to wrapper.
+ * 2. Release de reference to object.
+ * 3. The lastone remove the global reference to connection wrapper.
+ * 4. Clear local references.
+ */
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (connwrapper != null) {
+ logBasic("Dispose. Release connection: " + connwrapper.refCnt());
+ connwrapper.release();
+ if (!connwrapper.getConnection().isConnected()){
+ getPipeline().getExtensionDataMap().remove(meta.getConnection());
+ }
+ connwrapper = null;
+ writeRequest = null;
+
+ }
+ }
+
+
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteData.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteData.java
new file mode 100644
index 0000000000..81f9c909b8
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteData.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xoutput;
+
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import java.util.Date;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.pipeline.transform.BaseTransformData;
+import org.apache.hop.pipeline.transform.ITransformData;
+
+
+public class Plc4xWriteData extends BaseTransformData implements ITransformData {
+
+ //The Plc4xConnection metadata
+ public String connection;
+
+ public IRowMeta outputRowMeta;
+ public Object[] outputRowData;
+
+ public long rowLimit;
+ public long rowsWritten;
+ public Date rowDate;
+ public Date prevDate;
+ public long delay;
+
+
+
+ /**
+ * Default constructor for SampleData.
+ */
+ public Plc4xWriteData() {
+ super();
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteDialog.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteDialog.java
new file mode 100644
index 0000000000..1e2b3107ca
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteDialog.java
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xoutput;
+
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.PipelinePreviewFactory;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformDialog;
+import org.apache.hop.ui.core.ConstUi;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.dialog.EnterNumberDialog;
+import org.apache.hop.ui.core.dialog.EnterTextDialog;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.dialog.PreviewRowsDialog;
+import org.apache.hop.ui.core.widget.ColumnInfo;
+import org.apache.hop.ui.core.widget.MetaSelectionLine;
+import org.apache.hop.ui.core.widget.TableView;
+import org.apache.hop.ui.core.widget.TextVar;
+import org.apache.hop.ui.pipeline.dialog.PipelinePreviewProgressDialog;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.apache.hop.ui.pipeline.transform.ITableItemInsertListener;
+import org.apache.hop.ui.util.SwtSvgImageUtil;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+public class Plc4xWriteDialog extends BaseTransformDialog implements ITransformDialog {
+ private static final Class<?> PKG = Plc4xWriteDialog.class; // Needed by Translator
+
+ private MetaSelectionLine<Plc4xConnection> wConnection;
+
+ private Label wlLimit;
+ private TextVar wLimit;
+
+ private Button wNeverEnding;
+
+ private Label wlMaxwait;
+ private TextVar wMaxwait;
+
+ private Label wlInterval;
+ private TextVar wInterval;
+
+ private Label wlRowTimeField;
+ private TextVar wRowTimeField;
+
+ private Label wlLastTimeField;
+ private TextVar wLastTimeField;
+
+ private TableView wFields;
+
+ private Button wGetPrvFields;
+
+ private final Plc4xWriteMeta input;
+
+ public Plc4xWriteDialog(Shell parent, IVariables variables , Object in, PipelineMeta pipelineMeta, String sname ) {
+ super( parent, variables, (BaseTransformMeta) in, pipelineMeta, sname );
+ input = (Plc4xWriteMeta) in;
+ }
+
+ @Override
+ public String open() {
+ Shell parent = getParent();
+
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN);
+ props.setLook(shell);
+ setShellImage(shell, input);
+
+ ModifyListener lsMod = e -> input.setChanged();
+ changed = input.hasChanged();
+
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.DialogTitle"));
+
+ int middle = props.getMiddlePct();
+ int margin = props.getMargin();
+
+ // Filename line
+ wlTransformName = new Label(shell, SWT.RIGHT);
+ wlTransformName.setText(BaseMessages.getString(PKG, "System.Label.TransformName"));
+ props.setLook(wlTransformName);
+ fdlTransformName = new FormData();
+ fdlTransformName.left = new FormAttachment(0, 0);
+ fdlTransformName.right = new FormAttachment(middle, -margin);
+ fdlTransformName.top = new FormAttachment(0, margin);
+ wlTransformName.setLayoutData(fdlTransformName);
+
+ wTransformName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wTransformName.setText(transformName);
+ props.setLook(wTransformName);
+ wTransformName.addModifyListener(lsMod);
+ fdTransformName = new FormData();
+ fdTransformName.left = new FormAttachment(middle, 0);
+ fdTransformName.top = new FormAttachment(0, margin);
+ fdTransformName.right = new FormAttachment(100, 0);
+ wTransformName.setLayoutData(fdTransformName);
+
+ // Connection line
+ wConnection =
+ new MetaSelectionLine<>(
+ variables,
+ metadataProvider,
+ Plc4xConnection.class,
+ shell,
+ SWT.NONE,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Label"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Tooltip"));
+ FormData fdConnection = new FormData();
+ fdConnection.left = new FormAttachment(0, 0);
+ fdConnection.right = new FormAttachment(100, 0);
+ fdConnection.top = new FormAttachment(wTransformName, margin);
+ wConnection.setLayoutData(fdConnection);
+ props.setLook(wConnection);
+ try {
+ wConnection.fillItems();
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "Error listing Cassandra connection metadata objects", e);
+ }
+
+ Control lastControl = wConnection;
+
+ wlLimit = new Label(shell, SWT.RIGHT);
+ wlLimit.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Limit.Label"));
+ props.setLook(wlLimit);
+ FormData fdlLimit = new FormData();
+ fdlLimit.left = new FormAttachment(0, 0);
+ fdlLimit.right = new FormAttachment(middle, -margin);
+ fdlLimit.top = new FormAttachment(lastControl, margin);
+ wlLimit.setLayoutData(fdlLimit);
+ wLimit = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLimit);
+ wLimit.addModifyListener(lsMod);
+ FormData fdLimit = new FormData();
+ fdLimit.left = new FormAttachment(middle, 0);
+ fdLimit.top = new FormAttachment(lastControl, margin);
+ fdLimit.right = new FormAttachment(100, 0);
+ wLimit.setLayoutData(fdLimit);
+ lastControl = wLimit;
+
+ Label wlNeverEnding = new Label(shell, SWT.RIGHT);
+ wlNeverEnding.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlNeverEnding);
+ FormData fdlNeverEnding = new FormData();
+ fdlNeverEnding.left = new FormAttachment(0, 0);
+ fdlNeverEnding.right = new FormAttachment(middle, -margin);
+ fdlNeverEnding.top = new FormAttachment(lastControl, margin);
+ wlNeverEnding.setLayoutData(fdlNeverEnding);
+ wNeverEnding = new Button(shell, SWT.CHECK);
+ props.setLook(wNeverEnding);
+ wNeverEnding.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+ FormData fdNeverEnding = new FormData();
+ fdNeverEnding.left = new FormAttachment(middle, 0);
+ fdNeverEnding.top = new FormAttachment(wlNeverEnding, 0, SWT.CENTER);
+ fdNeverEnding.right = new FormAttachment(100, 0);
+ wNeverEnding.setLayoutData(fdNeverEnding);
+ lastControl = wlNeverEnding;
+
+ wlMaxwait = new Label(shell, SWT.RIGHT);
+ wlMaxwait.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Maxwait.Label"));
+ props.setLook(wlMaxwait);
+ FormData fdlMaxwait = new FormData();
+ fdlMaxwait.left = new FormAttachment(0, 0);
+ fdlMaxwait.right = new FormAttachment(middle, -margin);
+ fdlMaxwait.top = new FormAttachment(lastControl, margin);
+ wlMaxwait.setLayoutData(fdlMaxwait);
+ wMaxwait = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wMaxwait);
+ wMaxwait.addModifyListener(lsMod);
+ FormData fdMaxwait = new FormData();
+ fdMaxwait.left = new FormAttachment(middle, 0);
+ fdMaxwait.top = new FormAttachment(lastControl, margin);
+ fdMaxwait.right = new FormAttachment(100, 0);
+ wMaxwait.setLayoutData(fdMaxwait);
+ lastControl = wMaxwait;
+
+ wlInterval = new Label(shell, SWT.RIGHT);
+ wlInterval.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Interval.Label"));
+ props.setLook(wlInterval);
+ FormData fdlInterval = new FormData();
+ fdlInterval.left = new FormAttachment(0, 0);
+ fdlInterval.right = new FormAttachment(middle, -margin);
+ fdlInterval.top = new FormAttachment(lastControl, margin);
+ wlInterval.setLayoutData(fdlInterval);
+ wInterval = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wInterval);
+ wInterval.addModifyListener(lsMod);
+ FormData fdInterval = new FormData();
+ fdInterval.left = new FormAttachment(middle, 0);
+ fdInterval.top = new FormAttachment(lastControl, margin);
+ fdInterval.right = new FormAttachment(100, 0);
+ wInterval.setLayoutData(fdInterval);
+ lastControl = wInterval;
+
+ /*
+ wlRowTimeField = new Label(shell, SWT.RIGHT);
+ wlRowTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.RowTimeField.Label"));
+ props.setLook(wlRowTimeField);
+ FormData fdlRowTimeField = new FormData();
+ fdlRowTimeField.left = new FormAttachment(0, 0);
+ fdlRowTimeField.right = new FormAttachment(middle, -margin);
+ fdlRowTimeField.top = new FormAttachment(lastControl, margin);
+ wlRowTimeField.setLayoutData(fdlRowTimeField);
+ wRowTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wRowTimeField);
+ wRowTimeField.addModifyListener(lsMod);
+ FormData fdRowTimeField = new FormData();
+ fdRowTimeField.left = new FormAttachment(middle, 0);
+ fdRowTimeField.top = new FormAttachment(lastControl, margin);
+ fdRowTimeField.right = new FormAttachment(100, 0);
+ wRowTimeField.setLayoutData(fdRowTimeField);
+ lastControl = wRowTimeField;
+
+ wlLastTimeField = new Label(shell, SWT.RIGHT);
+ wlLastTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.LastTimeField.Label"));
+ props.setLook(wlLastTimeField);
+ FormData fdlLastTimeField = new FormData();
+ fdlLastTimeField.left = new FormAttachment(0, 0);
+ fdlLastTimeField.right = new FormAttachment(middle, -margin);
+ fdlLastTimeField.top = new FormAttachment(lastControl, margin);
+ wlLastTimeField.setLayoutData(fdlLastTimeField);
+ wLastTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLastTimeField);
+ wLastTimeField.addModifyListener(lsMod);
+ FormData fdLastTimeField = new FormData();
+ fdLastTimeField.left = new FormAttachment(middle, 0);
+ fdLastTimeField.top = new FormAttachment(lastControl, margin);
+ fdLastTimeField.right = new FormAttachment(100, 0);
+ wLastTimeField.setLayoutData(fdLastTimeField);
+ lastControl = wLastTimeField;
+ */
+ wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, e -> ok());
+
+ wGet = new Button(shell, SWT.PUSH);
+ wGet.setText(BaseMessages.getString(PKG, "Get Fields"));
+ wGet.addListener(SWT.Selection, e -> getfields());
+
+ wPreview = new Button(shell, SWT.PUSH);
+ wPreview.setText(BaseMessages.getString(PKG, "System.Button.Preview"));
+ wPreview.addListener(SWT.Selection, e -> preview());
+
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, e -> cancel());
+
+ setButtonPositions(new Button[] {wOk, wPreview, wGet, wCancel}, margin, null);
+
+ Label wlFields = new Label(shell, SWT.NONE);
+ wlFields.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Label"));
+ props.setLook(wlFields);
+ FormData fdlFields = new FormData();
+ fdlFields.left = new FormAttachment(0, 0);
+ fdlFields.top = new FormAttachment(lastControl, margin);
+ wlFields.setLayoutData(fdlFields);
+ lastControl = wlFields;
+
+ final int nrFields = input.getFields().size();
+
+ ColumnInfo[] colinf =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Name"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Item"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Type"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ ValueMetaFactory.getValueMetaNames()),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Format"),
+ ColumnInfo.COLUMN_TYPE_FORMAT,
+ 2),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Length"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Precision"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Currency"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Decimal"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Group"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Value"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.SetEmptyString"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ new String[] {
+ BaseMessages.getString(PKG, "System.Combo.Yes"),
+ BaseMessages.getString(PKG, "System.Combo.No")
+ })
+ };
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
+ colinf,
+ nrFields,
+ lsMod,
+ props);
+
+ FormData fdFields = new FormData();
+ fdFields.left = new FormAttachment(0, 0);
+ fdFields.top = new FormAttachment(lastControl, margin);
+ fdFields.right = new FormAttachment(100, 0);
+ fdFields.bottom = new FormAttachment(wOk, -2 * margin);
+ wFields.setLayoutData(fdFields);
+
+ lsResize =
+ event -> {
+ Point size = shell.getSize();
+ wFields.setSize(size.x - 10, size.y - 50);
+ wFields.table.setSize(size.x - 10, size.y - 50);
+ wFields.redraw();
+ };
+ shell.addListener(SWT.Resize, lsResize);
+
+ getData();
+ input.setChanged(changed);
+
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return transformName;
+ };
+
+ public void setActive() {
+ boolean neverEnding = wNeverEnding.getSelection();
+
+ wlLimit.setEnabled(!neverEnding);
+ wLimit.setEnabled(!neverEnding);
+
+ //wlInterval.setEnabled(neverEnding);
+ //wInterval.setEnabled(neverEnding);
+
+ //wlRowTimeField.setEnabled(neverEnding);
+ //wRowTimeField.setEnabled(neverEnding);
+
+ //wlLastTimeField.setEnabled(neverEnding);
+ //wLastTimeField.setEnabled(neverEnding);
+ }
+
+
+
+ private Image getImage() {
+ return SwtSvgImageUtil.getImage( shell.getDisplay(), getClass().getClassLoader(), "plc4x_toddy_read.svg", ConstUi.LARGE_ICON_SIZE,
+ ConstUi.LARGE_ICON_SIZE );
+ }
+
+ /**
+ * Copy information from the meta-data input to the dialog fields.
+ *
+ */
+ public void getData() {
+ if (isDebug()) {
+ logDebug("getting fields info...");
+ }
+ if (input.getConnection() == null) {
+ wConnection.setText("");
+ } else {
+ wConnection.setText(input.getConnection());
+ }
+
+ wLimit.setText(input.getRowLimit());
+ wNeverEnding.setSelection(input.isNeverEnding());
+ wMaxwait.setText(Const.NVL(input.getMaxwaitInMs(), ""));
+ wInterval.setText(Const.NVL(input.getIntervalInMs(), ""));
+ // wRowTimeField.setText(Const.NVL(input.getRowTimeField(), ""));
+ //wLastTimeField.setText(Const.NVL(input.getLastTimeField(), ""));
+
+ for (int i = 0; i < input.getFields().size(); i++) {
+ Plc4xGeneratorField field = input.getFields().get(i);
+ TableItem item = wFields.table.getItem(i);
+ int col = 1;
+ item.setText(col++, Const.NVL(field.getName(), ""));
+
+ item.setText(col++, Const.NVL(field.getItem(), ""));
+
+ String type = field.getType();
+ String format = field.getFormat();
+ String length = field.getLength() < 0 ? "" : ("" + field.getLength());
+ String prec = field.getPrecision() < 0 ? "" : ("" + field.getPrecision());
+
+ String curr = field.getCurrency();
+ String group = field.getGroup();
+ String decim = field.getDecimal();
+ String def = field.getValue();
+
+ item.setText(col++, Const.NVL(type, ""));
+ item.setText(col++, Const.NVL(format, ""));
+ item.setText(col++, Const.NVL(length, ""));
+ item.setText(col++, Const.NVL(prec, ""));
+ item.setText(col++, Const.NVL(curr, ""));
+ item.setText(col++, Const.NVL(decim, ""));
+ item.setText(col++, Const.NVL(group, ""));
+ item.setText(col++, Const.NVL(def, ""));
+ item.setText(
+ col++,
+ field.isSetEmptyString()
+ ? BaseMessages.getString(PKG, "System.Combo.Yes")
+ : BaseMessages.getString(PKG, "System.Combo.No"));
+ }
+
+ wFields.setRowNums();
+ wFields.optWidth(true);
+
+ setActive();
+
+ wTransformName.selectAll();
+ wTransformName.setFocus();
+ }
+
+ /**
+ * Stores the information from the dialog box in meta-data.
+ *
+ * @param meta
+ */
+ private void getInfo( Plc4xWriteMeta meta) throws HopException {
+ meta.setConnection(wConnection.getText());
+ meta.setRowLimit(wLimit.getText());
+ meta.setNeverEnding(wNeverEnding.getSelection());
+ meta.setMaxwaitInMs(wMaxwait.getText());
+ meta.setIntervalInMs(wInterval.getText());
+ //meta.setRowTimeField(wRowTimeField.getText());
+ //meta.setLastTimeField(wLastTimeField.getText());
+
+ meta.getFields().clear();
+
+ // CHECKSTYLE:Indentation:OFF
+ for (TableItem item : wFields.getNonEmptyItems()) {
+ Plc4xGeneratorField field = new Plc4xGeneratorField();
+ field.setName(item.getText(1));
+ field.setItem(item.getText(2));
+ field.setFormat(item.getText(4));
+ field.setLength(Const.toInt(item.getText(5), -1));
+ field.setPrecision(Const.toInt(item.getText(6), -1));
+ field.setCurrency(item.getText(7));
+ field.setDecimal(item.getText(8));
+ field.setGroup(item.getText(9));
+ field.setValue(field.isSetEmptyString() ? "" : item.getText(10));
+ field.setSetEmptyString(
+ BaseMessages.getString(PKG, "System.Combo.Yes").equalsIgnoreCase(item.getText(11)));
+ field.setType(field.isSetEmptyString() ? "String" : item.getText(3));
+
+ meta.getFields().add(field);
+ }
+ }
+
+ /**
+ * Get previos transform fields.
+ * Clear all information in actual fields.
+ *
+ * @param meta
+ */
+ private void getPrevFields(Plc4xWriteMeta meta) throws HopException {
+ IRowMeta r = pipelineMeta.getPrevTransformFields(variables, transformMeta);
+ if (r != null){
+ meta.getFields().clear();
+ r.getValueMetaList().forEach((f)->{
+ Plc4xGeneratorField field = new Plc4xGeneratorField();
+ field.setName(f.getName());
+ field.setItem("");
+ field.setType(f.getTypeDesc());
+ field.setFormat(f.getFormatMask());
+ field.setLength(f.getLength());
+ field.setPrecision(f.getPrecision());
+ field.setCurrency(f.getCurrencySymbol());
+ field.setDecimal(f.getDecimalSymbol());
+ field.setGroup(f.getGroupingSymbol());
+ field.setValue(f.getStringEncoding());
+ meta.getFields().add(field);
+ });
+ }
+ }
+
+
+ /**
+ * Cancel the dialog.
+ */
+ private void cancel() {
+ transformName = null;
+ input.setChanged( changed );
+ dispose();
+ }
+
+ private void ok() {
+ if (Utils.isEmpty(wTransformName.getText())) {
+ return;
+ }
+
+ transformName = wTransformName.getText(); // return value
+ try {
+ getInfo(new Plc4xWriteMeta()); // to see if there is an exception
+ getInfo(input); // to put the content on the input structure for real if all is well.
+ dispose();
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ }
+ }
+
+private void getfields() {
+ try {
+
+ IRowMeta r = pipelineMeta.getPrevTransformFields(variables, transformName);
+
+ if (r != null && !r.isEmpty()) {
+ ITableItemInsertListener listener =
+ (tableItem, v) -> {
+
+ tableItem.setText(2, "");
+ tableItem.setText(3, v.getTypeDesc());
+ tableItem.setText(4, v.getFormatMask()==null?"":v.getFormatMask());
+ tableItem.setText(5, Integer.toString(v.getLength()));
+ tableItem.setText(6, Integer.toString(v.getPrecision()));
+ tableItem.setText(7, v.getCurrencySymbol()==null?"":v.getCurrencySymbol());
+ tableItem.setText(8, v.getDecimalSymbol()==null?"":v.getDecimalSymbol());
+ tableItem.setText(9, v.getGroupingSymbol()==null?"":v.getGroupingSymbol());
+ //tableItem.setText(10, "N");
+ tableItem.setText(11, "N");
+ return true;
+ };
+ BaseTransformDialog.getFieldsFromPrevious(
+ r, wFields, 1, new int[] {1}, null, -1, -1, listener);
+ }
+
+
+
+
+ } catch (Exception ex){
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ ex);
+ }
+}
+
+ /**
+ * Preview the data generated by this transform. This generates a pipeline using this transform &
+ * a dummy and previews it.
+ */
+ private void preview() {
+ Plc4xWriteMeta oneMeta = new Plc4xWriteMeta();
+ try {
+ getInfo(oneMeta);
+ } catch (HopException e) {
+ new ErrorDialog(
+ shell,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Title"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Illegal.Dialog.Settings.Message"),
+ e);
+ return;
+ }
+
+ PipelineMeta previewMeta =
+ PipelinePreviewFactory.generatePreviewPipeline(
+ pipelineMeta.getMetadataProvider(), oneMeta, wTransformName.getText());
+
+ EnterNumberDialog numberDialog =
+ new EnterNumberDialog(
+ shell,
+ props.getDefaultPreviewSize(),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.EnterPreviewSize.Message"));
+ int previewSize = numberDialog.open();
+ if (previewSize > 0) {
+ PipelinePreviewProgressDialog progressDialog =
+ new PipelinePreviewProgressDialog(
+ shell,
+ variables,
+ previewMeta,
+ new String[] {wTransformName.getText()},
+ new int[] {previewSize});
+ progressDialog.open();
+
+ Pipeline pipeline = progressDialog.getPipeline();
+ String loggingText = progressDialog.getLoggingText();
+
+ if (!progressDialog.isCancelled()) {
+ if (pipeline.getResult() != null && pipeline.getResult().getNrErrors() > 0) {
+ EnterTextDialog etd =
+ new EnterTextDialog(
+ shell,
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Title"),
+ BaseMessages.getString(PKG, "System.Dialog.PreviewError.Message"),
+ loggingText,
+ true);
+ etd.setReadOnly();
+ etd.open();
+ }
+ }
+
+ PreviewRowsDialog prd =
+ new PreviewRowsDialog(
+ shell,
+ variables,
+ SWT.NONE,
+ wTransformName.getText(),
+ progressDialog.getPreviewRowsMeta(wTransformName.getText()),
+ progressDialog.getPreviewRows(wTransformName.getText()),
+ loggingText);
+ prd.open();
+ }
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteMeta.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteMeta.java
new file mode 100644
index 0000000000..d3996ad4a9
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xoutput/Plc4xWriteMeta.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xoutput;
+
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import java.util.ArrayList;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.core.exception.HopTransformException;
+import org.apache.hop.core.exception.HopXmlException;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.xml.XmlHandler;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.w3c.dom.Node;
+
+import java.util.List;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.pipeline.transform.ITransformIOMeta;
+import org.apache.hop.pipeline.transform.TransformIOMeta;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+
+/**
+ * Meta data for the sample transform.
+ */
+@Transform(
+ id = "plc4x-write",
+ name = "i18n::Plc4x.Read.Name",
+ description = "i18n::Plc4x.Read.Description",
+ image = "plc4x_write.svg",
+ categoryDescription = "i18n:org.apache.plc4x.hop.transforms.plc4xoutput:Plc4x.Category.plc4x",
+ documentationUrl = "https://plc4x.apache.org/users/integrations/apache-calcite.html"
+)
+public class Plc4xWriteMeta extends BaseTransformMeta implements ITransformMeta {
+
+ private static final Class<?> PKG = Plc4xWriteMeta.class; // Needed by Translator
+
+
+ @HopMetadataProperty(
+ key = "connection",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.Connection")
+ private String connection;
+
+ @HopMetadataProperty(
+ key = "never_ending",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.NeverEnding")
+ private boolean neverEnding;
+
+ @HopMetadataProperty(
+ key = "maxwait_in_ms",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.MaxwaitInMs")
+ private String maxwaitInMs;
+
+ @HopMetadataProperty(
+ key = "interval_in_ms",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.IntervalInMs")
+ private String intervalInMs;
+
+ @HopMetadataProperty(
+ key = "row_time_field",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.RowTimeField")
+ private String rowTimeField;
+
+ @HopMetadataProperty(
+ key = "last_time_field",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.LastTimeField")
+ private String lastTimeField;
+
+ @HopMetadataProperty(
+ key = "limit",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.RowLimit")
+ private String rowLimit;
+
+ @HopMetadataProperty(
+ groupKey = "fields",
+ key = "field",
+ injectionGroupDescription = "Plc4x.Read.Meta.Injection.Fields",
+ injectionKeyDescription = "Plc4x.Read.Meta.Injection.Fields")
+ private List<Plc4xGeneratorField> fields;
+
+ public Plc4xWriteMeta() {
+ fields = new ArrayList<>();
+
+ rowLimit = "10";
+ neverEnding = false;
+ maxwaitInMs = "1000";
+ intervalInMs = "5000";
+ rowTimeField = "now";
+ lastTimeField = "last";
+ }
+
+ public Plc4xWriteMeta(Plc4xWriteMeta m) {
+ this.connection = m.connection;
+ this.neverEnding = m.neverEnding;
+ this.intervalInMs = m.intervalInMs;
+ this.rowTimeField = m.rowTimeField;
+ this.lastTimeField = m.lastTimeField;
+ this.rowLimit = m.rowLimit;
+ this.fields = new ArrayList<>();
+ for (Plc4xGeneratorField field : m.fields) {
+ this.fields.add(new Plc4xGeneratorField(field));
+ }
+ }
+
+ @Override
+ public Plc4xWriteMeta clone() {
+ return new Plc4xWriteMeta(this);
+ }
+
+
+
+ @Override
+ public void getFields( IRowMeta inputRowMeta, String name, IRowMeta[] info, TransformMeta nextTransform,
+ IVariables variables, IHopMetadataProvider metadataProvider ) throws HopTransformException {
+ try {
+ logBasic("PASO 1");
+ List<ICheckResult> remarks = new ArrayList<>();
+ RowMetaAndData rowMetaAndData = Plc4xWrite.buildRow(this, remarks, name);
+ logBasic("PASO 2");
+ if (!remarks.isEmpty()) {
+ logBasic("PASO 3");
+ StringBuilder stringRemarks = new StringBuilder();
+ for (ICheckResult remark : remarks) {
+ logBasic("PASO 3x: " + remark.toString());
+ stringRemarks.append(remark.toString()).append(Const.CR);
+ }
+ logBasic("PASO 3.1");
+ throw new HopTransformException(stringRemarks.toString());
+ }
+ logBasic("PASO 4");
+ for (IValueMeta valueMeta : rowMetaAndData.getRowMeta().getValueMetaList()) {
+ valueMeta.setOrigin(name);
+ }
+ logBasic("PASO 5");
+ inputRowMeta.mergeRowMeta(rowMetaAndData.getRowMeta());
+ } catch (Exception e) {
+ throw new HopTransformException(e);
+ }
+ }
+
+
+ public Plc4xWrite createTransform(TransformMeta transformMeta, Plc4xWriteData data, int copyNr,
+ PipelineMeta pipelineMeta, Pipeline pipeline ) {
+ return new Plc4xWrite( transformMeta, this, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ public Plc4xWriteData getTransformData() {
+ return new Plc4xWriteData();
+ }
+/*
+ @Override
+ public void loadXml( Node transformNode, IHopMetadataProvider metadataProvider ) throws HopXmlException {
+ //load the saved values from the transformnode
+ String sampleValue = XmlHandler.getTagValue( transformNode, "sampleValue" );
+
+ }
+*/
+ @Override
+ public void setDefault() {
+ //default values when creating a new transform
+ }
+
+
+ /**
+ * Returns the Input/Output metadata for this transform.
+ * The generator transform only produces output, does not accept input!
+ * TransformIOMeta(inputAcceptor, outputProducer, inputOptional, outputDynamic, inputDynamic)
+ */
+ @Override
+ public ITransformIOMeta getTransformIOMeta() {
+ return new TransformIOMeta(false, true, false, false, false, false);
+ }
+
+ /**
+ * Gets Plc4xConnection metadata name.
+ *
+ * @return value of intervalInMs
+ */
+ public String getConnection() {
+ return connection;
+ }
+
+ /** @param connection */
+ public void setConnection(String connection) {
+ this.connection = connection;
+ }
+
+
+ /**
+ * Gets neverEnding
+ *
+ * @return value of neverEnding
+ */
+ public boolean isNeverEnding() {
+ return neverEnding;
+ }
+
+ /** @param neverEnding The neverEnding to set */
+ public void setNeverEnding(boolean neverEnding) {
+ this.neverEnding = neverEnding;
+ }
+
+ /**
+ * Gets intervalInMs
+ *
+ * @return value of intervalInMs
+ */
+ public String getMaxwaitInMs() {
+ return maxwaitInMs;
+ }
+
+ /** @param intervalInMs The intervalInMs to set */
+ public void setMaxwaitInMs(String maxwaitInMs) {
+ this.maxwaitInMs = maxwaitInMs;
+ }
+
+ /**
+ * Gets intervalInMs
+ *
+ * @return value of intervalInMs
+ */
+ public String getIntervalInMs() {
+ return intervalInMs;
+ }
+
+ /** @param intervalInMs The intervalInMs to set */
+ public void setIntervalInMs(String intervalInMs) {
+ this.intervalInMs = intervalInMs;
+ }
+
+ /**
+ * Gets rowTimeField
+ *
+ * @return value of rowTimeField
+ */
+ public String getRowTimeField() {
+ return rowTimeField;
+ }
+
+ /** @param rowTimeField The rowTimeField to set */
+ public void setRowTimeField(String rowTimeField) {
+ this.rowTimeField = rowTimeField;
+ }
+
+ /**
+ * Gets lastTimeField
+ *
+ * @return value of lastTimeField
+ */
+ public String getLastTimeField() {
+ return lastTimeField;
+ }
+
+ /** @param lastTimeField The lastTimeField to set */
+ public void setLastTimeField(String lastTimeField) {
+ this.lastTimeField = lastTimeField;
+ }
+
+ /**
+ * Gets rowLimit
+ *
+ * @return value of rowLimit
+ */
+ public String getRowLimit() {
+ return rowLimit;
+ }
+
+ /** @param rowLimit The rowLimit to set */
+ public void setRowLimit(String rowLimit) {
+ this.rowLimit = rowLimit;
+ }
+
+ /**
+ * Gets fields
+ *
+ * @return value of fields
+ */
+ public List<Plc4xGeneratorField> getFields() {
+ return fields;
+ }
+
+ /** @param fields The fields to set */
+ public void setFields(List<Plc4xGeneratorField> fields) {
+ this.fields = fields;
+ }
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubs.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubs.java
new file mode 100644
index 0000000000..51c6c9d536
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubs.java
@@ -0,0 +1,446 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xsubs;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hop.core.CheckResult;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.RowMetaAndData;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginException;
+import org.apache.hop.core.exception.HopValueException;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.RowDataUtil;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.StringUtil;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.BaseTransform;
+import org.apache.hop.pipeline.transform.ITransform;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.apache.plc4x.hop.transforms.util.Plc4xPlcField;
+import org.apache.plc4x.hop.transforms.util.Plc4xWrapperConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+
+/**
+ * Transform That contains the basic skeleton needed to create your own plugin
+ *
+ */
+public class Plc4xSubs extends BaseTransform<Plc4xSubsMeta, Plc4xSubsData> implements ITransform {
+
+ private static final Class<?> PKG = Plc4xSubs.class; // Needed by Translator
+
+ private Plc4xConnection connmeta = null;
+ private Plc4xWrapperConnection connwrapper = null;
+ private PlcReadRequest readRequest = null;
+ private PlcReadResponse readResponse = null;
+ private int maxwait = 0;
+ private static final ReentrantLock lock = new ReentrantLock();
+
+ private static final String dummy = "dummy";
+
+ private Map<String, Integer> index = new HashMap();
+ private Map<String, Plc4xPlcField> plcfields = new HashMap();
+
+ public Plc4xSubs(TransformMeta transformMeta, Plc4xSubsMeta meta, Plc4xSubsData data, int copyNr, PipelineMeta pipelineMeta,
+ Pipeline pipeline ) {
+ super( transformMeta, meta, data, copyNr, pipelineMeta, pipeline );
+ }
+
+ /*
+ * Including Date and Time field for every row
+ *
+ * @param meta Meta data from user dialog
+ * @param remarks Error registers
+ * @param origin transform instance name
+ */
+ public static final RowMetaAndData buildRow(
+ Plc4xSubsMeta meta, List<ICheckResult> remarks, String origin) throws HopPluginException {
+ IRowMeta rowMeta = new RowMeta();
+ Object[] rowData = RowDataUtil.allocateRowData(meta.getFields().size() + 2);
+ int index = 0;
+
+ if (!Utils.isEmpty(meta.getRowTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getRowTimeField()));
+ rowData[index++] = null;
+ }
+
+ if (!Utils.isEmpty(meta.getLastTimeField())) {
+ rowMeta.addValueMeta(new ValueMetaDate(meta.getLastTimeField()));
+ rowData[index++] = null;
+ }
+
+ for (Plc4xGeneratorField field : meta.getFields()) {
+ int typeString = ValueMetaFactory.getIdForValueMeta(field.getType());
+ if (StringUtils.isNotEmpty(field.getType())) {
+ System.out.println("typeString: " + typeString);
+ IValueMeta valueMeta =
+ ValueMetaFactory.createValueMeta(field.getName(), typeString); // build a
+ // value!
+ valueMeta.setLength(field.getLength());
+ valueMeta.setPrecision(field.getPrecision());
+ valueMeta.setConversionMask(field.getFormat());
+ valueMeta.setCurrencySymbol(field.getCurrency());
+ valueMeta.setGroupingSymbol(field.getGroup());
+ valueMeta.setDecimalSymbol(field.getDecimal());
+ valueMeta.setOrigin(origin);
+
+ IValueMeta stringMeta = ValueMetaFactory.cloneValueMeta(valueMeta, IValueMeta.TYPE_STRING);
+
+ if (field.isSetEmptyString()) {
+ // Set empty string
+ rowData[index] = StringUtil.EMPTY_STRING;
+ } else {
+ String stringValue = field.getValue();
+
+ // If the value is empty: consider it to be NULL.
+ if (Utils.isEmpty(stringValue)) {
+ rowData[index] = null;
+
+ if (valueMeta.getType() == IValueMeta.TYPE_NONE) {
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ }
+ } else {
+ // Convert the data from String to the specified type ...
+ //
+ try {
+ System.out.println("stringValue: " + stringValue);
+ rowData[index] = valueMeta.convertData(stringMeta, stringValue);
+ } catch (HopValueException e) {
+ switch (valueMeta.getType()) {
+ case IValueMeta.TYPE_NUMBER:
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Number",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_DATE:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Date",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_INTEGER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Integer",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_BIGNUMBER:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.BigNumber",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ case IValueMeta.TYPE_TIMESTAMP:
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.BuildRow.Error.Parsing.Timestamp",
+ valueMeta.getName(),
+ stringValue,
+ e.toString());
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+
+ default:
+ // Boolean and binary don't throw errors normally, so it's probably an unspecified
+ // error problem...
+ message =
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.CheckResult.SpecifyTypeError",
+ valueMeta.getName(),
+ stringValue);
+ remarks.add(new CheckResult(ICheckResult.TYPE_RESULT_ERROR, message, null));
+ break;
+ }
+ }
+ }
+ }
+
+ // Now add value to the row!
+ // This is in fact a copy from the fields row, but now with data.
+ rowMeta.addValueMeta(valueMeta);
+ index++;
+ }
+ }
+
+ return new RowMetaAndData(rowMeta, rowData);
+ }
+
+ /*
+ * 1. Block the other instances by means of a lock.
+ * 2. Try to locate an existing connection.
+ * 3. If it doesn't exist, it tries to take control of the routine to
+ * create an instance of PlcConnection and his wrapper.
+ * 4. Register the connection wrapper for global access.
+ * 5. If the connection to the PLC is made, then it creates the query
+ * and executes it.
+ *
+ */
+ @Override
+ public boolean processRow() throws HopException {
+ Object[] r = getRow(); // Get row from input rowset & set row busy!
+ setLogLevel(LogLevel.DEBUG);
+
+ if ((!meta.isNeverEnding() && data.rowsWritten >= data.rowLimit) && !isStopped()) {
+ setOutputDone(); // signal end to receiver(s)
+ return false;
+ }
+
+ if (first) {
+ index.clear();
+ plcfields.clear();
+ //This performs a minimal check on the user item.
+ //It guarantees that the rates are within those managed by Plc4x.
+ meta.getFields().forEach((f) ->{
+ plcfields.put(f.getName(),Plc4xPlcField.of(f.getItem()));
+ });
+ first = false;
+ }
+
+ lock.lock(); //(01)
+ try {
+ IHopMetadataProvider metaprovider = getMetadataProvider();
+ connmeta = metaprovider.getSerializer(Plc4xConnection.class).load(meta.getConnection());
+ if (connwrapper == null) {
+ connwrapper = (Plc4xWrapperConnection) getPipeline().getExtensionDataMap().get(meta.getConnection()); //(02)
+ if (connwrapper != null) connwrapper.retain();
+ };
+
+ if (connmeta == null){
+ logError(
+ BaseMessages.getString(
+ PKG,
+ "Plc4x.Read.Meta.Log.SetMetadata",
+ meta.getConnection()));
+ }
+
+ if ((connmeta != null) && (connwrapper == null)){
+ readRequest = null;
+ try{
+ PlcConnection conn = new DefaultPlcDriverManager().getConnection(connmeta.getUrl()); //(03)
+ if (conn.isConnected()) {
+ connwrapper = new Plc4xWrapperConnection(conn);
+ getPipeline().getExtensionDataMap().put(meta.getConnection(), connwrapper); //(04)
+ }
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Unable to create connection to PLC. " + ex.getMessage());
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+
+ if ((connmeta != null) && (connwrapper != null)){
+ if (connwrapper.getConnection().isConnected()){
+ if (readRequest == null){
+ PlcReadRequest.Builder builder = connwrapper.getConnection().readRequestBuilder(); //(05)
+ for (Plc4xGeneratorField field: meta.getFields()){
+ builder.addTagAddress(field.getName(), field.getItem());
+ }
+ readRequest = builder.build();
+ }
+ try {
+ maxwait = Integer.parseInt(meta.getMaxwaitInMs());
+ maxwait = (maxwait<100)?100:maxwait;
+ readResponse = readRequest.execute().get(maxwait, TimeUnit.MILLISECONDS);
+
+ for (Plc4xGeneratorField field: meta.getFields()){
+ field.setValue(readResponse.getString(field.getName()));
+ }
+ } catch (Exception ex) {
+ setErrors(1L);
+ logError("Unable read from PLC. " + ex.getMessage());
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC is not connected.");
+ setOutputDone();
+ return false;
+ }
+
+ } else {
+ setErrors(1L);
+ logError("PLC connection don't exist.");
+ setOutputDone();
+ return false;
+ }
+
+ //
+ int interval = Integer.parseInt(meta.getIntervalInMs());
+
+ try {
+ Thread.sleep(interval);
+ } catch (InterruptedException ex) {
+ setErrors(1L);
+ logError(ex.getMessage());
+ }
+
+ r = data.outputRowMeta.cloneRow(data.outputRowData);
+ logBasic("Tamano de los datos: " + r.length);
+ data.prevDate = data.rowDate;
+ data.rowDate = new Date();
+ int index = 0;
+ if (!Utils.isEmpty(meta.getRowTimeField())) {
+ r[index++] = data.rowDate;
+ }
+ if (!Utils.isEmpty(meta.getLastTimeField())) {
+ r[index++] = data.prevDate;
+ }
+ for (Plc4xGeneratorField field: meta.getFields()){
+ if (field.getType().equalsIgnoreCase("Boolean")){
+ r[index++] = Boolean.parseBoolean(field.getValue());
+ } else if (field.getType().equalsIgnoreCase("Number")){
+ r[index++] = Double.parseDouble(field.getValue());
+ } else if (field.getType().equalsIgnoreCase("Integer")){
+ r[index++] = Integer.parseInt(field.getValue());
+ }
+ }
+ putRow(data.outputRowMeta, r ); // return your data
+ data.rowsWritten++;
+ return true;
+ }
+
+
+ @Override
+ public boolean init() {
+ try {
+ if(super.init()){
+ // Determine the number of rows to generate...
+ data.rowLimit = Const.toLong(resolve(meta.getRowLimit()), -1L);
+ data.rowsWritten = 0L;
+ data.delay = Const.toLong(resolve(meta.getIntervalInMs()), -1L);
+
+ if (data.rowLimit < 0L) { // Unable to parse
+ logError(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Wrong.RowLimit.Number"));
+ return false; // fail
+ }
+
+ // Create a row (constants) with all the values in it...
+ List<ICheckResult> remarks = new ArrayList<>(); // stores the errors...
+ RowMetaAndData outputRow = buildRow(meta, remarks, getTransformName());
+ if (!remarks.isEmpty()) {
+ for (int i = 0; i < remarks.size(); i++) {
+ CheckResult cr = (CheckResult) remarks.get(i);
+ logError(cr.getText());
+ }
+ return false;
+ }
+
+ data.outputRowData = outputRow.getData();
+ data.outputRowMeta = outputRow.getRowMeta();
+
+ return true;
+ }
+ return false;
+ } catch (Exception ex){
+ setErrors(1L);
+ logError("Error initializing transform", ex);
+ return false;
+ }
+ }
+
+ /*
+ * Here, must perform the cleaning of any resource, main of the connection to
+ * the associated PLC.
+ */
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ logBasic("Cleanup. Release connection.");
+ if (connwrapper != null)
+ connwrapper.release();
+ }
+
+
+ /*
+ * Here, must perform the cleaning of any resource.
+ * 1. Check if we have reference to wrapper.
+ * 2. Release de reference to object.
+ * 3. The lastone remove the global reference to connection wrapper.
+ * 4. Clear local references.
+ */
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (connwrapper != null) {
+ logBasic("Dispose. Release connection: " + connwrapper.refCnt());
+ connwrapper.release();
+ if (!connwrapper.getConnection().isConnected()){
+ getPipeline().getExtensionDataMap().remove(meta.getConnection());
+ }
+ connwrapper = null;
+ readRequest = null;
+
+ }
+ }
+
+
+
+
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsData.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsData.java
new file mode 100644
index 0000000000..e39dad1456
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsData.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xsubs;
+
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import java.util.Date;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.pipeline.transform.BaseTransformData;
+import org.apache.hop.pipeline.transform.ITransformData;
+
+
+public class Plc4xSubsData extends BaseTransformData implements ITransformData {
+
+ //The Plc4xConnection metadata
+ public String connection;
+
+ public IRowMeta outputRowMeta;
+ public Object[] outputRowData;
+
+ public long rowLimit;
+ public long rowsWritten;
+ public Date rowDate;
+ public Date prevDate;
+ public long delay;
+
+
+
+ /**
+ * Default constructor for SampleData.
+ */
+ public Plc4xSubsData() {
+ super();
+ }
+}
diff --git a/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsDialog.java b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsDialog.java
new file mode 100644
index 0000000000..e5d14f2c8b
--- /dev/null
+++ b/plc4j/integrations/apache-hop/plc4x-hop-transformer/src/main/java/org/apache/plc4x/hop/transforms/plc4xsubs/Plc4xSubsDialog.java
@@ -0,0 +1,601 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.plc4x.hop.transforms.plc4xsubs;
+
+import org.apache.plc4x.hop.transforms.plc4xinput.*;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.pipeline.Pipeline;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.PipelinePreviewFactory;
+import org.apache.hop.pipeline.transform.BaseTransformMeta;
+import org.apache.hop.pipeline.transform.ITransformDialog;
+import org.apache.hop.ui.core.ConstUi;
+import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.dialog.EnterNumberDialog;
+import org.apache.hop.ui.core.dialog.EnterTextDialog;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.dialog.PreviewRowsDialog;
+import org.apache.hop.ui.core.widget.ColumnInfo;
+import org.apache.hop.ui.core.widget.MetaSelectionLine;
+import org.apache.hop.ui.core.widget.TableView;
+import org.apache.hop.ui.core.widget.TextVar;
+import org.apache.hop.ui.pipeline.dialog.PipelinePreviewProgressDialog;
+import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
+import org.apache.hop.ui.util.SwtSvgImageUtil;
+import org.apache.plc4x.hop.metadata.Plc4xConnection;
+import org.apache.plc4x.hop.transforms.util.Plc4xGeneratorField;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+public class Plc4xSubsDialog extends BaseTransformDialog implements ITransformDialog {
+ private static final Class<?> PKG = Plc4xSubsDialog.class; // Needed by Translator
+
+ private MetaSelectionLine<Plc4xConnection> wConnection;
+
+ private Label wlLimit;
+ private TextVar wLimit;
+
+ private Button wNeverEnding;
+
+ private Label wlMaxwait;
+ private TextVar wMaxwait;
+
+ private Label wlInterval;
+ private TextVar wInterval;
+
+ private Label wlRowTimeField;
+ private TextVar wRowTimeField;
+
+ private Label wlLastTimeField;
+ private TextVar wLastTimeField;
+
+ private TableView wFields;
+
+ private final Plc4xSubsMeta input;
+
+ public Plc4xSubsDialog(Shell parent, IVariables variables , Object in, PipelineMeta pipelineMeta, String sname ) {
+ super( parent, variables, (BaseTransformMeta) in, pipelineMeta, sname );
+ input = (Plc4xSubsMeta) in;
+ }
+
+ @Override
+ public String open() {
+ Shell parent = getParent();
+
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN);
+ props.setLook(shell);
+ setShellImage(shell, input);
+
+ ModifyListener lsMod = e -> input.setChanged();
+ changed = input.hasChanged();
+
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.DialogTitle"));
+
+ int middle = props.getMiddlePct();
+ int margin = props.getMargin();
+
+ // Filename line
+ wlTransformName = new Label(shell, SWT.RIGHT);
+ wlTransformName.setText(BaseMessages.getString(PKG, "System.Label.TransformName"));
+ props.setLook(wlTransformName);
+ fdlTransformName = new FormData();
+ fdlTransformName.left = new FormAttachment(0, 0);
+ fdlTransformName.right = new FormAttachment(middle, -margin);
+ fdlTransformName.top = new FormAttachment(0, margin);
+ wlTransformName.setLayoutData(fdlTransformName);
+
+ wTransformName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wTransformName.setText(transformName);
+ props.setLook(wTransformName);
+ wTransformName.addModifyListener(lsMod);
+ fdTransformName = new FormData();
+ fdTransformName.left = new FormAttachment(middle, 0);
+ fdTransformName.top = new FormAttachment(0, margin);
+ fdTransformName.right = new FormAttachment(100, 0);
+ wTransformName.setLayoutData(fdTransformName);
+
+ // Connection line
+ wConnection =
+ new MetaSelectionLine<>(
+ variables,
+ metadataProvider,
+ Plc4xConnection.class,
+ shell,
+ SWT.NONE,
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Label"),
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Connection.Tooltip"));
+ FormData fdConnection = new FormData();
+ fdConnection.left = new FormAttachment(0, 0);
+ fdConnection.right = new FormAttachment(100, 0);
+ fdConnection.top = new FormAttachment(wTransformName, margin);
+ wConnection.setLayoutData(fdConnection);
+ props.setLook(wConnection);
+ try {
+ wConnection.fillItems();
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "Error listing Cassandra connection metadata objects", e);
+ }
+
+ Control lastControl = wConnection;
+
+ wlLimit = new Label(shell, SWT.RIGHT);
+ wlLimit.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Limit.Label"));
+ props.setLook(wlLimit);
+ FormData fdlLimit = new FormData();
+ fdlLimit.left = new FormAttachment(0, 0);
+ fdlLimit.right = new FormAttachment(middle, -margin);
+ fdlLimit.top = new FormAttachment(lastControl, margin);
+ wlLimit.setLayoutData(fdlLimit);
+ wLimit = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLimit);
+ wLimit.addModifyListener(lsMod);
+ FormData fdLimit = new FormData();
+ fdLimit.left = new FormAttachment(middle, 0);
+ fdLimit.top = new FormAttachment(lastControl, margin);
+ fdLimit.right = new FormAttachment(100, 0);
+ wLimit.setLayoutData(fdLimit);
+ lastControl = wLimit;
+
+ Label wlNeverEnding = new Label(shell, SWT.RIGHT);
+ wlNeverEnding.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.NeverEnding.Label"));
+ props.setLook(wlNeverEnding);
+ FormData fdlNeverEnding = new FormData();
+ fdlNeverEnding.left = new FormAttachment(0, 0);
+ fdlNeverEnding.right = new FormAttachment(middle, -margin);
+ fdlNeverEnding.top = new FormAttachment(lastControl, margin);
+ wlNeverEnding.setLayoutData(fdlNeverEnding);
+ wNeverEnding = new Button(shell, SWT.CHECK);
+ props.setLook(wNeverEnding);
+ wNeverEnding.addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setActive();
+ input.setChanged();
+ }
+ });
+ FormData fdNeverEnding = new FormData();
+ fdNeverEnding.left = new FormAttachment(middle, 0);
+ fdNeverEnding.top = new FormAttachment(wlNeverEnding, 0, SWT.CENTER);
+ fdNeverEnding.right = new FormAttachment(100, 0);
+ wNeverEnding.setLayoutData(fdNeverEnding);
+ lastControl = wlNeverEnding;
+
+ wlMaxwait = new Label(shell, SWT.RIGHT);
+ wlMaxwait.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Maxwait.Label"));
+ props.setLook(wlMaxwait);
+ FormData fdlMaxwait = new FormData();
+ fdlMaxwait.left = new FormAttachment(0, 0);
+ fdlMaxwait.right = new FormAttachment(middle, -margin);
+ fdlMaxwait.top = new FormAttachment(lastControl, margin);
+ wlMaxwait.setLayoutData(fdlMaxwait);
+ wMaxwait = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wMaxwait);
+ wMaxwait.addModifyListener(lsMod);
+ FormData fdMaxwait = new FormData();
+ fdMaxwait.left = new FormAttachment(middle, 0);
+ fdMaxwait.top = new FormAttachment(lastControl, margin);
+ fdMaxwait.right = new FormAttachment(100, 0);
+ wMaxwait.setLayoutData(fdMaxwait);
+ lastControl = wMaxwait;
+
+ wlInterval = new Label(shell, SWT.RIGHT);
+ wlInterval.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Interval.Label"));
+ props.setLook(wlInterval);
+ FormData fdlInterval = new FormData();
+ fdlInterval.left = new FormAttachment(0, 0);
+ fdlInterval.right = new FormAttachment(middle, -margin);
+ fdlInterval.top = new FormAttachment(lastControl, margin);
+ wlInterval.setLayoutData(fdlInterval);
+ wInterval = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wInterval);
+ wInterval.addModifyListener(lsMod);
+ FormData fdInterval = new FormData();
+ fdInterval.left = new FormAttachment(middle, 0);
+ fdInterval.top = new FormAttachment(lastControl, margin);
+ fdInterval.right = new FormAttachment(100, 0);
+ wInterval.setLayoutData(fdInterval);
+ lastControl = wInterval;
+
+ /*
+ wlRowTimeField = new Label(shell, SWT.RIGHT);
+ wlRowTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.RowTimeField.Label"));
+ props.setLook(wlRowTimeField);
+ FormData fdlRowTimeField = new FormData();
+ fdlRowTimeField.left = new FormAttachment(0, 0);
+ fdlRowTimeField.right = new FormAttachment(middle, -margin);
+ fdlRowTimeField.top = new FormAttachment(lastControl, margin);
+ wlRowTimeField.setLayoutData(fdlRowTimeField);
+ wRowTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wRowTimeField);
+ wRowTimeField.addModifyListener(lsMod);
+ FormData fdRowTimeField = new FormData();
+ fdRowTimeField.left = new FormAttachment(middle, 0);
+ fdRowTimeField.top = new FormAttachment(lastControl, margin);
+ fdRowTimeField.right = new FormAttachment(100, 0);
+ wRowTimeField.setLayoutData(fdRowTimeField);
+ lastControl = wRowTimeField;
+
+ wlLastTimeField = new Label(shell, SWT.RIGHT);
+ wlLastTimeField.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.LastTimeField.Label"));
+ props.setLook(wlLastTimeField);
+ FormData fdlLastTimeField = new FormData();
+ fdlLastTimeField.left = new FormAttachment(0, 0);
+ fdlLastTimeField.right = new FormAttachment(middle, -margin);
+ fdlLastTimeField.top = new FormAttachment(lastControl, margin);
+ wlLastTimeField.setLayoutData(fdlLastTimeField);
+ wLastTimeField = new TextVar(variables, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wLastTimeField);
+ wLastTimeField.addModifyListener(lsMod);
+ FormData fdLastTimeField = new FormData();
+ fdLastTimeField.left = new FormAttachment(middle, 0);
+ fdLastTimeField.top = new FormAttachment(lastControl, margin);
+ fdLastTimeField.right = new FormAttachment(100, 0);
+ wLastTimeField.setLayoutData(fdLastTimeField);
+ lastControl = wLastTimeField;
+ */
+ wOk = new Button(shell, SWT.PUSH);
+ wOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wOk.addListener(SWT.Selection, e -> ok());
+ wPreview = new Button(shell, SWT.PUSH);
+ wPreview.setText(BaseMessages.getString(PKG, "System.Button.Preview"));
+ wPreview.addListener(SWT.Selection, e -> preview());
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+ wCancel.addListener(SWT.Selection, e -> cancel());
+
+ setButtonPositions(new Button[] {wOk, wPreview, wCancel}, margin, null);
+
+ Label wlFields = new Label(shell, SWT.NONE);
+ wlFields.setText(BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Label"));
+ props.setLook(wlFields);
+ FormData fdlFields = new FormData();
+ fdlFields.left = new FormAttachment(0, 0);
+ fdlFields.top = new FormAttachment(lastControl, margin);
+ wlFields.setLayoutData(fdlFields);
+ lastControl = wlFields;
+
+ final int nrFields = input.getFields().size();
+
+ ColumnInfo[] colinf =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Name"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "Plc4x.Read.Meta.Dialog.Fields.Item"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Type"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ ValueMetaFactory.getValueMetaNames()),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Format"),
+ ColumnInfo.COLUMN_TYPE_FORMAT,
+ 2),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Length"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Precision"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Currency"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Decimal"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Group"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.Value"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG, "System.Column.SetEmptyString"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ new String[] {
+ BaseMessages.getString(PKG, "System.Combo.Yes"),
+ BaseMessages.getString(PKG, "System.Combo.No")
+ })
+ };
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
+ colinf,
+ nrFields,
+ lsMod,
+ props);
+
+ FormData fdFields = new FormData();
+ fdFields.left = new FormAttachment(0, 0);
+ fdFields.top = new FormAttachment(lastControl, margin);
+ fdFields.right = new FormAttachment(100, 0);
+ fdFields.bottom = new FormAttachment(wOk, -2 * margin);
+ wFields.setLayoutData(fdFields);
+
+ lsResize =
+ event -> {
+ Point size = shell.getSize();
+ wFields.setSize(size.x - 10, size.y - 50);
+ wFields.table.setSize(size.x - 10, size.y - 50);
+ wFields.redraw();
+ };
+ shell.addListener(SWT.Resize, lsResize);
+
+ getData();
+ input.setChanged(changed);
+
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return transformName;
+ };
+
+ @Override
+ public void setActive() {
+ boolean neverEnding = wNeverEnding.getSelection();
+
+ wlLimit.setEnabled(!neverEnding);
+ wLimit.setEnabled(!neverEnding);
+
+ //wlInterval.setEnabled(neverEnding);
+ //wInterval.setEnabled(neverEnding);
+
+ //wlRowTimeField.setEnabled(neverEnding);
+ //wRowTimeField.setEnabled(neverEnding);
+
+ //wlLastTimeField.setEnabled(neverEnding);
+ //wLastTimeField.setEnabled(neverEnding);
+ }
+
+
+
+ private Image getImage() {
+ return SwtSvgImageUtil.getImage( shell.getDisplay(), getClass().getClassLoader(), "plc4x_toddy_read.svg", ConstUi.LARGE_ICON_SIZE,
+ ConstUi.LARGE_ICON_SIZE );
+ }
+
+ /**
+ * Copy information from the meta-data input to the dialog fields.
+ *
+ */
+ public void getData() {
+ if (isDebug()) {
+ logDebug("getting fields info...");
+ }
+ if (input.getConnection() == null) {
+ wConnection.setText("");
+ } else {
+ wConnection.setText(input.getConnection());
+ }
+
+ wLimit.setText(input.getRowLimit());
+ wNeverEnding.setSelection(input.isNeverEnding());
+ wMaxwait.setText(Const.NVL(input.getMaxwaitInMs(), ""));
+ wInterval.setText(Const.NVL(input.getIntervalInMs(), ""));
+ // wRowTimeField.setText(Const.NVL(input.getRowTimeField(), ""));
+ //wLastTimeField.setText(Const.NVL(input.getLastTimeField(), ""));
+
+ for (int i = 0; i < input.getFields().size(); i++) {
+ Plc4xGeneratorField field = input.getFields().get(i);
+ TableItem item = wFields.table.getItem(i);
... 9496 lines suppressed ...