From e75064f94917aacb76fe6060ab104cac64e9bf74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 10 Jul 2023 20:33:18 +0200 Subject: [PATCH 01/55] Fixing the code --- Example-Test-Plan.jmx | 18 ++++---- .../config/asyncapi/AsyncApiConfigGui.java | 45 +++++++++++++++++++ .../config/asyncapi/AsyncApiTestElement.java | 17 +++++++ 3 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java diff --git a/Example-Test-Plan.jmx b/Example-Test-Plan.jmx index e157244a..a014aa80 100644 --- a/Example-Test-Plan.jmx +++ b/Example-Test-Plan.jmx @@ -16,10 +16,10 @@ continue false - 1 + 1000 - 1 - 1 + 1000 + 10 false @@ -376,7 +376,7 @@ false - customer_account.billing_party.party_contact[].contact_id + customer_account.billing_party.party_contact[4].contact_id 0 int @@ -387,7 +387,7 @@ customer_account.billing_party.party_contact[].contact_name 0 string - + Juan, Pedro, tomas, brais, jose, Adrian true false @@ -408,7 +408,7 @@ false - details.in_details.customs_details.party.party_contact[].contact_id + details.in_details.customs_details.party.party_contact[6].contact_id 0 int @@ -424,10 +424,10 @@ false - details.in_details.customs_details.party.p_contact[].contact_id + details.in_details.customs_details.party.p_contact[2].contact_id 0 - int - + seq + 2000 true false diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java new file mode 100644 index 00000000..4858473d --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -0,0 +1,45 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.sngular.kloadgen.config.asyncapi; + +import org.apache.jmeter.config.gui.AbstractConfigGui; +import org.apache.jmeter.testelement.TestElement; + +import javax.swing.*; +import java.awt.*; + +public class AsyncApiConfigGui extends AbstractConfigGui { + + @Override + public String getLabelResource() { + return null; + } + + @Override + public TestElement createTestElement() { + var testElement = new AsyncApiTestElement(); + modifyTestElement(testElement); + return testElement; + } + + @Override + public void modifyTestElement(TestElement element) { + + } + + private void init() { + setLayout(new BorderLayout()); + setBorder(makeBorder()); + JPanel mainPanel = new JPanel(new GridBagLayout()); + } +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java new file mode 100644 index 00000000..920bd6f5 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java @@ -0,0 +1,17 @@ +package com.sngular.kloadgen.config.asyncapi; + +import org.apache.jmeter.config.Arguments; + +public class AsyncApiTestElement extends Arguments { + + public static final String FILENAME = "filename"; + public static final String BROKER = "broker"; + public static final String SCHEMA_REGISTRY = "schema_registry"; + public static final String CHANNEL = "channel"; + public static final String MESSAGE = "message"; + public static final String KAFKA_KEY = "kafka.key"; + public static final String KAFKA_PAYLOAD = "kafka_payload"; + + + +} From f64d6ff903a2d3c7997c0df60e39075206d0cc1b Mon Sep 17 00:00:00 2001 From: Jose Enrique Garcia Date: Mon, 10 Jul 2023 23:18:34 +0200 Subject: [PATCH 02/55] Add Async Api GUI --- .../config/asyncapi/AsyncApiConfigGui.java | 169 +++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 4858473d..89dd4257 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -12,14 +12,42 @@ package com.sngular.kloadgen.config.asyncapi; +import com.sngular.kloadgen.extractor.SchemaExtractor; +import com.sngular.kloadgen.property.editor.FileSubjectPropertyEditor; import org.apache.jmeter.config.gui.AbstractConfigGui; import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.util.JMeterUtils; +import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.JTableHeader; import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.util.Objects; public class AsyncApiConfigGui extends AbstractConfigGui { + private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + + private JPanel mainPanel; + private JTabbedPane asyncApiTabs; + private JTable brokerInfo; + private JTextField textField1; + private JTable schemaRegistry; + private JTable schemaFields; + private JTextField asyncApiFileTextField; + private JButton fileButton; + private JTableHeader jTableHeaderKafka; + private JTableHeader jTableHeaderRegistry; + private JTableHeader jTableHeaderSchema; + + private final SchemaExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); + + @Override public String getLabelResource() { return null; @@ -40,6 +68,145 @@ public void modifyTestElement(TestElement element) { private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); - JPanel mainPanel = new JPanel(new GridBagLayout()); + mainPanel = new JPanel(); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.setPreferredSize(new Dimension(-1, -1)); + mainPanel.putClientProperty("html.disable", Boolean.FALSE); + mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel fileChoosingPanel = new JPanel(); + fileChoosingPanel.setLayout(new GridBagLayout()); + fileChoosingPanel.setName("AsyncApi File"); + var gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.weighty = 0.03; + gridBagConstraints.fill = GridBagConstraints.BOTH; + mainPanel.add(fileChoosingPanel, gridBagConstraints); + asyncApiFileTextField = new JTextField(); + asyncApiFileTextField.setPreferredSize(new Dimension(249, 30)); + asyncApiFileTextField.setText(""); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); + fileButton = new JButton(); + fileButton.setText("Open File"); + fileButton.addActionListener(this::actionFileChooser); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(fileButton, gridBagConstraints); + final JLabel label1 = new JLabel(); + label1.setText("AsyncApi File"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + fileChoosingPanel.add(label1, gridBagConstraints); + asyncApiTabs = new JTabbedPane(); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.weightx = 0.5; + gridBagConstraints.weighty = 0.1; + gridBagConstraints.fill = GridBagConstraints.BOTH; + mainPanel.add(asyncApiTabs, gridBagConstraints); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new BorderLayout(0, 0)); + asyncApiTabs.addTab("Broker", panel3); + brokerInfo = new JTable(); + brokerInfo.setIntercellSpacing(new Dimension(2, 1)); + brokerInfo.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE); + brokerInfo.putClientProperty("Table.isFileList", Boolean.TRUE); + jTableHeaderKafka = new JTableHeader(); + jTableHeaderKafka.add(getComponentProperty("Property")); + jTableHeaderKafka.add(getComponentProperty("Value")); + brokerInfo.setTableHeader(jTableHeaderKafka); + panel3.add(brokerInfo, BorderLayout.CENTER); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridBagLayout()); + panel4.setMinimumSize(new Dimension(45, 45)); + panel4.setPreferredSize(new Dimension(200, 45)); + asyncApiTabs.addTab("Registry", panel4); + final JLabel label2 = new JLabel(); + label2.setText("Schema Registry URL"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + panel4.add(label2, gridBagConstraints); + textField1 = new JTextField(); + textField1.setPreferredSize(new Dimension(249, 30)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + panel4.add(textField1, gridBagConstraints); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = GridBagConstraints.BOTH; + panel4.add(panel5, gridBagConstraints); + final JLabel label3 = new JLabel(); + label3.setText("Security Options"); + panel5.add(label3); + schemaRegistry = new JTable(); + jTableHeaderRegistry = new JTableHeader(); + jTableHeaderRegistry.add(getComponentProperty("Property")); + jTableHeaderRegistry.add(getComponentProperty("Value")); + schemaRegistry.setTableHeader(jTableHeaderRegistry); + panel5.add(schemaRegistry); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + asyncApiTabs.addTab("Schema", panel6); + schemaFields = new JTable(); + jTableHeaderSchema = new JTableHeader(); + jTableHeaderSchema.add(getComponentProperty("Field Name")); + jTableHeaderSchema.add(getComponentProperty("Field Type")); + jTableHeaderSchema.add(getComponentProperty("Field Size")); + jTableHeaderSchema.add(getComponentProperty("Field Value")); + schemaFields.setTableHeader(jTableHeaderSchema); + schemaFields.setSurrendersFocusOnKeystroke(false); + panel6.add(schemaFields); + fileChoosingPanel.setNextFocusableComponent(asyncApiTabs); + } + + @NotNull + private static Component getComponentProperty(String Property) { + return new Component() { + @Override + public String getName() { + return Property; + } + }; + } + + public final void actionFileChooser(final ActionEvent event) { + + final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + + if (JFileChooser.APPROVE_OPTION == returnValue) { + final File subjectName = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(subjectName.getAbsolutePath()); + try { + + brokerInfo. = asyncApiExtractor.schemaTypesList(subjectName, schemaType); + subjectNameComboBox.removeAllItems(); + subjectNameComboBox.addItem(parserSchema.name()); + subjectNameComboBox.setSelectedItem(parserSchema.name()); + } catch (final IOException e) { + JOptionPane.showMessageDialog(panel, "Can't read a file : " + e.getMessage(), ERROR_FAILED_TO_RETRIEVE_PROPERTIES, + JOptionPane.ERROR_MESSAGE); + log.error(e.getMessage(), e); + } + subjectNameComboBox.addFocusListener(new FileSubjectPropertyEditor.ComboFiller()); + } } } From 6bec07302099e63cf57c52aff63e6c5ce5d2f0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 10 Jul 2023 20:33:18 +0200 Subject: [PATCH 03/55] Fixing the code --- Example-Test-Plan.jmx | 18 ++++---- .../config/asyncapi/AsyncApiConfigGui.java | 45 +++++++++++++++++++ .../config/asyncapi/AsyncApiTestElement.java | 17 +++++++ 3 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java diff --git a/Example-Test-Plan.jmx b/Example-Test-Plan.jmx index e157244a..a014aa80 100644 --- a/Example-Test-Plan.jmx +++ b/Example-Test-Plan.jmx @@ -16,10 +16,10 @@ continue false - 1 + 1000 - 1 - 1 + 1000 + 10 false @@ -376,7 +376,7 @@ false - customer_account.billing_party.party_contact[].contact_id + customer_account.billing_party.party_contact[4].contact_id 0 int @@ -387,7 +387,7 @@ customer_account.billing_party.party_contact[].contact_name 0 string - + Juan, Pedro, tomas, brais, jose, Adrian true false @@ -408,7 +408,7 @@ false - details.in_details.customs_details.party.party_contact[].contact_id + details.in_details.customs_details.party.party_contact[6].contact_id 0 int @@ -424,10 +424,10 @@ false - details.in_details.customs_details.party.p_contact[].contact_id + details.in_details.customs_details.party.p_contact[2].contact_id 0 - int - + seq + 2000 true false diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java new file mode 100644 index 00000000..4858473d --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -0,0 +1,45 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.sngular.kloadgen.config.asyncapi; + +import org.apache.jmeter.config.gui.AbstractConfigGui; +import org.apache.jmeter.testelement.TestElement; + +import javax.swing.*; +import java.awt.*; + +public class AsyncApiConfigGui extends AbstractConfigGui { + + @Override + public String getLabelResource() { + return null; + } + + @Override + public TestElement createTestElement() { + var testElement = new AsyncApiTestElement(); + modifyTestElement(testElement); + return testElement; + } + + @Override + public void modifyTestElement(TestElement element) { + + } + + private void init() { + setLayout(new BorderLayout()); + setBorder(makeBorder()); + JPanel mainPanel = new JPanel(new GridBagLayout()); + } +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java new file mode 100644 index 00000000..920bd6f5 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java @@ -0,0 +1,17 @@ +package com.sngular.kloadgen.config.asyncapi; + +import org.apache.jmeter.config.Arguments; + +public class AsyncApiTestElement extends Arguments { + + public static final String FILENAME = "filename"; + public static final String BROKER = "broker"; + public static final String SCHEMA_REGISTRY = "schema_registry"; + public static final String CHANNEL = "channel"; + public static final String MESSAGE = "message"; + public static final String KAFKA_KEY = "kafka.key"; + public static final String KAFKA_PAYLOAD = "kafka_payload"; + + + +} From 44eea5f423a39e7dc14043ff276aa2f708b1dcb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Tue, 11 Jul 2023 08:39:01 +0200 Subject: [PATCH 04/55] Fixing the code --- .../config/asyncapi/AsyncApiTestElement.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java index 920bd6f5..b2c7c258 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java @@ -4,14 +4,14 @@ public class AsyncApiTestElement extends Arguments { - public static final String FILENAME = "filename"; - public static final String BROKER = "broker"; - public static final String SCHEMA_REGISTRY = "schema_registry"; - public static final String CHANNEL = "channel"; - public static final String MESSAGE = "message"; - public static final String KAFKA_KEY = "kafka.key"; - public static final String KAFKA_PAYLOAD = "kafka_payload"; + public static final String FILENAME = "filename"; + public static final String BROKER = "broker"; + public static final String SCHEMA_REGISTRY = "schema_registry"; + public static final String CHANNEL = "channel"; + public static final String MESSAGE = "message"; + public static final String KAFKA_KEY = "kafka.key"; + public static final String KAFKA_PAYLOAD = "kafka_payload"; + - } From ce2315b7ffd882b52a546b44da67443be1a18257 Mon Sep 17 00:00:00 2001 From: Jose Enrique Garcia Date: Mon, 10 Jul 2023 23:18:34 +0200 Subject: [PATCH 05/55] Add Async Api GUI --- .../config/asyncapi/AsyncApiConfigGui.java | 169 +++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 4858473d..89dd4257 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -12,14 +12,42 @@ package com.sngular.kloadgen.config.asyncapi; +import com.sngular.kloadgen.extractor.SchemaExtractor; +import com.sngular.kloadgen.property.editor.FileSubjectPropertyEditor; import org.apache.jmeter.config.gui.AbstractConfigGui; import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.util.JMeterUtils; +import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.JTableHeader; import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.util.Objects; public class AsyncApiConfigGui extends AbstractConfigGui { + private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + + private JPanel mainPanel; + private JTabbedPane asyncApiTabs; + private JTable brokerInfo; + private JTextField textField1; + private JTable schemaRegistry; + private JTable schemaFields; + private JTextField asyncApiFileTextField; + private JButton fileButton; + private JTableHeader jTableHeaderKafka; + private JTableHeader jTableHeaderRegistry; + private JTableHeader jTableHeaderSchema; + + private final SchemaExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); + + @Override public String getLabelResource() { return null; @@ -40,6 +68,145 @@ public void modifyTestElement(TestElement element) { private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); - JPanel mainPanel = new JPanel(new GridBagLayout()); + mainPanel = new JPanel(); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.setPreferredSize(new Dimension(-1, -1)); + mainPanel.putClientProperty("html.disable", Boolean.FALSE); + mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel fileChoosingPanel = new JPanel(); + fileChoosingPanel.setLayout(new GridBagLayout()); + fileChoosingPanel.setName("AsyncApi File"); + var gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.weighty = 0.03; + gridBagConstraints.fill = GridBagConstraints.BOTH; + mainPanel.add(fileChoosingPanel, gridBagConstraints); + asyncApiFileTextField = new JTextField(); + asyncApiFileTextField.setPreferredSize(new Dimension(249, 30)); + asyncApiFileTextField.setText(""); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); + fileButton = new JButton(); + fileButton.setText("Open File"); + fileButton.addActionListener(this::actionFileChooser); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(fileButton, gridBagConstraints); + final JLabel label1 = new JLabel(); + label1.setText("AsyncApi File"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + fileChoosingPanel.add(label1, gridBagConstraints); + asyncApiTabs = new JTabbedPane(); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.weightx = 0.5; + gridBagConstraints.weighty = 0.1; + gridBagConstraints.fill = GridBagConstraints.BOTH; + mainPanel.add(asyncApiTabs, gridBagConstraints); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new BorderLayout(0, 0)); + asyncApiTabs.addTab("Broker", panel3); + brokerInfo = new JTable(); + brokerInfo.setIntercellSpacing(new Dimension(2, 1)); + brokerInfo.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE); + brokerInfo.putClientProperty("Table.isFileList", Boolean.TRUE); + jTableHeaderKafka = new JTableHeader(); + jTableHeaderKafka.add(getComponentProperty("Property")); + jTableHeaderKafka.add(getComponentProperty("Value")); + brokerInfo.setTableHeader(jTableHeaderKafka); + panel3.add(brokerInfo, BorderLayout.CENTER); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridBagLayout()); + panel4.setMinimumSize(new Dimension(45, 45)); + panel4.setPreferredSize(new Dimension(200, 45)); + asyncApiTabs.addTab("Registry", panel4); + final JLabel label2 = new JLabel(); + label2.setText("Schema Registry URL"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + panel4.add(label2, gridBagConstraints); + textField1 = new JTextField(); + textField1.setPreferredSize(new Dimension(249, 30)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + panel4.add(textField1, gridBagConstraints); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = GridBagConstraints.BOTH; + panel4.add(panel5, gridBagConstraints); + final JLabel label3 = new JLabel(); + label3.setText("Security Options"); + panel5.add(label3); + schemaRegistry = new JTable(); + jTableHeaderRegistry = new JTableHeader(); + jTableHeaderRegistry.add(getComponentProperty("Property")); + jTableHeaderRegistry.add(getComponentProperty("Value")); + schemaRegistry.setTableHeader(jTableHeaderRegistry); + panel5.add(schemaRegistry); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + asyncApiTabs.addTab("Schema", panel6); + schemaFields = new JTable(); + jTableHeaderSchema = new JTableHeader(); + jTableHeaderSchema.add(getComponentProperty("Field Name")); + jTableHeaderSchema.add(getComponentProperty("Field Type")); + jTableHeaderSchema.add(getComponentProperty("Field Size")); + jTableHeaderSchema.add(getComponentProperty("Field Value")); + schemaFields.setTableHeader(jTableHeaderSchema); + schemaFields.setSurrendersFocusOnKeystroke(false); + panel6.add(schemaFields); + fileChoosingPanel.setNextFocusableComponent(asyncApiTabs); + } + + @NotNull + private static Component getComponentProperty(String Property) { + return new Component() { + @Override + public String getName() { + return Property; + } + }; + } + + public final void actionFileChooser(final ActionEvent event) { + + final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + + if (JFileChooser.APPROVE_OPTION == returnValue) { + final File subjectName = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(subjectName.getAbsolutePath()); + try { + + brokerInfo. = asyncApiExtractor.schemaTypesList(subjectName, schemaType); + subjectNameComboBox.removeAllItems(); + subjectNameComboBox.addItem(parserSchema.name()); + subjectNameComboBox.setSelectedItem(parserSchema.name()); + } catch (final IOException e) { + JOptionPane.showMessageDialog(panel, "Can't read a file : " + e.getMessage(), ERROR_FAILED_TO_RETRIEVE_PROPERTIES, + JOptionPane.ERROR_MESSAGE); + log.error(e.getMessage(), e); + } + subjectNameComboBox.addFocusListener(new FileSubjectPropertyEditor.ComboFiller()); + } } } From 8b8e6733f5672404fdf6f0d3d372416bc95d3c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 19 Jul 2023 11:14:25 +0200 Subject: [PATCH 06/55] AsyncApi integration Skeleton --- .../config/asyncapi/AsyncApiConfigGui.java | 412 ++++++++++-------- .../kloadgen/extractor/ApiExtractor.java | 20 + .../asyncapi/AsyncApiExtractorImpl.java | 13 + .../extractor/model/AsyncApiFile.java | 17 + .../kloadgen/extractor/model/AsyncApiSR.java | 13 + .../extractor/model/AsyncApiSchema.java | 22 + .../extractor/model/AsyncApiServer.java | 17 + 7 files changed, 334 insertions(+), 180 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 89dd4257..83384344 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -12,201 +12,253 @@ package com.sngular.kloadgen.config.asyncapi; -import com.sngular.kloadgen.extractor.SchemaExtractor; -import com.sngular.kloadgen.property.editor.FileSubjectPropertyEditor; -import org.apache.jmeter.config.gui.AbstractConfigGui; -import org.apache.jmeter.testelement.TestElement; -import org.apache.jmeter.util.JMeterUtils; -import org.jetbrains.annotations.NotNull; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import java.util.Objects; -import javax.swing.*; +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; import javax.swing.table.JTableHeader; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.io.IOException; -import java.util.Objects; +import org.apache.jmeter.samplers.gui.AbstractSamplerGui; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.util.JMeterUtils; +import org.apache.jorphan.gui.JLabeledTextField; +import org.jetbrains.annotations.NotNull; -public class AsyncApiConfigGui extends AbstractConfigGui { +public class AsyncApiConfigGui extends AbstractSamplerGui { - private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + public static final String ERROR_FAILED_TO_RETRIEVE_PROPERTIES = "ERROR: Failed to retrieve properties!"; - private JPanel mainPanel; - private JTabbedPane asyncApiTabs; - private JTable brokerInfo; - private JTextField textField1; - private JTable schemaRegistry; - private JTable schemaFields; - private JTextField asyncApiFileTextField; - private JButton fileButton; - private JTableHeader jTableHeaderKafka; - private JTableHeader jTableHeaderRegistry; - private JTableHeader jTableHeaderSchema; + private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); - private final SchemaExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); + private final ApiExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); + private JPanel mainPanel; - @Override - public String getLabelResource() { - return null; - } + private JTable brokerInfo; - @Override - public TestElement createTestElement() { - var testElement = new AsyncApiTestElement(); - modifyTestElement(testElement); - return testElement; - } + private JTextField asyncApiFileTextField; - @Override - public void modifyTestElement(TestElement element) { + private JTextField registryUrl; - } + private JTable schemaRegistry; - private void init() { - setLayout(new BorderLayout()); - setBorder(makeBorder()); - mainPanel = new JPanel(); - mainPanel.setLayout(new GridBagLayout()); - mainPanel.setPreferredSize(new Dimension(-1, -1)); - mainPanel.putClientProperty("html.disable", Boolean.FALSE); - mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); - final JPanel fileChoosingPanel = new JPanel(); - fileChoosingPanel.setLayout(new GridBagLayout()); - fileChoosingPanel.setName("AsyncApi File"); - var gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.weighty = 0.03; - gridBagConstraints.fill = GridBagConstraints.BOTH; - mainPanel.add(fileChoosingPanel, gridBagConstraints); - asyncApiFileTextField = new JTextField(); - asyncApiFileTextField.setPreferredSize(new Dimension(249, 30)); - asyncApiFileTextField.setText(""); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); - fileButton = new JButton(); - fileButton.setText("Open File"); - fileButton.addActionListener(this::actionFileChooser); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - fileChoosingPanel.add(fileButton, gridBagConstraints); - final JLabel label1 = new JLabel(); - label1.setText("AsyncApi File"); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - fileChoosingPanel.add(label1, gridBagConstraints); - asyncApiTabs = new JTabbedPane(); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.weightx = 0.5; - gridBagConstraints.weighty = 0.1; - gridBagConstraints.fill = GridBagConstraints.BOTH; - mainPanel.add(asyncApiTabs, gridBagConstraints); - final JPanel panel3 = new JPanel(); - panel3.setLayout(new BorderLayout(0, 0)); - asyncApiTabs.addTab("Broker", panel3); - brokerInfo = new JTable(); - brokerInfo.setIntercellSpacing(new Dimension(2, 1)); - brokerInfo.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE); - brokerInfo.putClientProperty("Table.isFileList", Boolean.TRUE); - jTableHeaderKafka = new JTableHeader(); - jTableHeaderKafka.add(getComponentProperty("Property")); - jTableHeaderKafka.add(getComponentProperty("Value")); - brokerInfo.setTableHeader(jTableHeaderKafka); - panel3.add(brokerInfo, BorderLayout.CENTER); - final JPanel panel4 = new JPanel(); - panel4.setLayout(new GridBagLayout()); - panel4.setMinimumSize(new Dimension(45, 45)); - panel4.setPreferredSize(new Dimension(200, 45)); - asyncApiTabs.addTab("Registry", panel4); - final JLabel label2 = new JLabel(); - label2.setText("Schema Registry URL"); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - panel4.add(label2, gridBagConstraints); - textField1 = new JTextField(); - textField1.setPreferredSize(new Dimension(249, 30)); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - panel4.add(textField1, gridBagConstraints); - final JPanel panel5 = new JPanel(); - panel5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = GridBagConstraints.BOTH; - panel4.add(panel5, gridBagConstraints); - final JLabel label3 = new JLabel(); - label3.setText("Security Options"); - panel5.add(label3); - schemaRegistry = new JTable(); - jTableHeaderRegistry = new JTableHeader(); - jTableHeaderRegistry.add(getComponentProperty("Property")); - jTableHeaderRegistry.add(getComponentProperty("Value")); - schemaRegistry.setTableHeader(jTableHeaderRegistry); - panel5.add(schemaRegistry); - final JPanel panel6 = new JPanel(); - panel6.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); - asyncApiTabs.addTab("Schema", panel6); - schemaFields = new JTable(); - jTableHeaderSchema = new JTableHeader(); - jTableHeaderSchema.add(getComponentProperty("Field Name")); - jTableHeaderSchema.add(getComponentProperty("Field Type")); - jTableHeaderSchema.add(getComponentProperty("Field Size")); - jTableHeaderSchema.add(getComponentProperty("Field Value")); - schemaFields.setTableHeader(jTableHeaderSchema); - schemaFields.setSurrendersFocusOnKeystroke(false); - panel6.add(schemaFields); - fileChoosingPanel.setNextFocusableComponent(asyncApiTabs); - } + private JTable schemaFields; - @NotNull - private static Component getComponentProperty(String Property) { - return new Component() { - @Override - public String getName() { - return Property; - } - }; - } + private JButton fileButton; + + private JTableHeader jTableHeaderKafka; + + private JTableHeader jTableHeaderRegistry; + + private JTableHeader jTableHeaderSchema; - public final void actionFileChooser(final ActionEvent event) { - - final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); - - if (JFileChooser.APPROVE_OPTION == returnValue) { - final File subjectName = Objects.requireNonNull(fileChooser.getSelectedFile()); - asyncApiFileTextField.setText(subjectName.getAbsolutePath()); - try { - - brokerInfo. = asyncApiExtractor.schemaTypesList(subjectName, schemaType); - subjectNameComboBox.removeAllItems(); - subjectNameComboBox.addItem(parserSchema.name()); - subjectNameComboBox.setSelectedItem(parserSchema.name()); - } catch (final IOException e) { - JOptionPane.showMessageDialog(panel, "Can't read a file : " + e.getMessage(), ERROR_FAILED_TO_RETRIEVE_PROPERTIES, - JOptionPane.ERROR_MESSAGE); - log.error(e.getMessage(), e); - } - subjectNameComboBox.addFocusListener(new FileSubjectPropertyEditor.ComboFiller()); - } + protected AsyncApiConfigGui() { + init(); + } + + private void init() { + setLayout(new BorderLayout()); + setBorder(makeBorder()); + mainPanel = new JPanel(); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.setPreferredSize(new Dimension(-1, -1)); + mainPanel.putClientProperty("html.disable", Boolean.FALSE); + mainPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + + mainPanel.add("asyncapi.file.selector", createAsyncApiFileSelectPanel()); + mainPanel.add("asyncapi.config.options", createAsyncApiTabs()); + } + + @NotNull + private JPanel createAsyncApiFileSelectPanel() { + final JPanel fileChoosingPanel = new JPanel(); + fileChoosingPanel.setLayout(new GridBagLayout()); + fileChoosingPanel.setName("AsyncApi File"); + var gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.weighty = 0.03; + gridBagConstraints.fill = GridBagConstraints.BOTH; + asyncApiFileTextField = new JTextField(); + asyncApiFileTextField.setPreferredSize(new Dimension(249, 30)); + asyncApiFileTextField.setText(""); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); + fileButton = new JButton(); + fileButton.setText("Open File"); + fileButton.addActionListener(this::actionFileChooser); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + fileChoosingPanel.add(fileButton, gridBagConstraints); + final JLabel label1 = new JLabel(); + label1.setText("AsyncApi File"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + fileChoosingPanel.add(label1, gridBagConstraints); + return fileChoosingPanel; + } + + @NotNull + private JTabbedPane createAsyncApiTabs() { + var tabbedPanel = new JTabbedPane(); + tabbedPanel.addTab("Broker", createBrokerPanel()); + tabbedPanel.addTab("Registry", createRegistryTab()); + tabbedPanel.addTab("Schema", createSchemaTab()); + return tabbedPanel; + } + + public final void actionFileChooser(final ActionEvent event) { + + final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + + if (JFileChooser.APPROVE_OPTION == returnValue) { + final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(apiFile.getAbsolutePath()); + var asyncApiFile = asyncApiExtractor.processFile(apiFile); + + fillTable(brokerInfo, asyncApiExtractor.getBrokerData(asyncApiFile)); + fillTable(schemaRegistry, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); + fillTable(schemaFields, asyncApiExtractor.getSchemaData(asyncApiFile)); } + } + + private void fillTable(final JTable schemaFields, final List schemaData) { + + } + + @NotNull + private JPanel createBrokerPanel() { + final JPanel brokerPanel = new JPanel(); + brokerPanel.setLayout(new BorderLayout(0, 0)); + var label = new JLabeledTextField("") + brokerInfo = new JTable(); + brokerInfo.setIntercellSpacing(new Dimension(2, 1)); + brokerInfo.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE); + brokerInfo.putClientProperty("Table.isFileList", Boolean.TRUE); + jTableHeaderKafka = new JTableHeader(); + jTableHeaderKafka.add(getComponentProperty("Property")); + jTableHeaderKafka.add(getComponentProperty("Value")); + brokerInfo.setTableHeader(jTableHeaderKafka); + brokerPanel.add(brokerInfo, BorderLayout.CENTER); + return brokerPanel; + } + + @NotNull + private JPanel createRegistryTab() { + GridBagConstraints gridBagConstraints; + final JPanel registryUrlPanel = new JPanel(); + registryUrlPanel.setLayout(new GridBagLayout()); + registryUrlPanel.setMinimumSize(new Dimension(45, 45)); + registryUrlPanel.setPreferredSize(new Dimension(200, 45)); + final JLabel label2 = new JLabel(); + label2.setText("Schema Registry URL"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + registryUrlPanel.add(label2, gridBagConstraints); + this.registryUrl = new JTextField(); + this.registryUrl.setPreferredSize(new Dimension(249, 30)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + registryUrlPanel.add(this.registryUrl, gridBagConstraints); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = GridBagConstraints.BOTH; + registryUrlPanel.add(panel5, gridBagConstraints); + final JLabel label3 = new JLabel(); + label3.setText("Security Options"); + panel5.add(label3); + schemaRegistry = new JTable(); + jTableHeaderRegistry = new JTableHeader(); + jTableHeaderRegistry.add(getComponentProperty("Property")); + jTableHeaderRegistry.add(getComponentProperty("Value")); + schemaRegistry.setTableHeader(jTableHeaderRegistry); + panel5.add(schemaRegistry); + return registryUrlPanel; + } + + @NotNull + private JPanel createSchemaTab() { + final JPanel schemaTab = new JPanel(); + schemaTab.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + schemaFields = new JTable(); + jTableHeaderSchema = new JTableHeader(); + jTableHeaderSchema.add(getComponentProperty("Field Name")); + jTableHeaderSchema.add(getComponentProperty("Field Type")); + jTableHeaderSchema.add(getComponentProperty("Field Size")); + jTableHeaderSchema.add(getComponentProperty("Field Value")); + schemaFields.setTableHeader(jTableHeaderSchema); + schemaFields.setSurrendersFocusOnKeystroke(false); + schemaTab.add(schemaFields); + return schemaTab; + } + + @NotNull + private static Component getComponentProperty(final String Property) { + return new Component() { + @Override + public String getName() { + return Property; + } + }; + } + + @Override + public void clearGui() { + super.clearGui(); + asyncApiFileTextField.setText(""); + registryUrl.setText(""); + } + + @Override + public String getLabelResource() { + return null; + } + + @Override + public TestElement createTestElement() { + var testElement = new AsyncApiTestElement(); + modifyTestElement(testElement); + return testElement; + } + + @Override + public void modifyTestElement(TestElement element) { + + } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java new file mode 100644 index 00000000..2d4ace68 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -0,0 +1,20 @@ +package com.sngular.kloadgen.extractor; + +import java.io.File; +import java.util.List; + +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.extractor.model.AsyncApiSR; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; + +public interface ApiExtractor { + + AsyncApiFile processFile(File apiFile); + + List getBrokerData(AsyncApiFile asyncApiFile); + + List getSchemaRegistryData(AsyncApiFile asyncApiFile); + + List getSchemaData(AsyncApiFile asyncApiFile); +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java new file mode 100644 index 00000000..c53ba9e8 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -0,0 +1,13 @@ +package com.sngular.kloadgen.extractor.asyncapi; + +import java.io.File; + +import com.sngular.kloadgen.extractor.ApiExtractor; + +public class AsyncApiExtractorImpl implements ApiExtractor { + + @Override + public void processFile(final File apiFile) { + + } +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java new file mode 100644 index 00000000..7f73e420 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -0,0 +1,17 @@ +package com.sngular.kloadgen.extractor.model; + +import java.util.List; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class AsyncApiFile { + + List apiServerList; + + List apiAsyncApiSRList; + + List apiSchemaList; +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java new file mode 100644 index 00000000..f345e786 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java @@ -0,0 +1,13 @@ +package com.sngular.kloadgen.extractor.model; + +import lombok.Data; +import lombok.Value; + +@Value +@Data +public class AsyncApiSR { + + String schemaRegistryUrl; + + String schemaRegistryVendor; +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java new file mode 100644 index 00000000..2f261028 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java @@ -0,0 +1,22 @@ +package com.sngular.kloadgen.extractor.model; + +import java.util.List; + +import com.sngular.kloadgen.model.FieldValueMapping; +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class AsyncApiSchema { + + String topicName; + + boolean key; + + String keyType; + + String schemaLookupStrategy; + + List model; +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java new file mode 100644 index 00000000..fb2c1aad --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java @@ -0,0 +1,17 @@ +package com.sngular.kloadgen.extractor.model; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class AsyncApiServer { + + String name; + + String url; + + String protocol; + + String description; +} From af0f2f43a9413ea9c006af09a52df016622b5eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 26 Jul 2023 08:39:45 +0200 Subject: [PATCH 07/55] AsyncApi integration Skeleton --- .../kloadgen/common/tools/ApiTool.java | 296 ++++++++++++++++++ .../kloadgen/common/tools/TypeConstants.java | 87 +++++ .../config/asyncapi/AsyncApiConfigGui.java | 87 ++--- .../kloadgen/extractor/ApiExtractor.java | 2 +- .../asyncapi/AsyncApiExtractorImpl.java | 78 ++++- .../extractor/model/AsyncApiAbstract.java | 7 + .../kloadgen/extractor/model/AsyncApiSR.java | 7 +- .../extractor/model/AsyncApiServer.java | 7 +- .../kloadgen/model/FieldValueMapping.java | 7 +- 9 files changed, 520 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java create mode 100644 src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java create mode 100644 src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java new file mode 100644 index 00000000..3b5912bc --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -0,0 +1,296 @@ +package com.sngular.kloadgen.common.tools; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.IteratorUtils; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.lang3.StringUtils; + +public final class ApiTool { + + public static final String FORMAT = "format"; + public static final String ALL_OF = "allOf"; + public static final String ANY_OF = "anyOf"; + public static final String ONE_OF = "oneOf"; + public static final String COMPONENTS = "components"; + public static final String SCHEMAS = "schemas"; + public static final String REQUIRED = "required"; + + public static final String PARAMETERS = "parameters"; + + public static final String RESPONSES = "responses"; + + private ApiTool() { + } + + public static String getType(final JsonNode schema) { + return hasType(schema) ? getNodeAsString(schema, "type") : ""; + } + + public static Iterator> getProperties(final JsonNode schema) { + return getNode(schema, "properties").fields(); + } + + public static String getRefValue(final JsonNode schema) { + return getNode(schema, "$ref").textValue(); + } + + public static JsonNode getAdditionalProperties(final JsonNode schema) { + return getNode(schema, "additionalProperties"); + } + + public static String getFormat(final JsonNode schema) { + return getNodeAsString(schema, FORMAT); + } + + public static JsonNode getAllOf(final JsonNode schema) { + return getNode(schema, ALL_OF); + } + + public static JsonNode getAnyOf(final JsonNode schema) { + return getNode(schema, ANY_OF); + } + + public static JsonNode getOneOf(final JsonNode schema) { + return getNode(schema, ONE_OF); + } + + public static JsonNode getNode(final JsonNode schema, final String nodeName) { + return schema.get(nodeName); + } + + public static String getNodeAsString(final JsonNode schema, final String nodeName) { + return hasNode(schema, nodeName) ? getNode(schema, nodeName).textValue() : null; + } + + public static boolean getNodeAsBoolean(final JsonNode schema, final String nodeName) { + return hasNode(schema, nodeName) && getNode(schema, nodeName).booleanValue(); + } + + public static Iterator> getFieldIterator(final JsonNode schema) { + return Objects.nonNull(schema) ? schema.fields() : IteratorUtils.emptyIterator(); + } + + public static String getName(final JsonNode node) { + return hasNode(node, "name") ? getNodeAsString(node, "name") : node.textValue(); + } + + public static List getEnumValues(final JsonNode schema) { + return new ArrayList<>(CollectionUtils.collect( + IteratorUtils.toList(schema.get("enum").elements()), + getTextValue())); + } + + public static JsonNode getItems(final JsonNode schema) { + return getNode(schema, "items"); + } + + public static Map getComponentSchemas(final JsonNode openApi) { + final var schemasMap = new HashMap(); + + if (hasNode(openApi, COMPONENTS)) { + final var components = getNode(openApi, COMPONENTS); + if (hasNode(components, SCHEMAS)) { + final var schemas = getNode(components, SCHEMAS); + final var schemasIt = schemas.fieldNames(); + schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); + } + } + + return schemasMap; + } + + public static Map getParameterSchemas(final JsonNode openApi) { + final var schemasMap = new HashMap(); + + if (hasNode(openApi, COMPONENTS)) { + final var components = getNode(openApi, COMPONENTS); + if (hasNode(components, PARAMETERS)) { + final var schemas = getNode(components, PARAMETERS); + final var schemasIt = schemas.fieldNames(); + schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); + } + } + + return schemasMap; + } + + public static Map getResponseSchemas(final JsonNode openApi) { + final var schemasMap = new HashMap(); + + if (hasNode(openApi, COMPONENTS)) { + final var components = getNode(openApi, COMPONENTS); + if (hasNode(components, RESPONSES)) { + final var schemas = getNode(components, RESPONSES); + final var schemasIt = schemas.fieldNames(); + schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); + } + } + + return schemasMap; + } + + public static Map getComponentSecuritySchemes(final JsonNode openApi) { + final var schemasMap = new HashMap(); + + if (hasNode(openApi, COMPONENTS)) { + final var components = getNode(openApi, COMPONENTS); + if (hasNode(components, "securitySchemes")) { + getNode(components, "securitySchemes").fields().forEachRemaining(schema -> schemasMap.put(schema.getKey(), schema.getValue())); + } + } + + return schemasMap; + } + + public static String getNumberType(final JsonNode schema) { + final String type; + if (hasType(schema)) { + switch (getType(schema)) { + case TypeConstants.DOUBLE: type = TypeConstants.DOUBLE; + break; + case TypeConstants.FLOAT: type = TypeConstants.FLOAT; + break; + case TypeConstants.NUMBER: type = TypeConstants.NUMBER; + break; + case TypeConstants.INT_64: type = TypeConstants.INT_64; + break; + case TypeConstants.INT_32: type = TypeConstants.INT_32; + break; + default: type = TypeConstants.INTEGER; + break; + } + } else { + type = TypeConstants.INTEGER; + } + return type; + } + + public static boolean hasItems(final JsonNode schema) { + return hasNode(schema, "items"); + } + + public static boolean hasNode(final JsonNode schema, final String nodeName) { + return Objects.nonNull(schema) && schema.has(nodeName); + } + + public static boolean hasField(final JsonNode schema, final String... fieldNameArray) { + final var nodeNamesList = Arrays.asList(fieldNameArray); + return StringUtils.isNotEmpty(IteratorUtils.find(schema.fieldNames(), nodeNamesList::contains)); + } + + public static boolean hasRequired(final JsonNode schema) { + return hasNode(schema, REQUIRED); + } + + public static boolean hasType(final JsonNode schema) { + return hasNode(schema, "type"); + } + + public static boolean hasRef(final JsonNode schema) { + return hasNode(schema, "$ref"); + } + + public static boolean hasProperties(final JsonNode schema) { + return hasNode(schema, "properties"); + } + + public static boolean hasContent(final JsonNode schema) { + return hasNode(schema, "content"); + } + + public static boolean hasAdditionalProperties(final JsonNode schema) { + return hasNode(schema, "additionalProperties"); + } + + public static boolean isObject(final JsonNode schema) { + return hasType(schema) && TypeConstants.OBJECT.equalsIgnoreCase(getType(schema)); + } + + public static boolean isArray(final JsonNode schema) { + return hasType(schema) && TypeConstants.ARRAY.equalsIgnoreCase(getType(schema)); + } + + public static boolean isComposed(final JsonNode schema) { + return ApiTool.hasField(schema, ANY_OF, ALL_OF, ONE_OF); + } + + public static boolean isString(final JsonNode schema) { + return hasType(schema) && TypeConstants.STRING.equalsIgnoreCase(getType(schema)); + } + + public static boolean isBoolean(final JsonNode schema) { + return hasType(schema) && TypeConstants.BOOLEAN.equalsIgnoreCase(getType(schema)); + } + + public static boolean isNumber(final JsonNode schema) { + return hasType(schema) + && (TypeConstants.INTEGER.equalsIgnoreCase(getType(schema)) + || TypeConstants.NUMBER.equalsIgnoreCase(getType(schema)) + || TypeConstants.INT_64.equalsIgnoreCase(getType(schema)) + || TypeConstants.INT_32.equalsIgnoreCase(getType(schema))); + } + + public static boolean isEnum(final JsonNode schema) { + return schema.has("enum"); + } + + public static boolean isAllOf(final JsonNode schema) { + return hasNode(schema, ALL_OF); + } + + public static boolean isAnyOf(final JsonNode schema) { + return hasNode(schema, ANY_OF); + } + + public static boolean isOneOf(final JsonNode schema) { + return hasNode(schema, ONE_OF); + } + + public static boolean isDateTime(final JsonNode schema) { + final boolean isDateTime; + if (hasType(schema) && TypeConstants.STRING.equalsIgnoreCase(getType(schema))) { + if (hasNode(schema, FORMAT)) { + isDateTime = "date".equalsIgnoreCase(getNode(schema, FORMAT).textValue()) + || "date-time".equalsIgnoreCase(getNode(schema, FORMAT).textValue()); + } else { + isDateTime = false; + } + } else { + isDateTime = false; + } + return isDateTime; + } + + public static List findContentSchemas(final JsonNode schema) { + return hasNode(schema, "content") ? schema.findValues("schema") : Collections.emptyList(); + } + + public static boolean checkIfRequired(final JsonNode schema, final String fieldName) { + boolean isRequired = false; + if (hasNode(schema, REQUIRED)) { + final var fieldIt = getNode(schema, REQUIRED).elements(); + while (fieldIt.hasNext() && !isRequired) { + isRequired = fieldName.equalsIgnoreCase(fieldIt.next().textValue()); + } + } + return isRequired; + } + + private static Transformer getTextValue() { + return JsonNode::asText; + } + + protected static String findValue(final JsonNode message, final String key) { + } +} diff --git a/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java b/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java new file mode 100644 index 00000000..c4878e41 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java @@ -0,0 +1,87 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.sngular.kloadgen.common.tools; + +import java.util.Set; + +public final class TypeConstants { + + public static final String NUMBER = "number"; + + public static final String BOOLEAN = "boolean"; + + public static final String OBJECT = "object"; + + public static final String ARRAY = "array"; + + public static final String BIG_DECIMAL = "bigDecimal"; + + public static final String INTEGER = "integer"; + + public static final String DOUBLE = "double"; + + public static final String FLOAT = "float"; + + public static final String LONG = "long"; + + public static final String STRING = "string"; + + public static final String ENUM = "enum"; + + public static final String LOCAL_DATE = "localdate"; + + public static final String LOCAL_DATETIME = "localdatetime"; + + public static final String ZONED_DATE = "zoneddate"; + + public static final String ZONED_DATETIME = "zoneddatetime"; + + public static final String OFFSET_DATE = "offsetdate"; + + public static final String OFFSET_DATETIME = "offsetdatetime"; + + public static final String INT_32 = "int32"; + + public static final String INT_64 = "int64"; + + public static final Set BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER, ARRAY); + + public static final Set NO_IMPORT_TYPE = Set.of(STRING, INTEGER, OBJECT); + + public static final Set ALL_TYPES = Set.of( + NUMBER, + BOOLEAN, + OBJECT, + ARRAY, + BIG_DECIMAL, + INTEGER, + DOUBLE, + FLOAT, + LONG, + STRING, + ENUM, + LOCAL_DATE, + LOCAL_DATETIME, + ZONED_DATE, + ZONED_DATETIME, + OFFSET_DATE, + OFFSET_DATETIME + ); + + public static boolean isBoolean(final String isBoolean) { + return Boolean.parseBoolean(isBoolean.toLowerCase()); + } + + public enum TimeType { + LOCAL, + ZONED, + OFFSET + } + + private TypeConstants() { + } +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 83384344..49a9e48b 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -25,8 +25,11 @@ import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; import javax.swing.BorderFactory; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; @@ -35,12 +38,11 @@ import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; -import javax.swing.table.JTableHeader; +import javax.swing.table.DefaultTableModel; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; -import org.jetbrains.annotations.NotNull; public class AsyncApiConfigGui extends AbstractSamplerGui { @@ -52,23 +54,19 @@ public class AsyncApiConfigGui extends AbstractSamplerGui { private JPanel mainPanel; - private JTable brokerInfo; - private JTextField asyncApiFileTextField; private JTextField registryUrl; - private JTable schemaRegistry; - - private JTable schemaFields; + private DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Field Values List"}, 20); - private JButton fileButton; + private DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); - private JTableHeader jTableHeaderKafka; + private DefaultTableModel schemaRegistryFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); - private JTableHeader jTableHeaderRegistry; + private JButton fileButton; - private JTableHeader jTableHeaderSchema; + private JComboBox serverComboBox; protected AsyncApiConfigGui() { init(); @@ -82,13 +80,13 @@ private void init() { mainPanel.setPreferredSize(new Dimension(-1, -1)); mainPanel.putClientProperty("html.disable", Boolean.FALSE); mainPanel.setBorder( - BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + BorderFactory + .createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); mainPanel.add("asyncapi.file.selector", createAsyncApiFileSelectPanel()); mainPanel.add("asyncapi.config.options", createAsyncApiTabs()); } - @NotNull private JPanel createAsyncApiFileSelectPanel() { final JPanel fileChoosingPanel = new JPanel(); fileChoosingPanel.setLayout(new GridBagLayout()); @@ -125,7 +123,6 @@ private JPanel createAsyncApiFileSelectPanel() { return fileChoosingPanel; } - @NotNull private JTabbedPane createAsyncApiTabs() { var tabbedPanel = new JTabbedPane(); tabbedPanel.addTab("Broker", createBrokerPanel()); @@ -141,45 +138,44 @@ public final void actionFileChooser(final ActionEvent event) { if (JFileChooser.APPROVE_OPTION == returnValue) { final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); asyncApiFileTextField.setText(apiFile.getAbsolutePath()); - var asyncApiFile = asyncApiExtractor.processFile(apiFile); - - fillTable(brokerInfo, asyncApiExtractor.getBrokerData(asyncApiFile)); - fillTable(schemaRegistry, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); - fillTable(schemaFields, asyncApiExtractor.getSchemaData(asyncApiFile)); + final var asyncApiFile = asyncApiExtractor.processFile(apiFile); + asyncApiFile.getApiServerList().forEach(serverComboBox::addItem); + fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile)); + fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); + fillTable(schemaFieldModel, asyncApiExtractor.getSchemaData(asyncApiFile).getModel()); } } - private void fillTable(final JTable schemaFields, final List schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(i); + } + schemaData.forEach(data -> schemaFields.addRow(dataToRow(data))); + } + private Object[] dataToRow(final T data) { + return data.getProperties(); } - @NotNull private JPanel createBrokerPanel() { final JPanel brokerPanel = new JPanel(); brokerPanel.setLayout(new BorderLayout(0, 0)); - var label = new JLabeledTextField("") - brokerInfo = new JTable(); - brokerInfo.setIntercellSpacing(new Dimension(2, 1)); - brokerInfo.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE); - brokerInfo.putClientProperty("Table.isFileList", Boolean.TRUE); - jTableHeaderKafka = new JTableHeader(); - jTableHeaderKafka.add(getComponentProperty("Property")); - jTableHeaderKafka.add(getComponentProperty("Value")); - brokerInfo.setTableHeader(jTableHeaderKafka); - brokerPanel.add(brokerInfo, BorderLayout.CENTER); + brokerPanel.add(new JLabeledTextField("Broker Server")); + serverComboBox = new JComboBox<>(); + brokerPanel.add(serverComboBox); + brokerPanel.add(new JTable(brokerFieldModel), BorderLayout.CENTER); return brokerPanel; } - @NotNull private JPanel createRegistryTab() { - GridBagConstraints gridBagConstraints; final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new GridBagLayout()); registryUrlPanel.setMinimumSize(new Dimension(45, 45)); registryUrlPanel.setPreferredSize(new Dimension(200, 45)); final JLabel label2 = new JLabel(); label2.setText("Schema Registry URL"); - gridBagConstraints = new GridBagConstraints(); + var gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = GridBagConstraints.WEST; @@ -203,37 +199,22 @@ private JPanel createRegistryTab() { final JLabel label3 = new JLabel(); label3.setText("Security Options"); panel5.add(label3); - schemaRegistry = new JTable(); - jTableHeaderRegistry = new JTableHeader(); - jTableHeaderRegistry.add(getComponentProperty("Property")); - jTableHeaderRegistry.add(getComponentProperty("Value")); - schemaRegistry.setTableHeader(jTableHeaderRegistry); - panel5.add(schemaRegistry); + panel5.add(new JTable(schemaRegistryFieldModel)); return registryUrlPanel; } - @NotNull private JPanel createSchemaTab() { final JPanel schemaTab = new JPanel(); schemaTab.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); - schemaFields = new JTable(); - jTableHeaderSchema = new JTableHeader(); - jTableHeaderSchema.add(getComponentProperty("Field Name")); - jTableHeaderSchema.add(getComponentProperty("Field Type")); - jTableHeaderSchema.add(getComponentProperty("Field Size")); - jTableHeaderSchema.add(getComponentProperty("Field Value")); - schemaFields.setTableHeader(jTableHeaderSchema); - schemaFields.setSurrendersFocusOnKeystroke(false); - schemaTab.add(schemaFields); + schemaTab.add(new JTable(schemaFieldModel)); return schemaTab; } - @NotNull - private static Component getComponentProperty(final String Property) { + private static Component getComponentProperty(final String property) { return new Component() { @Override public String getName() { - return Property; + return property; } }; } diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java index 2d4ace68..c2f8678c 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -16,5 +16,5 @@ public interface ApiExtractor { List getSchemaRegistryData(AsyncApiFile asyncApiFile); - List getSchemaData(AsyncApiFile asyncApiFile); + AsyncApiSchema getSchemaData(AsyncApiFile asyncApiFile); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index c53ba9e8..89c4ce05 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -1,13 +1,89 @@ package com.sngular.kloadgen.extractor.asyncapi; import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.sngular.kloadgen.common.tools.ApiTool; +import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.extractor.model.AsyncApiSR; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; public class AsyncApiExtractorImpl implements ApiExtractor { + public static final String ERROR_WRONG_ASYNC_API_SCHEMA = "Wrong AsyncApi Schema"; + + public static final String SERVERS = "servers"; + + public static final String CHANNELS = "channels"; + + final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + @Override - public void processFile(final File apiFile) { + public AsyncApiFile processFile(final File apiFile) { + var builder = AsyncApiFile.builder(); + try { + final JsonNode openApi = om.readTree(apiFile); + builder.apiServerList(nodeToApServer(ApiTool.getNode(openApi, SERVERS))); + builder.apiSchemaList(nodeToSchema(ApiTool.getNode(openApi, CHANNELS))); + } catch (IOException e) { + throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e); + } + + return null; + } + private List nodeToSchema(final JsonNode node) { + var schemaList = new ArrayList(); + node.fields().forEachRemaining(channel -> schemaList.add(mapNodeToSchema(channel.getKey(), channel.getValue()))); + return schemaList; + } + + private AsyncApiSchema mapNodeToSchema(final String topic, final JsonNode node) { + var builder = AsyncApiSchema.builder(); + builder.topicName(topic); + var message = ApiTool.getNode(node, "message"); + if (ApiTool.hasNode(message, "bindings")) { + builder.key(true); + builder.keyType(ApiTool.findValue(message, "key")) + } + return builder.build(); + } + + private List nodeToApServer(final JsonNode node) { + var serverList = new ArrayList(); + node.fields().forEachRemaining(server -> serverList.add(mapNodeToServer(server.getKey(), server.getValue()))); + return serverList; + } + + private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode server) { + var builder = AsyncApiServer.builder(); + builder.name(serverName); + builder.url(ApiTool.getNodeAsString(server, "url")); + builder.protocol(ApiTool.getNodeAsString(server, "protocol")); + builder.description(ApiTool.getNodeAsString(server, "description")); + return builder.build(); + } + + @Override + public List getBrokerData(final AsyncApiFile asyncApiFile) { + return null; + } + + @Override + public List getSchemaRegistryData(final AsyncApiFile asyncApiFile) { + return null; + } + + @Override + public AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile) { + return null; } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java new file mode 100644 index 00000000..6375a653 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java @@ -0,0 +1,7 @@ +package com.sngular.kloadgen.extractor.model; + +public interface AsyncApiAbstract { + + Object[] getProperties(); + +} diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java index f345e786..11d26a24 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java @@ -5,9 +5,14 @@ @Value @Data -public class AsyncApiSR { +public class AsyncApiSR implements AsyncApiAbstract { String schemaRegistryUrl; String schemaRegistryVendor; + + @Override + public Object[] getProperties() { + return new Object[0]; + } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java index fb2c1aad..fca6f3bb 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java @@ -5,7 +5,7 @@ @Value @Builder -public class AsyncApiServer { +public class AsyncApiServer implements AsyncApiAbstract { String name; @@ -14,4 +14,9 @@ public class AsyncApiServer { String protocol; String description; + + @Override + public Object[] getProperties() { + return new Object[0]; + } } diff --git a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java index c3f257a2..eccd3438 100644 --- a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java +++ b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -28,7 +29,7 @@ @ToString @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class FieldValueMapping extends AbstractTestElement { +public class FieldValueMapping extends AbstractTestElement implements AsyncApiAbstract { public static final String FIELD_CONSTRAINTS = "constraints"; @@ -167,6 +168,10 @@ public final void setConstraints(final Map constrain this.constraints = constraints; } + public final Object[] getProperties() { + return new Object[] {getFieldName(), getFieldType(), getValueLength(), getFieldValuesList()}; + } + public static final class FieldValueMappingBuilder { private final Map constraints = new EnumMap<>(ConstraintTypeEnum.class); From d2ec0c399817b6bcafc3540c78bccbf9d70189db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Tue, 22 Aug 2023 11:13:29 +0200 Subject: [PATCH 08/55] 384 Support for reference Schemas --- src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java | 4 ++-- .../kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java index 3b5912bc..ace68eab 100644 --- a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -291,6 +291,6 @@ private static Transformer getTextValue() { return JsonNode::asText; } - protected static String findValue(final JsonNode message, final String key) { - } +/* protected static String findValue(final JsonNode message, final String key) { + }*/ } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 89c4ce05..375c4412 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -52,7 +52,7 @@ private AsyncApiSchema mapNodeToSchema(final String topic, final JsonNode node) var message = ApiTool.getNode(node, "message"); if (ApiTool.hasNode(message, "bindings")) { builder.key(true); - builder.keyType(ApiTool.findValue(message, "key")) + // builder.keyType(ApiTool.findValue(message, "key")); } return builder.build(); } From e7afd3a464a7d8bdf7d21a28307f229fb79337d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 23 Aug 2023 00:47:43 +0200 Subject: [PATCH 09/55] 340 Fix read schema file --- pom.xml | 9 ++--- .../config/asyncapi/AsyncApiConfigGui.java | 33 +++++++++++-------- .../config/asyncapi/AsyncApiTestElement.java | 17 ---------- .../kloadgen/sampler/AsyncApiSampler.java | 25 ++++++++++++++ ...KafkaHeadersConfigElementBeanInfoTest.java | 7 +++- ...leSerializedConfigElementBeanInfoTest.java | 2 +- ...eySerializedConfigElementBeanInfoTest.java | 2 +- ...leSerializedConfigElementBeanInfoTest.java | 14 ++++---- ...ueSerializedConfigElementBeanInfoTest.java | 12 +++---- 9 files changed, 68 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java create mode 100644 src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java diff --git a/pom.xml b/pom.xml index 1bc09f13..dc370f90 100644 --- a/pom.xml +++ b/pom.xml @@ -298,9 +298,9 @@ 2.8.6 32.0.0-jre 2.4.0-b180830.0359 - 11 + 17 provided - 5.5 + 5.6.2 2.6.0 5.8.2 7.1.1 @@ -343,11 +343,6 @@ - - com.google.guava - guava - ${guava.version} - com.eclipsesource.minimal-json minimal-json diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 49a9e48b..a46efa09 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -27,6 +27,7 @@ import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.sampler.AsyncApiSampler; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; @@ -43,10 +44,12 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; +import org.apache.jorphan.logging.LoggingManager; +import org.apache.log.Logger; -public class AsyncApiConfigGui extends AbstractSamplerGui { +public final class AsyncApiConfigGui extends AbstractSamplerGui { - public static final String ERROR_FAILED_TO_RETRIEVE_PROPERTIES = "ERROR: Failed to retrieve properties!"; + private static final Logger log = LoggingManager.getLoggerForClass(); private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); @@ -58,33 +61,37 @@ public class AsyncApiConfigGui extends AbstractSamplerGui { private JTextField registryUrl; - private DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Field Values List"}, 20); + private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Field Values List"}, 20); - private DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); + private final DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); - private DefaultTableModel schemaRegistryFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); - - private JButton fileButton; + private final DefaultTableModel schemaRegistryFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); private JComboBox serverComboBox; - protected AsyncApiConfigGui() { + public AsyncApiConfigGui() { + super(); init(); } + @Override + public String getStaticLabel() { + return "AsyncApi Sampler"; + } + private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); mainPanel = new JPanel(); mainPanel.setLayout(new GridBagLayout()); - mainPanel.setPreferredSize(new Dimension(-1, -1)); mainPanel.putClientProperty("html.disable", Boolean.FALSE); mainPanel.setBorder( BorderFactory .createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); - mainPanel.add("asyncapi.file.selector", createAsyncApiFileSelectPanel()); - mainPanel.add("asyncapi.config.options", createAsyncApiTabs()); + mainPanel.add(createAsyncApiFileSelectPanel(), BorderLayout.NORTH); + mainPanel.add(createAsyncApiTabs(), BorderLayout.SOUTH); + add(mainPanel); } private JPanel createAsyncApiFileSelectPanel() { @@ -105,7 +112,7 @@ private JPanel createAsyncApiFileSelectPanel() { gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); - fileButton = new JButton(); + JButton fileButton = new JButton(); fileButton.setText("Open File"); fileButton.addActionListener(this::actionFileChooser); gridBagConstraints = new GridBagConstraints(); @@ -233,7 +240,7 @@ public String getLabelResource() { @Override public TestElement createTestElement() { - var testElement = new AsyncApiTestElement(); + var testElement = new AsyncApiSampler(); modifyTestElement(testElement); return testElement; } diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java deleted file mode 100644 index b2c7c258..00000000 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiTestElement.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.sngular.kloadgen.config.asyncapi; - -import org.apache.jmeter.config.Arguments; - -public class AsyncApiTestElement extends Arguments { - - public static final String FILENAME = "filename"; - public static final String BROKER = "broker"; - public static final String SCHEMA_REGISTRY = "schema_registry"; - public static final String CHANNEL = "channel"; - public static final String MESSAGE = "message"; - public static final String KAFKA_KEY = "kafka.key"; - public static final String KAFKA_PAYLOAD = "kafka_payload"; - - - -} diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java new file mode 100644 index 00000000..8c475714 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -0,0 +1,25 @@ +package com.sngular.kloadgen.sampler; + +import java.io.Serializable; + +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.jmeter.config.ConfigTestElement; +import org.apache.jmeter.samplers.AbstractSampler; +import org.apache.jmeter.samplers.Entry; +import org.apache.jmeter.samplers.SampleResult; + +@Slf4j +@NoArgsConstructor +public class AsyncApiSampler extends AbstractSampler implements Serializable { + + @Override + public boolean applies(final ConfigTestElement configElement) { + return super.applies(configElement); + } + + @Override + public SampleResult sample(final Entry entry) { + return null; + } +} diff --git a/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java index f2e58370..403a04ae 100644 --- a/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java @@ -9,11 +9,13 @@ import java.beans.PropertyDescriptor; import java.util.Locale; +import lombok.extern.slf4j.Slf4j; import org.apache.jmeter.util.JMeterUtils; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +@Slf4j class KafkaHeadersConfigElementBeanInfoTest { private static final String KAFKA_HEADERS = "kafkaHeaders"; @@ -29,7 +31,10 @@ public void setUp() { @Test final void shouldGenerateElements() { final PropertyDescriptor[] propertyDescriptors = kafkaHeadersConfigElementBeanInfo.getPropertyDescriptors(); - Assertions.assertThat(propertyDescriptors).hasSize(1); + Assertions.assertThat(propertyDescriptors).hasSize(3); Assertions.assertThat(propertyDescriptors[0].getName()).isEqualTo(KAFKA_HEADERS); + for (var property : propertyDescriptors) { + log.info(property.toString()); + } } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/config/keyfileserialized/KeyFileSerializedConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/keyfileserialized/KeyFileSerializedConfigElementBeanInfoTest.java index 4aec184b..e64b7005 100644 --- a/src/test/java/com/sngular/kloadgen/config/keyfileserialized/KeyFileSerializedConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/keyfileserialized/KeyFileSerializedConfigElementBeanInfoTest.java @@ -39,7 +39,7 @@ public void setUp() { @Test void shouldGenerateElements() { final PropertyDescriptor[] propertyDescriptors = keyFileSerializedConfigElementBeanInfo.getPropertyDescriptors(); - Assertions.assertThat(propertyDescriptors).hasSize(6); + Assertions.assertThat(propertyDescriptors).hasSize(8); Assertions.assertThat(propertyDescriptors[0].getName()).isEqualTo(KEY_NAME_STRATEGY); Assertions.assertThat(propertyDescriptors[1].getName()).isEqualTo(KEY_SCHEMA_DEFINITION); Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(KEY_SCHEMA_PROPERTIES); diff --git a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java index c57ad23f..f5433c59 100644 --- a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java @@ -37,7 +37,7 @@ public void setUp() { @Test void shouldGenerateElements() { final PropertyDescriptor[] propertyDescriptors = keySerializedConfigElementBeanInfo.getPropertyDescriptors(); - Assertions.assertThat(propertyDescriptors).hasSize(5); + Assertions.assertThat(propertyDescriptors).hasSize(7); Assertions.assertThat(propertyDescriptors[0].getName()).isEqualTo(KEY_NAME_STRATEGY); Assertions.assertThat(propertyDescriptors[1].getName()).isEqualTo(KEY_SCHEMA_PROPERTIES); Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(KEY_SCHEMA_TYPE); diff --git a/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfoTest.java index 1346ec90..73e52752 100644 --- a/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfoTest.java @@ -39,12 +39,12 @@ public void setUp() { @Test void shouldGenerateElements() { final PropertyDescriptor[] propertyDescriptors = valueFileSerializedConfigElementBeanInfo.getPropertyDescriptors(); - Assertions.assertThat(propertyDescriptors).hasSize(6); - Assertions.assertThat(propertyDescriptors[0].getName()).isEqualTo(VALUE_NAME_STRATEGY); - Assertions.assertThat(propertyDescriptors[1].getName()).isEqualTo(VALUE_SCHEMA_DEFINITION); - Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(VALUE_SCHEMA_PROPERTIES); - Assertions.assertThat(propertyDescriptors[3].getName()).isEqualTo(VALUE_SCHEMA_TYPE); - Assertions.assertThat(propertyDescriptors[4].getName()).isEqualTo(SERIALIZER_PROPERTY); - Assertions.assertThat(propertyDescriptors[5].getName()).isEqualTo(VALUE_SUBJECT_NAME); + Assertions.assertThat(propertyDescriptors).hasSize(8); + Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(VALUE_NAME_STRATEGY); + Assertions.assertThat(propertyDescriptors[3].getName()).isEqualTo(VALUE_SCHEMA_DEFINITION); + Assertions.assertThat(propertyDescriptors[4].getName()).isEqualTo(VALUE_SCHEMA_PROPERTIES); + Assertions.assertThat(propertyDescriptors[5].getName()).isEqualTo(VALUE_SCHEMA_TYPE); + Assertions.assertThat(propertyDescriptors[6].getName()).isEqualTo(SERIALIZER_PROPERTY); + Assertions.assertThat(propertyDescriptors[7].getName()).isEqualTo(VALUE_SUBJECT_NAME); } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementBeanInfoTest.java index 6bd40d5d..e4477b9e 100644 --- a/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementBeanInfoTest.java @@ -36,11 +36,11 @@ public void setUp() { @Test void shouldGenerateElements() { final var propertyDescriptors = valueSerializedConfigElementBeanInfo.getPropertyDescriptors(); - Assertions.assertThat(propertyDescriptors).hasSize(5); - Assertions.assertThat(propertyDescriptors[0].getName()).isEqualTo(VALUE_NAME_STRATEGY); - Assertions.assertThat(propertyDescriptors[1].getName()).isEqualTo(VALUE_SCHEMA_PROPERTIES); - Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(VALUE_SCHEMA_TYPE); - Assertions.assertThat(propertyDescriptors[3].getName()).isEqualTo(VALUE_SERIALIZER_CONFIGURATION); - Assertions.assertThat(propertyDescriptors[4].getName()).isEqualTo(VALUE_SUBJECT_NAME); + Assertions.assertThat(propertyDescriptors).hasSize(7); + Assertions.assertThat(propertyDescriptors[2].getName()).isEqualTo(VALUE_NAME_STRATEGY); + Assertions.assertThat(propertyDescriptors[3].getName()).isEqualTo(VALUE_SCHEMA_PROPERTIES); + Assertions.assertThat(propertyDescriptors[4].getName()).isEqualTo(VALUE_SCHEMA_TYPE); + Assertions.assertThat(propertyDescriptors[5].getName()).isEqualTo(VALUE_SERIALIZER_CONFIGURATION); + Assertions.assertThat(propertyDescriptors[6].getName()).isEqualTo(VALUE_SUBJECT_NAME); } } \ No newline at end of file From b5fe862fd8f784a5df6207ad4f496899c7ff652d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 23 Aug 2023 16:35:43 +0200 Subject: [PATCH 10/55] 340 Fix read schema file --- .../kloadgen/config/asyncapi/AsyncApiConfigGui.java | 4 ++-- .../extractor/asyncapi/AsyncApiExtractorImpl.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index a46efa09..7090c615 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -83,7 +83,7 @@ private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); mainPanel = new JPanel(); - mainPanel.setLayout(new GridBagLayout()); + mainPanel.setLayout(new BorderLayout()); mainPanel.putClientProperty("html.disable", Boolean.FALSE); mainPanel.setBorder( BorderFactory @@ -138,7 +138,7 @@ private JTabbedPane createAsyncApiTabs() { return tabbedPanel; } - public final void actionFileChooser(final ActionEvent event) { + public void actionFileChooser(final ActionEvent event) { final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 375c4412..ff0c933a 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -37,7 +37,7 @@ public AsyncApiFile processFile(final File apiFile) { throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e); } - return null; + return builder.build(); } private List nodeToSchema(final JsonNode node) { @@ -74,16 +74,16 @@ private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode s @Override public List getBrokerData(final AsyncApiFile asyncApiFile) { - return null; + return asyncApiFile.getApiServerList(); } @Override public List getSchemaRegistryData(final AsyncApiFile asyncApiFile) { - return null; + return asyncApiFile.getApiAsyncApiSRList(); } @Override public AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile) { - return null; + return asyncApiFile.getApiSchemaList().get(0); } } From e64d4675b6387e4f5e8e92b2723c3f0151abc3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Tue, 5 Sep 2023 19:40:34 +0200 Subject: [PATCH 11/55] AsyncApi parser support --- .../kloadgen/common/tools/ApiTool.java | 65 +++--- .../kloadgen/common/tools/MapperUtil.java | 135 ++++++++++++ .../config/asyncapi/ApiSchemaRenderer.java | 51 +++++ .../config/asyncapi/ApiServerRenderer.java | 51 +++++ .../config/asyncapi/AsyncApiConfigGui.java | 40 ++-- .../kloadgen/extractor/ApiExtractor.java | 12 +- .../asyncapi/AsyncApiExtractorImpl.java | 204 ++++++++++++++++-- .../extractor/model/AsyncApiFile.java | 4 +- .../kloadgen/extractor/model/AsyncApiSR.java | 2 +- .../extractor/model/AsyncApiSchema.java | 8 +- .../extractor/model/AsyncApiServer.java | 2 +- 11 files changed, 487 insertions(+), 87 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java create mode 100644 src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java index ace68eab..5f8de2a2 100644 --- a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -9,7 +9,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; - import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IteratorUtils; @@ -24,6 +23,8 @@ public final class ApiTool { public static final String ONE_OF = "oneOf"; public static final String COMPONENTS = "components"; public static final String SCHEMAS = "schemas"; + + public static final String MESSAGES = "messages"; public static final String REQUIRED = "required"; public static final String PARAMETERS = "parameters"; @@ -33,6 +34,9 @@ public final class ApiTool { private ApiTool() { } + public static JsonNode findNodeValue(final JsonNode node, final String valueName) { + return node.findValue(valueName); + } public static String getType(final JsonNode schema) { return hasType(schema) ? getNodeAsString(schema, "type") : ""; } @@ -96,44 +100,31 @@ public static JsonNode getItems(final JsonNode schema) { } public static Map getComponentSchemas(final JsonNode openApi) { - final var schemasMap = new HashMap(); - - if (hasNode(openApi, COMPONENTS)) { - final var components = getNode(openApi, COMPONENTS); - if (hasNode(components, SCHEMAS)) { - final var schemas = getNode(components, SCHEMAS); - final var schemasIt = schemas.fieldNames(); - schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); - } - } + return getSchemas(openApi, SCHEMAS); + } - return schemasMap; + public static Map getComponentMessages(final JsonNode openApi) { + return getSchemas(openApi, MESSAGES); } public static Map getParameterSchemas(final JsonNode openApi) { - final var schemasMap = new HashMap(); + return getSchemas(openApi, PARAMETERS); + } - if (hasNode(openApi, COMPONENTS)) { - final var components = getNode(openApi, COMPONENTS); - if (hasNode(components, PARAMETERS)) { - final var schemas = getNode(components, PARAMETERS); - final var schemasIt = schemas.fieldNames(); - schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); - } - } + public static Map getResponseSchemas(final JsonNode openApi) { - return schemasMap; + return getSchemas(openApi, RESPONSES); } - public static Map getResponseSchemas(final JsonNode openApi) { + public static Map getSchemas(final JsonNode openApi, final String schemaType) { final var schemasMap = new HashMap(); if (hasNode(openApi, COMPONENTS)) { final var components = getNode(openApi, COMPONENTS); - if (hasNode(components, RESPONSES)) { - final var schemas = getNode(components, RESPONSES); + if (hasNode(components, schemaType)) { + final var schemas = getNode(components, schemaType); final var schemasIt = schemas.fieldNames(); - schemasIt.forEachRemaining(name -> schemasMap.put(name, getNode(schemas, name))); + schemasIt.forEachRemaining(name -> schemasMap.put(schemaType + "/" + name, getNode(schemas, name))); } } @@ -156,20 +147,14 @@ public static Map getComponentSecuritySchemes(final JsonNode o public static String getNumberType(final JsonNode schema) { final String type; if (hasType(schema)) { - switch (getType(schema)) { - case TypeConstants.DOUBLE: type = TypeConstants.DOUBLE; - break; - case TypeConstants.FLOAT: type = TypeConstants.FLOAT; - break; - case TypeConstants.NUMBER: type = TypeConstants.NUMBER; - break; - case TypeConstants.INT_64: type = TypeConstants.INT_64; - break; - case TypeConstants.INT_32: type = TypeConstants.INT_32; - break; - default: type = TypeConstants.INTEGER; - break; - } + type = switch (getType(schema)) { + case TypeConstants.DOUBLE -> TypeConstants.DOUBLE; + case TypeConstants.FLOAT -> TypeConstants.FLOAT; + case TypeConstants.NUMBER -> TypeConstants.NUMBER; + case TypeConstants.INT_64 -> TypeConstants.INT_64; + case TypeConstants.INT_32 -> TypeConstants.INT_32; + default -> TypeConstants.INTEGER; + }; } else { type = TypeConstants.INTEGER; } diff --git a/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java b/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java new file mode 100644 index 00000000..c21a9113 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java @@ -0,0 +1,135 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.sngular.kloadgen.common.tools; + +import java.util.Objects; +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.commons.lang3.StringUtils; + +public class MapperUtil { + + public static final String INTEGER = "integer"; + + public static final String DOUBLE = "double"; + + public static final String FLOAT = "float"; + + public static final String NUMBER = "number"; + + public static final String INT_64 = "int64"; + + public static final String LONG = "long"; + + public static final String BIG_DECIMAL = "bigDecimal"; + + public static final String REF = "$ref"; + + private static final String DIVISOR = "([./])"; + + private MapperUtil() {} + + public static String getSimpleType(final JsonNode schema, final String prefix, final String suffix) { + String type = schema.textValue(); + if (schema.has("type")) { + type = schema.get("type").textValue(); + String format = null; + if ("string".equalsIgnoreCase(type)) { + type = "String"; + } + if (schema.has("format")) { + format = schema.get("format").textValue(); + } + if (NUMBER.equalsIgnoreCase(type)) { + if (FLOAT.equalsIgnoreCase(format)) { + type = FLOAT; + } else if (DOUBLE.equalsIgnoreCase(format)) { + type = DOUBLE; + } else { + type = BIG_DECIMAL; + } + } else if (INTEGER.equalsIgnoreCase(type)) { + if (INT_64.equalsIgnoreCase(format)) { + type = LONG; + } else { + type = INTEGER; + } + } + } else if (schema.has(REF)) { + type = getRef(schema, prefix, suffix); + } + return type; + } + + public static String getRef(final JsonNode schema, final String prefix, final String suffix) { + return getPojoName(getRefClass(schema), prefix, suffix); + } + + public static String getLongRefClass(final JsonNode schema) { + final String[] pathObjectRef = getStrings(schema); + return pathObjectRef[pathObjectRef.length - 2] + "/" + pathObjectRef[pathObjectRef.length - 1]; + } + + private static String[] getStrings(final JsonNode schema) { + return splitName(schema.get(REF).textValue()); + } + + public static String getRefClass(final JsonNode schema) { + final String[] pathObjectRef = getStrings(schema); + return pathObjectRef[pathObjectRef.length - 1]; + } + + public static String getTypeMap(final JsonNode mapSchema, final String prefix, final String suffix) { + var typeMap = ""; + final var mapNode = mapSchema.get("additionalProperties"); + final var mapValueType = mapNode.findPath("type"); + typeMap = getCollectionType(mapNode, mapValueType, prefix, suffix); + return typeMap; + } + + public static String getTypeArray(final JsonNode array, final String prefix, final String suffix) { + var typeArray = ""; + final var arrayNode = array.get("items"); + final JsonNode mapValueType; + if (arrayNode.has("type")) { + mapValueType = arrayNode.get("type"); + } else { + mapValueType = arrayNode.get(REF); + } + typeArray = getCollectionType(arrayNode, mapValueType, prefix, suffix); + return typeArray; + } + + private static String getCollectionType(final JsonNode mapNode, final JsonNode mapValueType, final String prefix, final String suffix) { + var typeMap = mapValueType.textValue(); + if (!typeMap.contains("#")) { + if ("string".equalsIgnoreCase(mapValueType.textValue())) { + typeMap = "String"; + } else if (INTEGER.equalsIgnoreCase(mapValueType.textValue())) { + typeMap = "Integer"; + } else { + typeMap = mapValueType.textValue(); + } + } else { + final var valueSchema = mapNode.findPath(REF); + if (Objects.nonNull(valueSchema)) { + getRef(valueSchema, prefix, suffix); + } + } + return typeMap; + } + + public static String getPojoName(final String namePojo, final String prefix, final String suffix) { + return StringUtils.defaultIfBlank(prefix, "") + + StringUtils.capitalize(namePojo) + + StringUtils.defaultIfBlank(suffix, ""); + } + + public static String[] splitName(final String name) { + return name.split(DIVISOR); + } + +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java new file mode 100644 index 00000000..a7c5bb62 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java @@ -0,0 +1,51 @@ +package com.sngular.kloadgen.config.asyncapi; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.JLabel; +import javax.swing.JList; + +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; + +public class ApiSchemaRenderer extends JLabel implements javax.swing.ListCellRenderer { + + protected ApiSchemaRenderer() { + setOpaque(true); + } + + @Override + public final Component getListCellRendererComponent( + final JList list, final AsyncApiSchema value, final int index, final boolean isSelected, final boolean cellHasFocus) { + + setText(value.toString()); + + final Color background; + final Color foreground; + + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + background = Color.BLUE; + foreground = Color.WHITE; + + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; + + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + + setBackground(background); + setForeground(foreground); + + return this; + } +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java new file mode 100644 index 00000000..1d0126db --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java @@ -0,0 +1,51 @@ +package com.sngular.kloadgen.config.asyncapi; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.JLabel; +import javax.swing.JList; + +import com.sngular.kloadgen.extractor.model.AsyncApiServer; + +public class ApiServerRenderer extends JLabel implements javax.swing.ListCellRenderer { + + protected ApiServerRenderer() { + setOpaque(true); + } + + @Override + public final Component getListCellRendererComponent( + final JList list, final AsyncApiServer value, final int index, final boolean isSelected, final boolean cellHasFocus) { + + setText(value.toString()); + + final Color background; + final Color foreground; + + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + background = Color.BLUE; + foreground = Color.WHITE; + + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; + + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + + setBackground(background); + setForeground(foreground); + + return this; + } +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 7090c615..5c4a52ef 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -23,11 +23,6 @@ import java.util.List; import java.util.Objects; -import com.sngular.kloadgen.extractor.ApiExtractor; -import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; -import com.sngular.kloadgen.sampler.AsyncApiSampler; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; @@ -40,6 +35,13 @@ import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; import javax.swing.table.DefaultTableModel; + +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.sampler.AsyncApiSampler; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; @@ -69,6 +71,8 @@ public final class AsyncApiConfigGui extends AbstractSamplerGui { private JComboBox serverComboBox; + private JComboBox topicComboBox; + public AsyncApiConfigGui() { super(); init(); @@ -112,7 +116,7 @@ private JPanel createAsyncApiFileSelectPanel() { gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); - JButton fileButton = new JButton(); + final JButton fileButton = new JButton(); fileButton.setText("Open File"); fileButton.addActionListener(this::actionFileChooser); gridBagConstraints = new GridBagConstraints(); @@ -131,7 +135,7 @@ private JPanel createAsyncApiFileSelectPanel() { } private JTabbedPane createAsyncApiTabs() { - var tabbedPanel = new JTabbedPane(); + final var tabbedPanel = new JTabbedPane(); tabbedPanel.addTab("Broker", createBrokerPanel()); tabbedPanel.addTab("Registry", createRegistryTab()); tabbedPanel.addTab("Schema", createSchemaTab()); @@ -149,16 +153,18 @@ public void actionFileChooser(final ActionEvent event) { asyncApiFile.getApiServerList().forEach(serverComboBox::addItem); fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile)); fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); - fillTable(schemaFieldModel, asyncApiExtractor.getSchemaData(asyncApiFile).getModel()); + asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); } } private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { - final var count = schemaFields.getRowCount(); - for (var i = 0; i < count; i++) { - schemaFields.removeRow(i); + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + schemaData.forEach(data -> schemaFields.addRow(dataToRow(data))); } - schemaData.forEach(data -> schemaFields.addRow(dataToRow(data))); } private Object[] dataToRow(final T data) { @@ -170,6 +176,7 @@ private JPanel createBrokerPanel() { brokerPanel.setLayout(new BorderLayout(0, 0)); brokerPanel.add(new JLabeledTextField("Broker Server")); serverComboBox = new JComboBox<>(); + serverComboBox.setRenderer(new ApiServerRenderer()); brokerPanel.add(serverComboBox); brokerPanel.add(new JTable(brokerFieldModel), BorderLayout.CENTER); return brokerPanel; @@ -179,7 +186,7 @@ private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new GridBagLayout()); registryUrlPanel.setMinimumSize(new Dimension(45, 45)); - registryUrlPanel.setPreferredSize(new Dimension(200, 45)); + registryUrlPanel.setPreferredSize(new Dimension(800, 600)); final JLabel label2 = new JLabel(); label2.setText("Schema Registry URL"); var gridBagConstraints = new GridBagConstraints(); @@ -213,6 +220,9 @@ private JPanel createRegistryTab() { private JPanel createSchemaTab() { final JPanel schemaTab = new JPanel(); schemaTab.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + topicComboBox = new JComboBox<>(); + topicComboBox.setRenderer(new ApiSchemaRenderer()); + schemaTab.add(topicComboBox); schemaTab.add(new JTable(schemaFieldModel)); return schemaTab; } @@ -235,12 +245,12 @@ public void clearGui() { @Override public String getLabelResource() { - return null; + return "Asyncapi"; } @Override public TestElement createTestElement() { - var testElement = new AsyncApiSampler(); + final var testElement = new AsyncApiSampler(); modifyTestElement(testElement); return testElement; } diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java index c2f8678c..9984498d 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -2,7 +2,7 @@ import java.io.File; import java.util.List; - +import java.util.Map; import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; @@ -10,11 +10,13 @@ public interface ApiExtractor { - AsyncApiFile processFile(File apiFile); + AsyncApiFile processFile(final File apiFile); + + List getBrokerData(final AsyncApiFile asyncApiFile); - List getBrokerData(AsyncApiFile asyncApiFile); + List getSchemaRegistryData(final AsyncApiFile asyncApiFile); - List getSchemaRegistryData(AsyncApiFile asyncApiFile); + AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile, final String topic); - AsyncApiSchema getSchemaData(AsyncApiFile asyncApiFile); + Map getSchemaDataMap(final AsyncApiFile asyncApiFile); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index ff0c933a..bee725fe 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -3,68 +3,225 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; - +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.sngular.kloadgen.common.tools.ApiTool; +import com.sngular.kloadgen.common.tools.MapperUtil; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.model.FieldValueMapping; +import org.apache.commons.lang3.StringUtils; public class AsyncApiExtractorImpl implements ApiExtractor { - public static final String ERROR_WRONG_ASYNC_API_SCHEMA = "Wrong AsyncApi Schema"; + private static final Set COMPLEX_TYPES = Set.of("record", "array"); + private static final String ERROR_WRONG_ASYNC_API_SCHEMA = "Wrong AsyncApi Schema"; - public static final String SERVERS = "servers"; + private static final String SERVERS = "servers"; - public static final String CHANNELS = "channels"; + private static final String CHANNELS = "channels"; - final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); @Override - public AsyncApiFile processFile(final File apiFile) { - var builder = AsyncApiFile.builder(); + public final AsyncApiFile processFile(final File apiFile) { + final var builder = AsyncApiFile.builder(); try { final JsonNode openApi = om.readTree(apiFile); builder.apiServerList(nodeToApServer(ApiTool.getNode(openApi, SERVERS))); - builder.apiSchemaList(nodeToSchema(ApiTool.getNode(openApi, CHANNELS))); - } catch (IOException e) { + builder.apiSchemaList(nodeToSchema(openApi)); + } catch (final IOException e) { throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e); } return builder.build(); } - private List nodeToSchema(final JsonNode node) { - var schemaList = new ArrayList(); - node.fields().forEachRemaining(channel -> schemaList.add(mapNodeToSchema(channel.getKey(), channel.getValue()))); + private Map nodeToSchema(final JsonNode openApi) { + final var channels = ApiTool.getNode(openApi, CHANNELS); + final var schemaList = new HashMap(); + final Map totalSchemas = new HashMap<>(ApiTool.getComponentSchemas(openApi)); + totalSchemas.putAll(ApiTool.getComponentMessages(openApi)); + channels + .fields() + .forEachRemaining(channel -> + schemaList.put(channel.getKey(), + mapNodeToSchema(totalSchemas, channel.getKey(), channel.getValue()))); return schemaList; } - private AsyncApiSchema mapNodeToSchema(final String topic, final JsonNode node) { - var builder = AsyncApiSchema.builder(); + private AsyncApiSchema mapNodeToSchema(final Map components, final String topic, final JsonNode node) { + final var antiLoopList = new ArrayList(); + final var builder = AsyncApiSchema.builder(); builder.topicName(topic); - var message = ApiTool.getNode(node, "message"); + final var message = ApiTool.findNodeValue(node, "message"); if (ApiTool.hasNode(message, "bindings")) { builder.key(true); // builder.keyType(ApiTool.findValue(message, "key")); } + builder.model(messageToFieldList(message, components, antiLoopList)); return builder.build(); } + private List messageToFieldList(final JsonNode message, final Map components, final List antiLoopList) { + var payload = ApiTool.getNode(message, "payload"); + if (ApiTool.hasRef(message)) { + payload = solveRef(message, components, antiLoopList, "messages"); + } else if (!ApiTool.hasNode(message, "payload")) { + throw new KLoadGenException("AsyncApi format still not supported"); + } + + + return extractFieldList(payload, components, antiLoopList); + } + + private List extractFieldList(final JsonNode payload, final Map components, final List antiLoopList) { + var finalPayload = payload; + if (ApiTool.hasRef(payload)) { + final var payloadPath = MapperUtil.splitName(ApiTool.getRefValue(payload)); + final String objectName = payloadPath[payloadPath.length - 1]; + if (!antiLoopList.contains(objectName)) { + finalPayload = components.get("schemas/" + objectName); + antiLoopList.add(objectName); + } + } + if (!ApiTool.hasProperties(finalPayload)) { + throw new KLoadGenException("Wrong Payload for message "); + } + return new ArrayList<>(processPayload(finalPayload, "", components, antiLoopList)); + } + + private List processPayload(final JsonNode finalPayload, final String root, final Map components, final List antiLoopList) { + final var fieldList = new ArrayList(); + if (ApiTool.hasRef(finalPayload)) { + fieldList.addAll(processPayload(solveRef(finalPayload, components, antiLoopList, "schemas"), root, components, antiLoopList)); + } else if (ApiTool.hasAdditionalProperties(finalPayload)) { + fieldList.addAll(processMap(finalPayload, root, components, antiLoopList)); + } else { + for (Iterator> it = ApiTool.getProperties(finalPayload); it.hasNext();) { + final var property = it.next(); + final var propertyDef = property.getValue(); + if (ApiTool.hasRef(propertyDef)) { + final var solvedPayload = solveRef(propertyDef, components, antiLoopList, "schemas"); + if (Objects.nonNull(solvedPayload)) { + fieldList.addAll(processPayload(solvedPayload, calculateName(property.getKey(), root), components, antiLoopList)); + } + } else if (COMPLEX_TYPES.contains(ApiTool.getType(propertyDef)) || ApiTool.hasAdditionalProperties(propertyDef)) { + fieldList.addAll(calculatePayload(propertyDef, calculateName(property.getKey(), root), components, antiLoopList)); + } else { + fieldList.add(FieldValueMapping + .builder() + .fieldName(calculateName(property.getKey(), root)) + .fieldType(ApiTool.getType(propertyDef)) + .build()); + } + } + } + return fieldList; + } + + private List calculatePayload(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) { + final var fieldList = new ArrayList(); + if (!ApiTool.hasAdditionalProperties(propertyDef)) { + switch (ApiTool.getType(propertyDef)) { + case "object" -> fieldList.addAll(processPayload(propertyDef, root, components, antiLoopList)); + case "array" -> fieldList.addAll(processArray(propertyDef, root, components, antiLoopList)); + default -> { + } + } + } else { + fieldList.addAll(processMap(propertyDef, root, components, antiLoopList)); + } + return fieldList; + } + + private List processArray(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) { + final List fieldList = new ArrayList<>(); + + if (ApiTool.hasItems(propertyDef)) { + final var itemNode = ApiTool.getItems(propertyDef); + if (ApiTool.hasRef(itemNode)) { + fieldList.addAll(processPayload(itemNode, root + "[]", components, antiLoopList)); + } else { + switch (ApiTool.getType(itemNode)) { + case "object" -> fieldList.addAll(processPayload(itemNode, root + "[]", components, antiLoopList)); + case "string", "number", "integer", "boolean" -> fieldList.add(FieldValueMapping + .builder() + .fieldName(root + "[]") + .fieldType(ApiTool.getType(itemNode) + "-array") + .build()); + + default -> throw new KLoadGenException("Unexpected value: " + ApiTool.getType(itemNode)); + } + } + } else { + throw new KLoadGenException(String.format("Wrong Array Definition for %s", root)); + } + return fieldList; + } + + private List processMap(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) { + final List fieldList = new ArrayList<>(); + + if (ApiTool.hasAdditionalProperties(propertyDef)) { + final var itemNode = ApiTool.getAdditionalProperties(propertyDef); + + switch (ApiTool.getType(itemNode)) { + case "object" -> fieldList.addAll(processPayload(itemNode, root + "[:]", components, antiLoopList)); + case "string", "number", "integer", "boolean" -> fieldList.add(FieldValueMapping + .builder() + .fieldName(root + "[:]") + .fieldType(ApiTool.getType(itemNode) + "-map") + .build()); + default -> throw new KLoadGenException("Unexpected value: " + ApiTool.getType(itemNode)); + } + } else { + throw new KLoadGenException(String.format("Wrong Array Definition for %s", root)); + } + return fieldList; + } + + private String calculateName(final String propertyName, final String root) { + final String finalName; + if (StringUtils.isEmpty(root)) { + finalName = propertyName; + } else { + finalName = root + "." + propertyName; + } + return finalName; + } + private List nodeToApServer(final JsonNode node) { - var serverList = new ArrayList(); + final var serverList = new ArrayList(); node.fields().forEachRemaining(server -> serverList.add(mapNodeToServer(server.getKey(), server.getValue()))); return serverList; } + private JsonNode solveRef(final JsonNode message, final Map components, final List antiLoopList, final String schemaType) { + JsonNode payload = null; + final var payloadPath = MapperUtil.splitName(ApiTool.getRefValue(message)); + final var objectName = payloadPath[payloadPath.length - 1]; + if (!antiLoopList.contains(objectName)) { + payload = components.get(schemaType + "/" + objectName); + antiLoopList.add(objectName); + } + return payload; + } + private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode server) { - var builder = AsyncApiServer.builder(); + final var builder = AsyncApiServer.builder(); builder.name(serverName); builder.url(ApiTool.getNodeAsString(server, "url")); builder.protocol(ApiTool.getNodeAsString(server, "protocol")); @@ -73,17 +230,22 @@ private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode s } @Override - public List getBrokerData(final AsyncApiFile asyncApiFile) { + public final List getBrokerData(final AsyncApiFile asyncApiFile) { return asyncApiFile.getApiServerList(); } @Override - public List getSchemaRegistryData(final AsyncApiFile asyncApiFile) { + public final List getSchemaRegistryData(final AsyncApiFile asyncApiFile) { return asyncApiFile.getApiAsyncApiSRList(); } @Override - public AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile) { - return asyncApiFile.getApiSchemaList().get(0); + public final AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile, final String topic) { + return asyncApiFile.getApiSchemaList().get(topic); + } + + @Override + public final Map getSchemaDataMap(final AsyncApiFile asyncApiFile) { + return asyncApiFile.getApiSchemaList(); } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java index 7f73e420..f7047cbb 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -1,7 +1,7 @@ package com.sngular.kloadgen.extractor.model; import java.util.List; - +import java.util.Map; import lombok.Builder; import lombok.Value; @@ -13,5 +13,5 @@ public class AsyncApiFile { List apiAsyncApiSRList; - List apiSchemaList; + Map apiSchemaList; } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java index 11d26a24..dbe13e42 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java @@ -13,6 +13,6 @@ public class AsyncApiSR implements AsyncApiAbstract { @Override public Object[] getProperties() { - return new Object[0]; + return new Object[] {schemaRegistryUrl, schemaRegistryVendor}; } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java index 2f261028..810f1236 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java @@ -1,14 +1,13 @@ package com.sngular.kloadgen.extractor.model; import java.util.List; - import com.sngular.kloadgen.model.FieldValueMapping; import lombok.Builder; import lombok.Value; @Value @Builder -public class AsyncApiSchema { +public class AsyncApiSchema implements AsyncApiAbstract { String topicName; @@ -19,4 +18,9 @@ public class AsyncApiSchema { String schemaLookupStrategy; List model; + + @Override + public Object[] getProperties() { + return model.toArray(); + } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java index fca6f3bb..b7aeb98a 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java @@ -17,6 +17,6 @@ public class AsyncApiServer implements AsyncApiAbstract { @Override public Object[] getProperties() { - return new Object[0]; + return new Object[] {name, url, protocol, description}; } } From 55dcb940610119cc18f54ee2601eb6edc5b760d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 20 Sep 2023 00:30:50 +0200 Subject: [PATCH 12/55] get The Parser un and Running --- pom-maven-central.xml | 4 +- pom.xml | 21 +--------- .../config/asyncapi/AsyncApiConfigGui.java | 41 +++++++++++-------- .../extractor/model/AsyncApiSchema.java | 7 ++++ .../kloadgen/sampler/AsyncApiSampler.java | 2 +- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/pom-maven-central.xml b/pom-maven-central.xml index 99f802f9..6320419b 100644 --- a/pom-maven-central.xml +++ b/pom-maven-central.xml @@ -7,7 +7,7 @@ kloadgen - 5.6.5 + 5.7.0 KLoadGen Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial @@ -307,7 +307,7 @@ 4.4 3.12.0 2.8.6 - 31.0.1-jre + 32.0.0-jre 2.4.0-b180830.0359 11 provided diff --git a/pom.xml b/pom.xml index dc370f90..74286d73 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ kloadgen - 5.6.5 + 5.7.0 KLoadGen Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial @@ -317,17 +317,6 @@ - - org.apache.jmeter - jorphan - ${jmeter.version} - - - org.slf4j - slf4j-api - - - org.apache.kafka kafka-clients @@ -721,10 +710,6 @@ ${jmeter.version} provided - - org.apache.jmeter - jorphan - org.apache.logging.log4j log4j-slf4j-impl @@ -791,10 +776,6 @@ ApacheJMeter_java ${jmeter.version} - - org.apache.jmeter - jorphan - org.apache.logging.log4j log4j-slf4j-impl diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 5c4a52ef..450915c5 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -13,7 +13,6 @@ package com.sngular.kloadgen.config.asyncapi; import java.awt.BorderLayout; -import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; @@ -23,6 +22,13 @@ import java.util.List; import java.util.Objects; +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.sampler.AsyncApiSampler; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; @@ -35,13 +41,6 @@ import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; import javax.swing.table.DefaultTableModel; - -import com.sngular.kloadgen.extractor.ApiExtractor; -import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; -import com.sngular.kloadgen.sampler.AsyncApiSampler; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; @@ -167,6 +166,18 @@ private void fillTable(final DefaultTableModel sche } } + private void fillTable(final DefaultTableModel schemaFields, final Object[] schemaData) { + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + for (var data : schemaData) { + schemaFields.addRow(((FieldValueMapping) data).getProperties()); + } + } + } + private Object[] dataToRow(final T data) { return data.getProperties(); } @@ -219,21 +230,19 @@ private JPanel createRegistryTab() { private JPanel createSchemaTab() { final JPanel schemaTab = new JPanel(); - schemaTab.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + schemaTab.setLayout(new BorderLayout(5, 5)); topicComboBox = new JComboBox<>(); topicComboBox.setRenderer(new ApiSchemaRenderer()); + topicComboBox.addActionListener(this::topicComboActionListener); schemaTab.add(topicComboBox); schemaTab.add(new JTable(schemaFieldModel)); return schemaTab; } - private static Component getComponentProperty(final String property) { - return new Component() { - @Override - public String getName() { - return property; - } - }; + private void topicComboActionListener(final ActionEvent event) { + final JComboBox cb = (JComboBox)event.getSource(); + final var selectedSchema = (AsyncApiSchema) cb.getSelectedItem(); + fillTable(schemaFieldModel, selectedSchema.getProperties()); } @Override diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java index 810f1236..3537cd33 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java @@ -1,12 +1,14 @@ package com.sngular.kloadgen.extractor.model; import java.util.List; + import com.sngular.kloadgen.model.FieldValueMapping; import lombok.Builder; import lombok.Value; @Value @Builder + public class AsyncApiSchema implements AsyncApiAbstract { String topicName; @@ -23,4 +25,9 @@ public class AsyncApiSchema implements AsyncApiAbstract { public Object[] getProperties() { return model.toArray(); } + + @Override + public String toString() { + return topicName; + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 8c475714..9add0f2c 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -14,7 +14,7 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { @Override - public boolean applies(final ConfigTestElement configElement) { + public final boolean applies(final ConfigTestElement configElement) { return super.applies(configElement); } From 4f1ab29a8f52196c184cf8a06780d7c5987cfd13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Thu, 21 Sep 2023 21:16:38 +0200 Subject: [PATCH 13/55] #340 update dependencies --- .../config/asyncapi/ApiSchemaRenderer.java | 60 ++++++++-------- .../config/asyncapi/ApiServerRenderer.java | 49 ++++++------- .../config/asyncapi/AsyncApiConfigGui.java | 71 +++++++------------ .../asyncapi/AsyncApiExtractorImpl.java | 3 +- src/test/resources/asyncapi/event-api.yml | 51 +++++++++++++ 5 files changed, 133 insertions(+), 101 deletions(-) create mode 100644 src/test/resources/asyncapi/event-api.yml diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java index a7c5bb62..3d8b6475 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java @@ -2,12 +2,12 @@ import java.awt.Color; import java.awt.Component; +import java.util.Objects; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import javax.swing.JLabel; import javax.swing.JList; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; - public class ApiSchemaRenderer extends JLabel implements javax.swing.ListCellRenderer { protected ApiSchemaRenderer() { @@ -17,35 +17,35 @@ protected ApiSchemaRenderer() { @Override public final Component getListCellRendererComponent( final JList list, final AsyncApiSchema value, final int index, final boolean isSelected, final boolean cellHasFocus) { - - setText(value.toString()); - - final Color background; - final Color foreground; - - // check if this cell represents the current DnD drop location - final JList.DropLocation dropLocation = list.getDropLocation(); - if (dropLocation != null - && !dropLocation.isInsert() - && dropLocation.getIndex() == index) { - - background = Color.BLUE; - foreground = Color.WHITE; - - // check if this cell is selected - } else if (isSelected) { - background = Color.RED; - foreground = Color.WHITE; - - // unselected, and not the DnD drop location - } else { - background = Color.WHITE; - foreground = Color.BLACK; + if (Objects.nonNull(value)) { + setText(value.getTopicName()); + + final Color background; + final Color foreground; + + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + background = Color.BLUE; + foreground = Color.WHITE; + + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; + + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + + setBackground(background); + setForeground(foreground); } - - setBackground(background); - setForeground(foreground); - return this; } } diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java index 1d0126db..48d700de 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java @@ -2,12 +2,12 @@ import java.awt.Color; import java.awt.Component; +import java.util.Objects; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; import javax.swing.JLabel; import javax.swing.JList; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; - public class ApiServerRenderer extends JLabel implements javax.swing.ListCellRenderer { protected ApiServerRenderer() { @@ -18,34 +18,35 @@ protected ApiServerRenderer() { public final Component getListCellRendererComponent( final JList list, final AsyncApiServer value, final int index, final boolean isSelected, final boolean cellHasFocus) { - setText(value.toString()); + if (Objects.nonNull(value)) { + setText(value.getName()); - final Color background; - final Color foreground; + final Color background; + final Color foreground; - // check if this cell represents the current DnD drop location - final JList.DropLocation dropLocation = list.getDropLocation(); - if (dropLocation != null - && !dropLocation.isInsert() - && dropLocation.getIndex() == index) { + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { - background = Color.BLUE; - foreground = Color.WHITE; + background = Color.BLUE; + foreground = Color.WHITE; - // check if this cell is selected - } else if (isSelected) { - background = Color.RED; - foreground = Color.WHITE; + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; - // unselected, and not the DnD drop location - } else { - background = Color.WHITE; - foreground = Color.BLACK; - } - - setBackground(background); - setForeground(foreground); + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + setBackground(background); + setForeground(foreground); + } return this; } } diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java index 450915c5..8b83c95a 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java @@ -14,7 +14,6 @@ import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; @@ -22,6 +21,7 @@ import java.util.List; import java.util.Objects; +import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; @@ -34,7 +34,9 @@ import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextField; @@ -45,13 +47,9 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; -import org.apache.jorphan.logging.LoggingManager; -import org.apache.log.Logger; public final class AsyncApiConfigGui extends AbstractSamplerGui { - private static final Logger log = LoggingManager.getLoggerForClass(); - private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); private final ApiExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); @@ -93,7 +91,7 @@ private void init() { .createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); mainPanel.add(createAsyncApiFileSelectPanel(), BorderLayout.NORTH); - mainPanel.add(createAsyncApiTabs(), BorderLayout.SOUTH); + mainPanel.add(createAsyncApiTabs(), BorderLayout.CENTER); add(mainPanel); } @@ -146,13 +144,17 @@ public void actionFileChooser(final ActionEvent event) { final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); if (JFileChooser.APPROVE_OPTION == returnValue) { - final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); - asyncApiFileTextField.setText(apiFile.getAbsolutePath()); - final var asyncApiFile = asyncApiExtractor.processFile(apiFile); - asyncApiFile.getApiServerList().forEach(serverComboBox::addItem); - fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile)); - fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); - asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); + try { + final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(apiFile.getAbsolutePath()); + final var asyncApiFile = asyncApiExtractor.processFile(apiFile); + asyncApiFile.getApiServerList().forEach(serverComboBox::addItem); + fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile)); + fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); + asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); + } catch (KLoadGenException ex) { + JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); + } } } @@ -188,54 +190,31 @@ private JPanel createBrokerPanel() { brokerPanel.add(new JLabeledTextField("Broker Server")); serverComboBox = new JComboBox<>(); serverComboBox.setRenderer(new ApiServerRenderer()); - brokerPanel.add(serverComboBox); - brokerPanel.add(new JTable(brokerFieldModel), BorderLayout.CENTER); + brokerPanel.add(serverComboBox, BorderLayout.NORTH); + brokerPanel.add(new JScrollPane(new JTable(brokerFieldModel)), BorderLayout.CENTER); return brokerPanel; } private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); - registryUrlPanel.setLayout(new GridBagLayout()); - registryUrlPanel.setMinimumSize(new Dimension(45, 45)); - registryUrlPanel.setPreferredSize(new Dimension(800, 600)); - final JLabel label2 = new JLabel(); - label2.setText("Schema Registry URL"); - var gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - registryUrlPanel.add(label2, gridBagConstraints); + registryUrlPanel.setLayout(new BorderLayout(0, 0)); + registryUrlPanel.add(new JLabeledTextField("Schema Registry URL")); this.registryUrl = new JTextField(); this.registryUrl.setPreferredSize(new Dimension(249, 30)); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - registryUrlPanel.add(this.registryUrl, gridBagConstraints); - final JPanel panel5 = new JPanel(); - panel5.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = GridBagConstraints.BOTH; - registryUrlPanel.add(panel5, gridBagConstraints); - final JLabel label3 = new JLabel(); - label3.setText("Security Options"); - panel5.add(label3); - panel5.add(new JTable(schemaRegistryFieldModel)); + registryUrlPanel.add(this.registryUrl, BorderLayout.NORTH); + registryUrlPanel.add(new JScrollPane(new JTable(schemaRegistryFieldModel)), BorderLayout.CENTER); return registryUrlPanel; } private JPanel createSchemaTab() { final JPanel schemaTab = new JPanel(); - schemaTab.setLayout(new BorderLayout(5, 5)); + schemaTab.setLayout(new BorderLayout(0, 0)); + schemaTab.add(new JLabeledTextField("Schema Configuration")); topicComboBox = new JComboBox<>(); topicComboBox.setRenderer(new ApiSchemaRenderer()); topicComboBox.addActionListener(this::topicComboActionListener); - schemaTab.add(topicComboBox); - schemaTab.add(new JTable(schemaFieldModel)); + schemaTab.add(topicComboBox, BorderLayout.NORTH); + schemaTab.add(new JScrollPane(new JTable(schemaFieldModel)), BorderLayout.CENTER); return schemaTab; } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index bee725fe..67574bc8 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -10,6 +10,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -78,7 +79,7 @@ private AsyncApiSchema mapNodeToSchema(final Map components, f private List messageToFieldList(final JsonNode message, final Map components, final List antiLoopList) { var payload = ApiTool.getNode(message, "payload"); if (ApiTool.hasRef(message)) { - payload = solveRef(message, components, antiLoopList, "messages"); + payload = ApiTool.getNode(solveRef(message, components, antiLoopList, "messages"), "payload"); } else if (!ApiTool.hasNode(message, "payload")) { throw new KLoadGenException("AsyncApi format still not supported"); } diff --git a/src/test/resources/asyncapi/event-api.yml b/src/test/resources/asyncapi/event-api.yml new file mode 100644 index 00000000..de1ebf2f --- /dev/null +++ b/src/test/resources/asyncapi/event-api.yml @@ -0,0 +1,51 @@ +asyncapi: 2.0.0 +info: + title: Email Service + version: '1.0.0' + description: | + Sends emails upon certain events + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + +servers: + production: + url: mqtt://test.mosquitto.org + protocol: mqtt + description: Test MQTT broker + +channels: + user/signedup: + publish: + operationId: onUserSignUp + message: + $ref : '#/components/messages/UserSignedUp' + +components: + messages: + UserSignedUp: + name: userSignedUp + title: User signed up event + summary: Inform about a new user registration in the system + contentType: application/json + payload: + $ref: '#/components/schemas/userSignedUpPayload' + + schemas: + userSignedUpPayload: + type: object + properties: + firstName: + type: string + description: "foo" + lastName: + type: string + description: "bar" + email: + type: string + format: email + description: "baz" + createdAt: + type: string + format: date-time + description: "foo" \ No newline at end of file From 0e429ef679a7b936ed26915244fc5023ce125c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 4 Oct 2023 09:18:55 +0200 Subject: [PATCH 14/55] #332 Fix styles and pom version --- .github/workflows/maven-central-push.yml | 4 +- .github/workflows/maven-pr.yml | 4 +- .../kloadgen/sampler/SamplerUtilTest.java | 210 +++++++++--------- .../serializer/AvroDeserializerTest.java | 64 +++--- 4 files changed, 134 insertions(+), 148 deletions(-) diff --git a/.github/workflows/maven-central-push.yml b/.github/workflows/maven-central-push.yml index b2665d60..3564e316 100644 --- a/.github/workflows/maven-central-push.yml +++ b/.github/workflows/maven-central-push.yml @@ -25,10 +25,10 @@ jobs: with: ref: ${{ github.event.pull_request.head.ref }} - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v2 with: - java-version: "11" + java-version: "17" distribution: "adopt" server-id: ossrh server-username: MAVEN_USERNAME diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index 2b2873ea..0b3ba30a 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -36,10 +36,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v2 with: - java-version: "11" + java-version: "17" distribution: "adopt" - name: Build with Maven run: mvn -B package --file pom.xml diff --git a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java index c2a823a6..8d1dea60 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java @@ -6,8 +6,6 @@ package com.sngular.kloadgen.sampler; -import static com.sngular.kloadgen.serializer.SerializerTestFixture.createFieldValueMapping; - import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -15,9 +13,9 @@ import java.util.Properties; import java.util.stream.Stream; -import com.sngular.kloadgen.extractor.SchemaExtractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; +import com.sngular.kloadgen.serializer.SerializerTestFixture; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.PropsKeysHelper; @@ -34,112 +32,112 @@ class SamplerUtilTest { - - private JMeterContext jmcx; - - private final FileHelper fileHelper = new FileHelper(); - - private final SchemaExtractor extractor = new SchemaExtractor(); - - private static Stream parametersForConfigureValueGeneratorTest() { - return Stream.of("localhost:8081", ""); - } - - private static Stream parametersForConfigureKeyGeneratorTest() { - return Stream.of("avro", "json","protobuf"); - } - - @BeforeEach - public final void setUp() throws IOException { - final File file = new File("src/test/resources"); - final String absolutePath = file.getAbsolutePath(); - JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); - jmcx = JMeterContextService.getContext(); - jmcx.setVariables(new JMeterVariables()); - JMeterUtils.setLocale(Locale.ENGLISH); - } - - public JMeterVariables getVariablesAvro() throws IOException { - final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); - var variables = new JMeterVariables(); - variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "avro"); - variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "test"); - variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "test"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); - variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( - FieldValueMapping.builder().fieldName("subEntity.anotherLevel.subEntityIntArray[2]").fieldType("int-array").valueLength(0).fieldValueList("[1]").required(true) - .isAncestorRequired(true).build(), - FieldValueMapping.builder().fieldName("topLevelIntArray[3]").fieldType("int-array").valueLength(0).fieldValueList("[2]").required(true).isAncestorRequired(true).build()) - ); - return variables; + private final FileHelper fileHelper = new FileHelper(); + + private JMeterContext jmcx; + + private static Stream parametersForConfigureValueGeneratorTest() { + return Stream.of("localhost:8081", ""); + } + + private static Stream parametersForConfigureKeyGeneratorTest() { + return Stream.of("avro", "json", "protobuf"); + } + + @BeforeEach + public final void setUp() throws IOException { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + } + + @ParameterizedTest + @MethodSource("parametersForConfigureValueGeneratorTest") + void configureValueGeneratorTest(final String jmeterProps) throws IOException { + final Properties props = new Properties(); + props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, jmeterProps); + jmcx.setVariables(getVariablesAvro()); + final var generator = SamplerUtil.configureValueGenerator(props); + Assertions.assertThat(generator.nextMessage()).isNotNull(); + } + + public JMeterVariables getVariablesAvro() throws IOException { + final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); + final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final var variables = new JMeterVariables(); + variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "avro"); + variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "test"); + variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "test"); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( + FieldValueMapping.builder().fieldName("subEntity.anotherLevel.subEntityIntArray[2]").fieldType("int-array").valueLength(0).fieldValueList("[1]").required(true) + .isAncestorRequired(true).build(), + FieldValueMapping.builder().fieldName("topLevelIntArray[3]").fieldType("int-array").valueLength(0).fieldValueList("[2]").required(true).isAncestorRequired(true).build()) + ); + return variables; + } + + @ParameterizedTest + @MethodSource("parametersForConfigureKeyGeneratorTest") + void configureKeyGeneratorTest(final String jmeterProps) throws IOException { + final Properties props = new Properties(); + props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, "localhost:8081"); + props.put(PropsKeysHelper.KEY_SCHEMA_TYPE, jmeterProps); + + if ("json".equalsIgnoreCase(jmeterProps)) { + jmcx.setVariables(getVariablesJsonSchema()); } - - public JMeterVariables getVariablesProtobuf() throws IOException { - - final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF"); - var variables = new JMeterVariables(); - variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "protobuf"); - variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "protobufSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "protobufSubject"); - variables.putObject(PropsKeysHelper.KEY_SCHEMA_PROPERTIES, Arrays.asList( - createFieldValueMapping("street", "string"), - createFieldValueMapping("number[]", "int-array"), - createFieldValueMapping("zipcode", "long"))); - variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( - createFieldValueMapping("street", "string"), - createFieldValueMapping("number[]", "int-array"), - createFieldValueMapping("zipcode", "long"))); - return variables; - } - - public JMeterVariables getVariablesJsonSchema() throws IOException { - - final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); - - var variables = new JMeterVariables(); - variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); - variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); - variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA); - return variables; + if ("avro".equalsIgnoreCase(jmeterProps)) { + jmcx.setVariables(getVariablesAvro()); } - - @ParameterizedTest - @MethodSource("parametersForConfigureValueGeneratorTest") - void configureValueGeneratorTest(String jmeterProps) throws IOException { - Properties props = new Properties(); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, jmeterProps); - jmcx.setVariables(getVariablesAvro()); - var generator = SamplerUtil.configureValueGenerator(props); - Assertions.assertThat(generator.nextMessage()).isNotNull(); + if ("protobuf".equalsIgnoreCase(jmeterProps)) { + jmcx.setVariables(getVariablesProtobuf()); } - @ParameterizedTest - @MethodSource("parametersForConfigureKeyGeneratorTest") - void configureKeyGeneratorTest(String jmeterProps) throws IOException { - Properties props = new Properties(); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, "localhost:8081"); - props.put(PropsKeysHelper.KEY_SCHEMA_TYPE, jmeterProps); - - if (jmeterProps.equalsIgnoreCase("json")) - jmcx.setVariables(getVariablesJsonSchema()); - if (jmeterProps.equalsIgnoreCase("avro")) - jmcx.setVariables(getVariablesAvro()); - if (jmeterProps.equalsIgnoreCase("protobuf")) - jmcx.setVariables(getVariablesProtobuf()); - - var generator = SamplerUtil.configureKeyGenerator(props); - Assertions.assertThat(generator.nextMessage()).isNotNull(); - - - } + final var generator = SamplerUtil.configureKeyGenerator(props); + Assertions.assertThat(generator.nextMessage()).isNotNull(); + + + } + + public JMeterVariables getVariablesJsonSchema() throws IOException { + + final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); + final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); + + final var variables = new JMeterVariables(); + variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); + variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA); + return variables; + } + + public JMeterVariables getVariablesProtobuf() throws IOException { + + final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); + final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF"); + final var variables = new JMeterVariables(); + variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "protobuf"); + variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "protobufSubject"); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "protobufSubject"); + variables.putObject(PropsKeysHelper.KEY_SCHEMA_PROPERTIES, Arrays.asList( + SerializerTestFixture.createFieldValueMapping("street", "string"), + SerializerTestFixture.createFieldValueMapping("number[]", "int-array"), + SerializerTestFixture.createFieldValueMapping("zipcode", "long"))); + variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( + SerializerTestFixture.createFieldValueMapping("street", "string"), + SerializerTestFixture.createFieldValueMapping("number[]", "int-array"), + SerializerTestFixture.createFieldValueMapping("zipcode", "long"))); + return variables; + } } diff --git a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java index d2680ab2..057bc851 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java @@ -1,17 +1,5 @@ package com.sngular.kloadgen.serializer; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_FILE_ISSUE; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_ISSUE; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_LOGICAL_TYPES; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_MAP; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_NULL_ON_OPTIONAL_FIELDS; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_OPTIONAL_ENUM; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_OPTIONAL_MAP; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_SUBENTITY_ARRAY; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_UNION_RECORD; -import static com.sngular.kloadgen.serializer.AvroSerializersTestFixture.TEST_USER; -import static com.sngular.kloadgen.serializer.SerializerTestFixture.readSchema; - import java.io.File; import java.util.List; import java.util.Map; @@ -52,39 +40,39 @@ void setUp() { private static Stream getSchemaToTest() { - Builder builder = Stream.builder(); - - File testSubentityArrayFile = TEST_SUBENTITY_ARRAY.getFirst(); - builder.add(Arguments.arguments(Named.of(testSubentityArrayFile.getName(), testSubentityArrayFile), TEST_SUBENTITY_ARRAY.getSecond())); - File testIssueFile = TEST_ISSUE.getFirst(); - builder.add(Arguments.arguments(Named.of(testIssueFile.getName(), testIssueFile), TEST_ISSUE.getSecond())); - File testOptionalEnumFile = TEST_OPTIONAL_ENUM.getFirst(); - builder.add(Arguments.arguments(Named.of(testOptionalEnumFile.getName(), testOptionalEnumFile), TEST_OPTIONAL_ENUM.getSecond())); - File testFileIssueFile = TEST_FILE_ISSUE.getFirst(); - builder.add(Arguments.arguments(Named.of(testFileIssueFile.getName(), testFileIssueFile), TEST_FILE_ISSUE.getSecond())); - File testLogicalTypesFile = TEST_LOGICAL_TYPES.getFirst(); - builder.add(Arguments.arguments(Named.of(testLogicalTypesFile.getName(), testLogicalTypesFile), TEST_LOGICAL_TYPES.getSecond())); - File testMapFile = TEST_MAP.getFirst(); - builder.add(Arguments.arguments(Named.of(testMapFile.getName(), testMapFile), TEST_MAP.getSecond())); - File testNullOnOptionalFieldsFile = TEST_NULL_ON_OPTIONAL_FIELDS.getFirst(); + final Builder builder = Stream.builder(); + + final File testSubentityArrayFile = AvroSerializersTestFixture.TEST_SUBENTITY_ARRAY.getFirst(); + builder.add(Arguments.arguments(Named.of(testSubentityArrayFile.getName(), testSubentityArrayFile), AvroSerializersTestFixture.TEST_SUBENTITY_ARRAY.getSecond())); + final File testIssueFile = AvroSerializersTestFixture.TEST_ISSUE.getFirst(); + builder.add(Arguments.arguments(Named.of(testIssueFile.getName(), testIssueFile), AvroSerializersTestFixture.TEST_ISSUE.getSecond())); + final File testOptionalEnumFile = AvroSerializersTestFixture.TEST_OPTIONAL_ENUM.getFirst(); + builder.add(Arguments.arguments(Named.of(testOptionalEnumFile.getName(), testOptionalEnumFile), AvroSerializersTestFixture.TEST_OPTIONAL_ENUM.getSecond())); + final File testFileIssueFile = AvroSerializersTestFixture.TEST_FILE_ISSUE.getFirst(); + builder.add(Arguments.arguments(Named.of(testFileIssueFile.getName(), testFileIssueFile), AvroSerializersTestFixture.TEST_FILE_ISSUE.getSecond())); + final File testLogicalTypesFile = AvroSerializersTestFixture.TEST_LOGICAL_TYPES.getFirst(); + builder.add(Arguments.arguments(Named.of(testLogicalTypesFile.getName(), testLogicalTypesFile), AvroSerializersTestFixture.TEST_LOGICAL_TYPES.getSecond())); + final File testMapFile = AvroSerializersTestFixture.TEST_MAP.getFirst(); + builder.add(Arguments.arguments(Named.of(testMapFile.getName(), testMapFile), AvroSerializersTestFixture.TEST_MAP.getSecond())); + final File testNullOnOptionalFieldsFile = AvroSerializersTestFixture.TEST_NULL_ON_OPTIONAL_FIELDS.getFirst(); builder.add( - Arguments.arguments(Named.of(testNullOnOptionalFieldsFile.getName(), testNullOnOptionalFieldsFile), TEST_NULL_ON_OPTIONAL_FIELDS.getSecond())); - File testOptionalMapFile = TEST_OPTIONAL_MAP.getFirst(); - builder.add(Arguments.arguments(Named.of(testOptionalMapFile.getName(), testOptionalMapFile), TEST_OPTIONAL_MAP.getSecond())); - File testNullOnOptionalFields = TEST_NULL_ON_OPTIONAL_FIELDS.getFirst(); - builder.add(Arguments.arguments(Named.of(testNullOnOptionalFields.getName(), testNullOnOptionalFields), TEST_NULL_ON_OPTIONAL_FIELDS.getSecond())); - File testUnionRecordFile = TEST_UNION_RECORD.getFirst(); - builder.add(Arguments.arguments(Named.of(testUnionRecordFile.getName(), testUnionRecordFile), TEST_UNION_RECORD.getSecond())); - File testUserFile = TEST_USER.getFirst(); - builder.add(Arguments.arguments(Named.of(testUserFile.getName(), testUserFile), TEST_USER.getSecond())); + Arguments.arguments(Named.of(testNullOnOptionalFieldsFile.getName(), testNullOnOptionalFieldsFile), AvroSerializersTestFixture.TEST_NULL_ON_OPTIONAL_FIELDS.getSecond())); + final File testOptionalMapFile = AvroSerializersTestFixture.TEST_OPTIONAL_MAP.getFirst(); + builder.add(Arguments.arguments(Named.of(testOptionalMapFile.getName(), testOptionalMapFile), AvroSerializersTestFixture.TEST_OPTIONAL_MAP.getSecond())); + final File testNullOnOptionalFields = AvroSerializersTestFixture.TEST_NULL_ON_OPTIONAL_FIELDS.getFirst(); + builder.add(Arguments.arguments(Named.of(testNullOnOptionalFields.getName(), testNullOnOptionalFields), AvroSerializersTestFixture.TEST_NULL_ON_OPTIONAL_FIELDS.getSecond())); + final File testUnionRecordFile = AvroSerializersTestFixture.TEST_UNION_RECORD.getFirst(); + builder.add(Arguments.arguments(Named.of(testUnionRecordFile.getName(), testUnionRecordFile), AvroSerializersTestFixture.TEST_UNION_RECORD.getSecond())); + final File testUserFile = AvroSerializersTestFixture.TEST_USER.getFirst(); + builder.add(Arguments.arguments(Named.of(testUserFile.getName(), testUserFile), AvroSerializersTestFixture.TEST_USER.getSecond())); return builder.build(); } @ParameterizedTest @MethodSource("getSchemaToTest") - void deserialize(File schemaFile, List fieldValueMappings) throws Exception { - final var schemaStr = readSchema(schemaFile); + void deserialize(final File schemaFile, final List fieldValueMappings) throws Exception { + final var schemaStr = SerializerTestFixture.readSchema(schemaFile); final BaseSchemaMetadata confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, From a8de0fc21039c27850c2c76bc2fe4c641be0bfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 4 Oct 2023 09:22:58 +0200 Subject: [PATCH 15/55] #332 Fix styles and pom version --- .../com/sngular/kloadgen/serializer/AvroDeserializerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java index 057bc851..4fbf94b8 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java @@ -6,6 +6,8 @@ import java.util.stream.Stream; import java.util.stream.Stream.Builder; +import javax.xml.bind.DatatypeConverter; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.processor.SchemaProcessor; @@ -14,7 +16,6 @@ import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.PropsKeysHelper; import io.confluent.kafka.schemaregistry.ParsedSchema; -import javax.xml.bind.DatatypeConverter; import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; From 82d1d4e6672ee5bf27bfab3901b428667d3e690c Mon Sep 17 00:00:00 2001 From: Jose Enrique Garcia Date: Mon, 9 Oct 2023 16:11:03 +0200 Subject: [PATCH 16/55] Add Async Api GUI --- .../kloadgen/extractor/ApiExtractor.java | 10 +- .../asyncapi/AsyncApiExtractorImpl.java | 28 ++- .../extractor/model/AsyncApiAbstract.java | 7 + .../extractor/model/AsyncApiFile.java | 7 +- .../kloadgen/extractor/model/AsyncApiSR.java | 14 +- .../extractor/model/AsyncApiServer.java | 7 + .../kloadgen/sampler/AsyncApiSampler.java | 138 +++++++++++++- .../sampler/KafkaProducerSampler.java | 28 ++- .../sngular/kloadgen/sampler/SamplerUtil.java | 68 +++---- .../gui}/ApiSchemaRenderer.java | 12 +- .../gui}/ApiServerRenderer.java | 12 +- .../sampler/gui/AsyncApiSRRenderer.java | 49 +++++ .../gui/AsyncApiSamplerGui.java} | 172 ++++++++++-------- 13 files changed, 366 insertions(+), 186 deletions(-) rename src/main/java/com/sngular/kloadgen/{config/asyncapi => sampler/gui}/ApiSchemaRenderer.java (89%) rename src/main/java/com/sngular/kloadgen/{config/asyncapi => sampler/gui}/ApiServerRenderer.java (89%) create mode 100644 src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java rename src/main/java/com/sngular/kloadgen/{config/asyncapi/AsyncApiConfigGui.java => sampler/gui/AsyncApiSamplerGui.java} (75%) diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java index 9984498d..76496ecd 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -1,22 +1,24 @@ package com.sngular.kloadgen.extractor; -import java.io.File; -import java.util.List; -import java.util.Map; import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import java.io.File; +import java.util.List; +import java.util.Map; + public interface ApiExtractor { AsyncApiFile processFile(final File apiFile); - List getBrokerData(final AsyncApiFile asyncApiFile); + Map getBrokerData(final AsyncApiFile asyncApiFile); List getSchemaRegistryData(final AsyncApiFile asyncApiFile); AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile, final String topic); Map getSchemaDataMap(final AsyncApiFile asyncApiFile); + } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 67574bc8..1d37c965 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -1,16 +1,5 @@ package com.sngular.kloadgen.extractor.asyncapi; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -25,6 +14,11 @@ import com.sngular.kloadgen.model.FieldValueMapping; import org.apache.commons.lang3.StringUtils; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + public class AsyncApiExtractorImpl implements ApiExtractor { private static final Set COMPLEX_TYPES = Set.of("record", "array"); @@ -41,7 +35,7 @@ public final AsyncApiFile processFile(final File apiFile) { final var builder = AsyncApiFile.builder(); try { final JsonNode openApi = om.readTree(apiFile); - builder.apiServerList(nodeToApServer(ApiTool.getNode(openApi, SERVERS))); + builder.apiServerMap(nodeToApServer(ApiTool.getNode(openApi, SERVERS))); builder.apiSchemaList(nodeToSchema(openApi)); } catch (final IOException e) { throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e); @@ -204,9 +198,9 @@ private String calculateName(final String propertyName, final String root) { return finalName; } - private List nodeToApServer(final JsonNode node) { - final var serverList = new ArrayList(); - node.fields().forEachRemaining(server -> serverList.add(mapNodeToServer(server.getKey(), server.getValue()))); + private Map nodeToApServer(final JsonNode node) { + final var serverList = new HashMap(); + node.fields().forEachRemaining(server -> serverList.put(server.getKey(), mapNodeToServer(server.getKey(), server.getValue()))); return serverList; } @@ -231,8 +225,8 @@ private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode s } @Override - public final List getBrokerData(final AsyncApiFile asyncApiFile) { - return asyncApiFile.getApiServerList(); + public final Map getBrokerData(final AsyncApiFile asyncApiFile) { + return asyncApiFile.getApiServerMap(); } @Override diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java index 6375a653..30a4a9c8 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java @@ -1,7 +1,14 @@ package com.sngular.kloadgen.extractor.model; +import java.util.Collections; +import java.util.Map; + public interface AsyncApiAbstract { Object[] getProperties(); + default Map getPropertiesMap() { + return Collections.emptyMap(); + } + } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java index f7047cbb..4bbcf7af 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -1,15 +1,16 @@ package com.sngular.kloadgen.extractor.model; -import java.util.List; -import java.util.Map; import lombok.Builder; import lombok.Value; +import java.util.List; +import java.util.Map; + @Value @Builder public class AsyncApiFile { - List apiServerList; + Map apiServerMap; List apiAsyncApiSRList; diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java index dbe13e42..7b27be36 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java @@ -1,18 +1,10 @@ package com.sngular.kloadgen.extractor.model; -import lombok.Data; -import lombok.Value; - -@Value -@Data -public class AsyncApiSR implements AsyncApiAbstract { - - String schemaRegistryUrl; - - String schemaRegistryVendor; +public record AsyncApiSR(String name, String schemaRegistryUrl, + String schemaRegistryVendor) implements AsyncApiAbstract { @Override public Object[] getProperties() { - return new Object[] {schemaRegistryUrl, schemaRegistryVendor}; + return new Object[]{schemaRegistryUrl, schemaRegistryVendor}; } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java index b7aeb98a..d4868889 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java @@ -3,6 +3,8 @@ import lombok.Builder; import lombok.Value; +import java.util.Map; + @Value @Builder public class AsyncApiServer implements AsyncApiAbstract { @@ -19,4 +21,9 @@ public class AsyncApiServer implements AsyncApiAbstract { public Object[] getProperties() { return new Object[] {name, url, protocol, description}; } + + @Override + public Map getPropertiesMap() { + return Map.of("name", name, "url", url, "protocol", protocol); + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 9add0f2c..1944c6f2 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -1,25 +1,149 @@ package com.sngular.kloadgen.sampler; -import java.io.Serializable; - -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.loadgen.BaseLoadGenerator; +import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; +import com.sngular.kloadgen.serializer.EnrichedRecord; +import com.sngular.kloadgen.util.ProducerKeysHelper; +import lombok.Getter; +import lombok.Setter; import org.apache.jmeter.config.ConfigTestElement; import org.apache.jmeter.samplers.AbstractSampler; import org.apache.jmeter.samplers.Entry; import org.apache.jmeter.samplers.SampleResult; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -@Slf4j -@NoArgsConstructor +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + +@Getter +@Setter public class AsyncApiSampler extends AbstractSampler implements Serializable { + private static final Logger LOG = LoggerFactory.getLogger(AsyncApiSampler.class); + + private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; + + private transient AsyncApiFile asyncApiFile; + + private transient ApiExtractor apiExtractor; + + private String asyncApiFileStr; + + private String asyncApiServerName; + + private String asyncApiSchemaName; + + private transient BaseLoadGenerator generator; + + private transient final ObjectMapper mapper = new ObjectMapper(); + + public AsyncApiSampler() { + apiExtractor = new AsyncApiExtractorImpl(); + } + @Override public final boolean applies(final ConfigTestElement configElement) { + + generator = new JsonSRLoadGenerator(); return super.applies(configElement); } @Override public SampleResult sample(final Entry entry) { - return null; + + final var sampleResult = new SampleResult(); + try (final KafkaProducer producer = new KafkaProducer<>(extractProps(asyncApiServerName))) { + final var messageVal = generator.nextMessage(); + if (Objects.nonNull(messageVal)) { + final var producerRecord = getProducerRecord(messageVal, enrichedKeyFlag(), enrichedValueFlag()); + fillSamplerResult(producerRecord, sampleResult); + final var result = producer.send(producerRecord, (metadata, e) -> { + if (e != null) { + LOG.error("Send failed for record {}", producerRecord, e); + throw new KLoadGenException("Failed to sent message due ", e); + } + }); + fillSampleResult(sampleResult, prettyPrint(result.get()), true); + } else { + LOG.error("Failed to Generate message"); + fillSampleResult(sampleResult, "Failed to Generate message", false); + } + } catch (final KLoadGenException | InterruptedException | ExecutionException e) { + LOG.error("Failed to send message", e); + fillSampleResult(sampleResult, e.getMessage() != null ? e.getMessage() : "", false); + } + sampleResult.sampleStart(); + + return sampleResult; + } + + private Map extractProps(String asyncApiServerName) { + final var properties = new HashMap(); + final var asyncApiBrokerProps = apiExtractor.getBrokerData(asyncApiFile).get(asyncApiServerName).getPropertiesMap(); + SamplerUtil.getCommonProducerDefaultParameters().forEach(property -> + properties.put(property.getName(), property.getStringValue())); + properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, asyncApiBrokerProps.get("url")); + properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "GenericJsonRecordSerializer.class"); + properties.put(ProducerKeysHelper.KAFKA_TOPIC_CONFIG, asyncApiSchemaName); + return properties; + } + + public String getAsyncApiFileStr() throws JsonProcessingException { + return mapper.writeValueAsString(asyncApiFileStr); + } + + public void setAsyncApiFileStr(String asyncApiFileStr) throws IOException { + this.asyncApiFileStr = asyncApiFileStr; + this.asyncApiFile = mapper.createParser(asyncApiFileStr).readValueAs(AsyncApiFile.class); + } + + private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean keyFlag, final boolean valueFlag) { + final ProducerRecord producerRecord; + producerRecord = new ProducerRecord<>(asyncApiSchemaName, getObject(messageVal, valueFlag)); + return producerRecord; + } + + private Boolean enrichedKeyFlag() { + return false; + } + + private Boolean enrichedValueFlag() { + return false; + } + + private void fillSamplerResult(final ProducerRecord producerRecord, final SampleResult sampleResult) { + String result = "key: " + producerRecord.key() + + ", payload: " + producerRecord.value(); + sampleResult.setSamplerData(result); + } + + private void fillSampleResult(final SampleResult sampleResult, final String responseData, final boolean successful) { + sampleResult.setResponseData(responseData, StandardCharsets.UTF_8.name()); + sampleResult.setSuccessful(successful); + sampleResult.sampleEnd(); + } + + private String prettyPrint(final RecordMetadata recordMetadata) { + return String.format(TEMPLATE, recordMetadata.topic(), recordMetadata.partition(), recordMetadata.offset()); + } + + private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { + return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java index 16e78dfa..0318d5db 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java @@ -6,16 +6,6 @@ package com.sngular.kloadgen.sampler; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ExecutionException; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.model.HeaderMapping; @@ -43,6 +33,11 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.serialization.StringSerializer; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ExecutionException; + public final class KafkaProducerSampler extends AbstractJavaSamplerClient implements Serializable { private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; @@ -75,8 +70,8 @@ public void setupTest(final JavaSamplerContext context) { generator = SamplerUtil.configureValueGenerator(props); - if ("true".equals(context.getJMeterVariables().get(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY)) - || "true".equals(context.getJMeterVariables().get(PropsKeysHelper.SIMPLE_KEYED_MESSAGE_KEY))) { + if ("true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY)) + || "true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SIMPLE_KEYED_MESSAGE_KEY))) { keyMessageFlag = true; if (!Objects.isNull(JMeterContextService.getContext().getVariables().get(PropsKeysHelper.KEY_SUBJECT_NAME))) { keyGenerator = SamplerUtil.configureKeyGenerator(props); @@ -135,7 +130,7 @@ public void teardownTest(final JavaSamplerContext context) { @Override public Arguments getDefaultParameters() { - return SamplerUtil.getCommonDefaultParameters(); + return SamplerUtil.getCommonProducerDefaultParameters(); } @Override @@ -209,10 +204,9 @@ private Boolean enrichedValueFlag() { } private void fillSamplerResult(final ProducerRecord producerRecord, final SampleResult sampleResult) { - final StringBuilder result = new StringBuilder(); - result.append("key: ").append(producerRecord.key()) - .append(", payload: ").append(producerRecord.value()); - sampleResult.setSamplerData(result.toString()); + String result = "key: " + producerRecord.key() + + ", payload: " + producerRecord.value(); + sampleResult.setSamplerData(result); } private void fillSampleResult(final SampleResult sampleResult, final String respondeData, final boolean successful) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index cabb59cc..8b78c86d 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -6,18 +6,6 @@ package com.sngular.kloadgen.sampler; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.AvroSRLoadGenerator; @@ -48,6 +36,10 @@ import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.common.security.auth.SecurityProtocol; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.*; + public final class SamplerUtil { private static final StatelessGeneratorTool STATELESS_GENERATOR_TOOL = new StatelessGeneratorTool(); @@ -58,7 +50,7 @@ private SamplerUtil() { } @SuppressWarnings("checkstyle:ExecutableStatementCount") - public static Arguments getCommonDefaultParameters() { + public static Arguments getCommonProducerDefaultParameters() { final Arguments defaultParameters = new Arguments(); defaultParameters.addArgument(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, ProducerKeysHelper.BOOTSTRAP_SERVERS_CONFIG_DEFAULT); defaultParameters.addArgument(ProducerKeysHelper.ZOOKEEPER_SERVERS, ProducerKeysHelper.ZOOKEEPER_SERVERS_DEFAULT); @@ -101,15 +93,15 @@ public static Properties setupCommonProperties(final JavaSamplerContext context) final Properties props = new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, context.getParameter(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)); - if ("true".equals(context.getJMeterVariables().get(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY))) { - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, context.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); - } else if ("true".equals(context.getJMeterVariables().get(PropsKeysHelper.SIMPLE_KEYED_MESSAGE_KEY))) { - props.put(PropsKeysHelper.MESSAGE_KEY_KEY_TYPE, context.getJMeterVariables().get(PropsKeysHelper.KEY_TYPE)); - props.put(PropsKeysHelper.MESSAGE_KEY_KEY_VALUE, context.getJMeterVariables().get(PropsKeysHelper.KEY_VALUE)); - if (Objects.nonNull(context.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE))) { - props.put(PropsKeysHelper.KEY_SCHEMA_TYPE, context.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE)); + if ("true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY))) { + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); + } else if ("true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SIMPLE_KEYED_MESSAGE_KEY))) { + props.put(PropsKeysHelper.MESSAGE_KEY_KEY_TYPE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_TYPE)); + props.put(PropsKeysHelper.MESSAGE_KEY_KEY_VALUE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_VALUE)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE))) { + props.put(PropsKeysHelper.KEY_SCHEMA_TYPE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE)); } - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, context.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); } else { props.put(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY, Boolean.FALSE); } @@ -128,15 +120,15 @@ public static Properties setupCommonProperties(final JavaSamplerContext context) props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, context.getParameter(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG)); props.put(ProducerKeysHelper.SASL_MECHANISM, context.getParameter(ProducerKeysHelper.SASL_MECHANISM)); - final String schemaRegistryNameValue = context.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); + final String schemaRegistryNameValue = JavaSamplerContext.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); final String enableSchemaRegistrationValue = context.getParameter(SchemaRegistryKeyHelper.ENABLE_AUTO_SCHEMA_REGISTRATION_CONFIG); if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_APICURIO.equalsIgnoreCase(schemaRegistryNameValue)) { props.put(SerdeConfig.AUTO_REGISTER_ARTIFACT, enableSchemaRegistrationValue); - props.put(SchemaResolverConfig.REGISTRY_URL, context.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, context.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); + props.put(SchemaResolverConfig.REGISTRY_URL, JavaSamplerContext.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); + props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, JavaSamplerContext.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); } else { props.put(SchemaRegistryKeyHelper.ENABLE_AUTO_SCHEMA_REGISTRATION_CONFIG, enableSchemaRegistrationValue); - final String schemaRegistryURL = context.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL); + final String schemaRegistryURL = JavaSamplerContext.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL); if (StringUtils.isNotBlank(schemaRegistryURL)) { props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, schemaRegistryURL); } @@ -206,13 +198,13 @@ public static Arguments getCommonConsumerDefaultParameters() { } public static void setupConsumerDeserializerProperties(final JavaSamplerContext context, final Properties props) { - if (Objects.nonNull(context.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY))) { - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, context.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY))) { + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY)); } else { props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); } - if (Objects.nonNull(context.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY))) { - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, context.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY))) { + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY)); } else { props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); } @@ -220,14 +212,14 @@ public static void setupConsumerDeserializerProperties(final JavaSamplerContext public static void setupConsumerSchemaRegistryProperties(final JavaSamplerContext context, final Properties props) { final Map originals = new HashMap<>(); - setupSchemaRegistryAuthenticationProperties(context.getJMeterVariables(), originals); + setupSchemaRegistryAuthenticationProperties(JavaSamplerContext.getJMeterVariables(), originals); props.putAll(originals); - if (Objects.nonNull(context.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY))) { - props.put(ProducerKeysHelper.VALUE_NAME_STRATEGY, context.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY))) { + props.put(ProducerKeysHelper.VALUE_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY)); } - if (Objects.nonNull(context.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY))) { - props.put(ProducerKeysHelper.KEY_NAME_STRATEGY, context.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY))) { + props.put(ProducerKeysHelper.KEY_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY)); } } @@ -267,11 +259,11 @@ public static Properties setupCommonConsumerProperties(final JavaSamplerContext props.put(CommonClientConfigs.CLIENT_ID_CONFIG, context.getParameter(CommonClientConfigs.CLIENT_ID_CONFIG)); - if (Objects.nonNull(context.getJMeterVariables().get(PropsKeysHelper.VALUE_SCHEMA))) { - props.put(PropsKeysHelper.VALUE_SCHEMA, context.getJMeterVariables().get(PropsKeysHelper.VALUE_SCHEMA)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_SCHEMA))) { + props.put(PropsKeysHelper.VALUE_SCHEMA, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_SCHEMA)); } - if (Objects.nonNull(context.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA))) { - props.put(PropsKeysHelper.KEY_SCHEMA, context.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA)); + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA))) { + props.put(PropsKeysHelper.KEY_SCHEMA, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA)); } props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, context.getParameter(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG)); diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java similarity index 89% rename from src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java rename to src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java index 3d8b6475..1cb6dd53 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiSchemaRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java @@ -1,12 +1,10 @@ -package com.sngular.kloadgen.config.asyncapi; - -import java.awt.Color; -import java.awt.Component; -import java.util.Objects; +package com.sngular.kloadgen.sampler.gui; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; -import javax.swing.JLabel; -import javax.swing.JList; + +import javax.swing.*; +import java.awt.*; +import java.util.Objects; public class ApiSchemaRenderer extends JLabel implements javax.swing.ListCellRenderer { diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java similarity index 89% rename from src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java rename to src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java index 48d700de..52e4c98e 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/ApiServerRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java @@ -1,12 +1,10 @@ -package com.sngular.kloadgen.config.asyncapi; - -import java.awt.Color; -import java.awt.Component; -import java.util.Objects; +package com.sngular.kloadgen.sampler.gui; import com.sngular.kloadgen.extractor.model.AsyncApiServer; -import javax.swing.JLabel; -import javax.swing.JList; + +import javax.swing.*; +import java.awt.*; +import java.util.Objects; public class ApiServerRenderer extends JLabel implements javax.swing.ListCellRenderer { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java new file mode 100644 index 00000000..3cb2ed91 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java @@ -0,0 +1,49 @@ +package com.sngular.kloadgen.sampler.gui; + +import com.sngular.kloadgen.extractor.model.AsyncApiSR; + +import javax.swing.*; +import java.awt.*; +import java.util.Objects; + +public class AsyncApiSRRenderer extends JLabel implements javax.swing.ListCellRenderer { + + public AsyncApiSRRenderer() { + setOpaque(true); + } + + @Override + public Component getListCellRendererComponent(final JList list, final AsyncApiSR value, final int index, final boolean isSelected, final boolean cellHasFocus) { + if (Objects.nonNull(value)) { + setText(value.name()); + + final Color background; + final Color foreground; + + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + background = Color.BLUE; + foreground = Color.WHITE; + + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; + + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + + setBackground(background); + setForeground(foreground); + } + return this; + } + +} diff --git a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java similarity index 75% rename from src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java rename to src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 8b83c95a..f1467073 100644 --- a/src/main/java/com/sngular/kloadgen/config/asyncapi/AsyncApiConfigGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -10,45 +10,30 @@ * * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package com.sngular.kloadgen.config.asyncapi; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.List; -import java.util.Objects; +package com.sngular.kloadgen.sampler.gui; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.extractor.model.*; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.sampler.AsyncApiSampler; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileSystemView; -import javax.swing.table.DefaultTableModel; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; -public final class AsyncApiConfigGui extends AbstractSamplerGui { +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.Collection; +import java.util.Objects; + +public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); @@ -58,8 +43,6 @@ public final class AsyncApiConfigGui extends AbstractSamplerGui { private JTextField asyncApiFileTextField; - private JTextField registryUrl; - private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Field Values List"}, 20); private final DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); @@ -70,7 +53,11 @@ public final class AsyncApiConfigGui extends AbstractSamplerGui { private JComboBox topicComboBox; - public AsyncApiConfigGui() { + private JComboBox registryComboBox; + + private AsyncApiFile asyncApiFile; + + public AsyncApiSamplerGui() { super(); init(); } @@ -80,6 +67,72 @@ public String getStaticLabel() { return "AsyncApi Sampler"; } + @Override + public void clearGui() { + super.clearGui(); + asyncApiFileTextField.setText(""); + // registryUrl.setText(""); + } + + @Override + public String getLabelResource() { + return "Asyncapi"; + } + + @Override + public TestElement createTestElement() { + final var testElement = new AsyncApiSampler(); + configureTestElement(testElement); + return testElement; + } + + @Override + public void modifyTestElement(TestElement element) { + super.configureTestElement(element); + if (element instanceof AsyncApiSampler asyncApiSampler) { + if (Objects.nonNull(asyncApiFile)) { + asyncApiSampler.setAsyncApiFile(asyncApiFile); + asyncApiSampler.setAsyncApiServerName(((AsyncApiServer) serverComboBox.getSelectedItem()).getName()); + asyncApiSampler.setAsyncApiSchemaName(((AsyncApiSchema) topicComboBox.getSelectedItem()).getTopicName()); + // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); + } + } + } + + @Override + public void configure(TestElement element) { + super.configure(element); + if (element instanceof AsyncApiSampler) { + asyncApiFile = ((AsyncApiSampler) element).getAsyncApiFile(); + populateData(); + } + } + + private void actionFileChooser(final ActionEvent event) { + + final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + + if (JFileChooser.APPROVE_OPTION == returnValue) { + try { + final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(apiFile.getAbsolutePath()); + asyncApiFile = asyncApiExtractor.processFile(apiFile); + populateData(); + } catch (KLoadGenException ex) { + JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); + } + } + } + + private void populateData() { + if (Objects.nonNull(asyncApiFile)) { + asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); + fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile).values()); + fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); + asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); + } + } + private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); @@ -134,31 +187,12 @@ private JPanel createAsyncApiFileSelectPanel() { private JTabbedPane createAsyncApiTabs() { final var tabbedPanel = new JTabbedPane(); tabbedPanel.addTab("Broker", createBrokerPanel()); - tabbedPanel.addTab("Registry", createRegistryTab()); + // tabbedPanel.addTab("Registry", createRegistryTab()); tabbedPanel.addTab("Schema", createSchemaTab()); return tabbedPanel; } - public void actionFileChooser(final ActionEvent event) { - - final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); - - if (JFileChooser.APPROVE_OPTION == returnValue) { - try { - final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); - asyncApiFileTextField.setText(apiFile.getAbsolutePath()); - final var asyncApiFile = asyncApiExtractor.processFile(apiFile); - asyncApiFile.getApiServerList().forEach(serverComboBox::addItem); - fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile)); - fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); - asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); - } catch (KLoadGenException ex) { - JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); - } - } - } - - private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final Collection schemaData) { if (Objects.nonNull(schemaData)) { final var count = schemaFields.getRowCount(); for (var i = 0; i < count; i++) { @@ -190,18 +224,21 @@ private JPanel createBrokerPanel() { brokerPanel.add(new JLabeledTextField("Broker Server")); serverComboBox = new JComboBox<>(); serverComboBox.setRenderer(new ApiServerRenderer()); + serverComboBox.addActionListener(this::serverChooseActionListener); brokerPanel.add(serverComboBox, BorderLayout.NORTH); brokerPanel.add(new JScrollPane(new JTable(brokerFieldModel)), BorderLayout.CENTER); return brokerPanel; } + private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new BorderLayout(0, 0)); registryUrlPanel.add(new JLabeledTextField("Schema Registry URL")); - this.registryUrl = new JTextField(); - this.registryUrl.setPreferredSize(new Dimension(249, 30)); - registryUrlPanel.add(this.registryUrl, BorderLayout.NORTH); + registryComboBox = new JComboBox<>(); + registryComboBox.setRenderer(new AsyncApiSRRenderer()); + registryComboBox.addActionListener(this::registryComboActionListener); + registryUrlPanel.add(this.registryComboBox, BorderLayout.NORTH); registryUrlPanel.add(new JScrollPane(new JTable(schemaRegistryFieldModel)), BorderLayout.CENTER); return registryUrlPanel; } @@ -224,27 +261,12 @@ private void topicComboActionListener(final ActionEvent event) { fillTable(schemaFieldModel, selectedSchema.getProperties()); } - @Override - public void clearGui() { - super.clearGui(); - asyncApiFileTextField.setText(""); - registryUrl.setText(""); + private void registryComboActionListener(ActionEvent actionEvent) { } - @Override - public String getLabelResource() { - return "Asyncapi"; - } - - @Override - public TestElement createTestElement() { - final var testElement = new AsyncApiSampler(); - modifyTestElement(testElement); - return testElement; - } - - @Override - public void modifyTestElement(TestElement element) { - + private void serverChooseActionListener(ActionEvent actionEvent) { + final JComboBox cb = (JComboBox)actionEvent.getSource(); + final var selectedSchema = (AsyncApiServer) cb.getSelectedItem(); + fillTable(brokerFieldModel, selectedSchema.getProperties()); } } From cf6eef3f85be30f995ad27caec298dcdd968e379 Mon Sep 17 00:00:00 2001 From: Jose Enrique Garcia Date: Tue, 10 Oct 2023 00:29:55 +0200 Subject: [PATCH 17/55] Add Async Api GUI --- .../kloadgen/common/tools/ApiTool.java | 16 ++-- .../asyncapi/AsyncApiExtractorImpl.java | 73 ++++++++++++++++++- .../kloadgen/model/ConstraintTypeEnum.java | 2 +- .../sampler/gui/AsyncApiSamplerGui.java | 10 ++- 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java index 5f8de2a2..b58aec34 100644 --- a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -1,20 +1,14 @@ package com.sngular.kloadgen.common.tools; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.collections4.Transformer; import org.apache.commons.lang3.StringUtils; +import java.util.*; +import java.util.Map.Entry; + public final class ApiTool { public static final String FORMAT = "format"; @@ -198,6 +192,10 @@ public static boolean hasAdditionalProperties(final JsonNode schema) { return hasNode(schema, "additionalProperties"); } + public static boolean hasFormat(JsonNode schema) { + return hasNode(schema, "format"); + } + public static boolean isObject(final JsonNode schema) { return hasType(schema) && TypeConstants.OBJECT.equalsIgnoreCase(getType(schema)); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 1d37c965..ac09fd34 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -11,6 +11,7 @@ import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.model.ConstraintTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; import org.apache.commons.lang3.StringUtils; @@ -104,7 +105,7 @@ private List processPayload(final JsonNode finalPayload, fina fieldList.addAll(processPayload(solveRef(finalPayload, components, antiLoopList, "schemas"), root, components, antiLoopList)); } else if (ApiTool.hasAdditionalProperties(finalPayload)) { fieldList.addAll(processMap(finalPayload, root, components, antiLoopList)); - } else { + } else if (ApiTool.hasProperties(finalPayload)) { for (Iterator> it = ApiTool.getProperties(finalPayload); it.hasNext();) { final var property = it.next(); final var propertyDef = property.getValue(); @@ -120,13 +121,73 @@ private List processPayload(final JsonNode finalPayload, fina .builder() .fieldName(calculateName(property.getKey(), root)) .fieldType(ApiTool.getType(propertyDef)) + .fieldValueList(hasValues(propertyDef)) + .constraints(getConstraints(propertyDef)) .build()); } } + } else { + fieldList.add(FieldValueMapping + .builder() + .fieldName(calculateName(null, root)) + .fieldType(getType(finalPayload)) + .fieldValueList(hasValues(finalPayload)) + .constraints(getConstraints(finalPayload)) + .build()); } return fieldList; } + private String getType(JsonNode finalPayload) { + String type = ApiTool.getType(finalPayload); + if (ApiTool.hasFormat(finalPayload)) { + type = switch (ApiTool.getFormat(finalPayload)) { + case "date-time" -> "datetime"; + case "int64" -> "long"; + case "double" -> "double"; + case "date" -> "date"; + default -> ApiTool.getType(finalPayload); + }; + + } + return type; + } + + private Map getConstraints(JsonNode finalPayload) { + Map constraints = new EnumMap<>(ConstraintTypeEnum.class); + if (ApiTool.hasNode(finalPayload, "minLength")) { + constraints.put(ConstraintTypeEnum.MIN_LENGTH, ApiTool.getNodeAsString(finalPayload, "minLength")); + } + if (ApiTool.hasNode(finalPayload, "maxLength")) { + constraints.put(ConstraintTypeEnum.MAX_LENGTH, ApiTool.getNodeAsString(finalPayload, "minLength")); + } + if (ApiTool.hasNode(finalPayload, "minimum")) { + constraints.put(ConstraintTypeEnum.MINIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "minimum")); + } + if (ApiTool.hasNode(finalPayload, "maximum")) { + constraints.put(ConstraintTypeEnum.MAXIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "maximum")); + } + if (ApiTool.hasNode(finalPayload, "exclusiveMinimum")) { + constraints.put(ConstraintTypeEnum.EXCLUDED_MINIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "exclusiveMinimum")); + } + if (ApiTool.hasNode(finalPayload, "exclusiveMaximum")) { + constraints.put(ConstraintTypeEnum.EXCLUDED_MAXIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "exclusiveMaximum")); + } + if (ApiTool.hasNode(finalPayload, "multipleOf")) { + constraints.put(ConstraintTypeEnum.MULTIPLE_OF, ApiTool.getNodeAsString(finalPayload, "multipleOf")); + } + + return constraints; + } + + private String hasValues(JsonNode propertyDef) { + String values = null; + if (ApiTool.isEnum(propertyDef)) { + values = String.join(",", ApiTool.getEnumValues(propertyDef)); + } + return values; + } + private List calculatePayload(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) { final var fieldList = new ArrayList(); if (!ApiTool.hasAdditionalProperties(propertyDef)) { @@ -190,10 +251,14 @@ private List processMap(final JsonNode propertyDef, final Str private String calculateName(final String propertyName, final String root) { final String finalName; - if (StringUtils.isEmpty(root)) { - finalName = propertyName; + if (Objects.nonNull(propertyName)) { + if (StringUtils.isEmpty(root)) { + finalName = propertyName; + } else { + finalName = root + "." + propertyName; + } } else { - finalName = root + "." + propertyName; + finalName = root.substring(root.lastIndexOf(".")); } return finalName; } diff --git a/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java b/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java index 81f10718..a3abce2a 100644 --- a/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java +++ b/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java @@ -15,5 +15,5 @@ public enum ConstraintTypeEnum { REGEX, FORMAT, PRECISION, - SCALE + MIN_LENGTH, MAX_LENGTH, SCALE } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index f1467073..bfee9287 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -92,8 +92,12 @@ public void modifyTestElement(TestElement element) { if (element instanceof AsyncApiSampler asyncApiSampler) { if (Objects.nonNull(asyncApiFile)) { asyncApiSampler.setAsyncApiFile(asyncApiFile); - asyncApiSampler.setAsyncApiServerName(((AsyncApiServer) serverComboBox.getSelectedItem()).getName()); - asyncApiSampler.setAsyncApiSchemaName(((AsyncApiSchema) topicComboBox.getSelectedItem()).getTopicName()); + if (serverComboBox.getSelectedIndex() > -1) { + asyncApiSampler.setAsyncApiServerName(((AsyncApiServer) serverComboBox.getSelectedItem()).getName()); + } + if (topicComboBox.getSelectedIndex() > -1) { + asyncApiSampler.setAsyncApiSchemaName(((AsyncApiSchema) topicComboBox.getSelectedItem()).getTopicName()); + } // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } } @@ -127,9 +131,11 @@ private void actionFileChooser(final ActionEvent event) { private void populateData() { if (Objects.nonNull(asyncApiFile)) { asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); + serverComboBox.setSelectedIndex(0); fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile).values()); fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); + topicComboBox.setSelectedIndex(0); } } From 92737c2dbc1d9d4d243a17cb83b031ae6fc86a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Fri, 13 Oct 2023 00:17:11 +0200 Subject: [PATCH 18/55] #332 Fix checkstyle issues --- .../SchemaRegistryConfigElementBeanInfo.java | 3 +- .../extractor/model/AsyncApiFile.java | 10 +- .../kloadgen/extractor/model/AsyncApiSR.java | 7 + .../extractor/model/AsyncApiServer.java | 4 +- .../kloadgen/sampler/AsyncApiSampler.java | 77 ++++++--- .../sngular/kloadgen/sampler/SamplerUtil.java | 154 +++++++++--------- .../sampler/gui/AsyncApiSRRenderer.java | 84 +++++----- .../sampler/gui/AsyncApiSamplerGui.java | 92 ++++++++--- .../gui/SchemaRegistryProperties.java} | 8 +- 9 files changed, 274 insertions(+), 165 deletions(-) rename src/main/java/com/sngular/kloadgen/{config/schemaregistry/DefaultPropertiesHelper.java => sampler/gui/SchemaRegistryProperties.java} (86%) diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java index cc90a49c..c8d5b5a7 100644 --- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java +++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java @@ -15,6 +15,7 @@ import com.sngular.kloadgen.model.PropertyMapping; import com.sngular.kloadgen.property.editor.SchemaRegistryConfigPropertyEditor; import com.sngular.kloadgen.property.editor.SchemaRegistryNamePropertyEditor; +import com.sngular.kloadgen.sampler.gui.SchemaRegistryProperties; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.jmeter.testbeans.BeanInfoSupport; import org.apache.jmeter.testbeans.gui.TableEditor; @@ -45,7 +46,7 @@ public SchemaRegistryConfigElementBeanInfo() { tableProperties.setValue(TableEditor.CLASSNAME, PropertyMapping.class.getName()); tableProperties.setValue(TableEditor.HEADERS, new String[]{"Property Name", "Property Value"}); tableProperties.setValue(TableEditor.OBJECT_PROPERTIES, new String[]{PropertyMapping.PROPERTY_NAME, PropertyMapping.PROPERTY_VALUE}); - tableProperties.setValue(DEFAULT, DefaultPropertiesHelper.DEFAULTS); + tableProperties.setValue(DEFAULT, SchemaRegistryProperties.DEFAULTS); tableProperties.setValue(NOT_UNDEFINED, Boolean.TRUE); tableProperties.setValue(NOT_EXPRESSION, Boolean.FALSE); diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java index 4bbcf7af..e2ee4775 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -1,18 +1,22 @@ package com.sngular.kloadgen.extractor.model; -import lombok.Builder; -import lombok.Value; - import java.util.List; import java.util.Map; +import lombok.Builder; +import lombok.Singular; +import lombok.Value; + @Value @Builder public class AsyncApiFile { + @Singular("apiServer") Map apiServerMap; + @Singular("apiAsyncApiSR") List apiAsyncApiSRList; + @Singular("apiSchema") Map apiSchemaList; } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java index 7b27be36..d4ee6446 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java @@ -1,5 +1,7 @@ package com.sngular.kloadgen.extractor.model; +import java.util.Map; + public record AsyncApiSR(String name, String schemaRegistryUrl, String schemaRegistryVendor) implements AsyncApiAbstract { @@ -7,4 +9,9 @@ public record AsyncApiSR(String name, String schemaRegistryUrl, public Object[] getProperties() { return new Object[]{schemaRegistryUrl, schemaRegistryVendor}; } + + @Override + public Map getPropertiesMap() { + return Map.of("url", schemaRegistryUrl, "type", schemaRegistryVendor); + } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java index d4868889..a27ec386 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java @@ -1,10 +1,10 @@ package com.sngular.kloadgen.extractor.model; +import java.util.Map; + import lombok.Builder; import lombok.Value; -import java.util.Map; - @Value @Builder public class AsyncApiServer implements AsyncApiAbstract { diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 1944c6f2..75fa5906 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -1,5 +1,13 @@ package com.sngular.kloadgen.sampler; +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.sngular.kloadgen.exception.KLoadGenException; @@ -10,9 +18,8 @@ import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.util.ProducerKeysHelper; -import lombok.Getter; -import lombok.Setter; import org.apache.jmeter.config.ConfigTestElement; +import org.apache.jmeter.gui.GUIMenuSortOrder; import org.apache.jmeter.samplers.AbstractSampler; import org.apache.jmeter.samplers.Entry; import org.apache.jmeter.samplers.SampleResult; @@ -23,17 +30,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ExecutionException; - -@Getter -@Setter -public class AsyncApiSampler extends AbstractSampler implements Serializable { +@GUIMenuSortOrder(Integer.MAX_VALUE) +public class AsyncApiSampler extends AbstractSampler implements Serializable { private static final Logger LOG = LoggerFactory.getLogger(AsyncApiSampler.class); @@ -51,7 +49,7 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { private transient BaseLoadGenerator generator; - private transient final ObjectMapper mapper = new ObjectMapper(); + private final transient ObjectMapper mapper = new ObjectMapper(); public AsyncApiSampler() { apiExtractor = new AsyncApiExtractorImpl(); @@ -65,7 +63,7 @@ public final boolean applies(final ConfigTestElement configElement) { } @Override - public SampleResult sample(final Entry entry) { + public final SampleResult sample(final Entry entry) { final var sampleResult = new SampleResult(); try (final KafkaProducer producer = new KafkaProducer<>(extractProps(asyncApiServerName))) { @@ -104,13 +102,53 @@ private Map extractProps(String asyncApiServerName) { return properties; } - public String getAsyncApiFileStr() throws JsonProcessingException { + public final String getAsyncApiFileStr() throws JsonProcessingException { return mapper.writeValueAsString(asyncApiFileStr); } - public void setAsyncApiFileStr(String asyncApiFileStr) throws IOException { + public final void setAsyncApiFileStr(String asyncApiFileStr) { this.asyncApiFileStr = asyncApiFileStr; - this.asyncApiFile = mapper.createParser(asyncApiFileStr).readValueAs(AsyncApiFile.class); + try { + this.asyncApiFile = mapper.createParser(asyncApiFileStr).readValueAs(AsyncApiFile.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public final AsyncApiFile getAsyncApiFile() { + try { + asyncApiFile = mapper.createParser(this.getPropertyAsString("asyncapifilestr")).readValueAs(AsyncApiFile.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + return asyncApiFile; + } + + public final void setAsyncApiFile(final AsyncApiFile asyncApiFile) { + try { + this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFile)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + this.asyncApiFile = asyncApiFile; + } + + public final String getAsyncApiServerName() { + return asyncApiServerName; + } + + public final void setAsyncApiServerName(final String asyncApiServerName) { + this.setProperty("asyncApiServerName", asyncApiServerName); + this.asyncApiServerName = asyncApiServerName; + } + + public final String getAsyncApiSchemaName() { + return asyncApiSchemaName; + } + + public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { + this.setProperty("asyncapischemaname", asyncApiSchemaName); + this.asyncApiSchemaName = asyncApiSchemaName; } private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean keyFlag, final boolean valueFlag) { @@ -128,8 +166,7 @@ private Boolean enrichedValueFlag() { } private void fillSamplerResult(final ProducerRecord producerRecord, final SampleResult sampleResult) { - String result = "key: " + producerRecord.key() + - ", payload: " + producerRecord.value(); + final String result = "key: " + producerRecord.key() + ", payload: " + producerRecord.value(); sampleResult.setSamplerData(result); } diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index 8b78c86d..2e4ae4cb 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -6,6 +6,18 @@ package com.sngular.kloadgen.sampler; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.AvroSRLoadGenerator; @@ -36,10 +48,6 @@ import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.common.security.auth.SecurityProtocol; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.*; - public final class SamplerUtil { private static final StatelessGeneratorTool STATELESS_GENERATOR_TOOL = new StatelessGeneratorTool(); @@ -146,10 +154,6 @@ public static Properties setupCommonProperties(final JavaSamplerContext context) return props; } - private static String propertyOrDefault(final String property, final String defaultToken, final String valueToSent) { - return defaultToken.equals(property) ? valueToSent : property; - } - @SuppressWarnings("checkstyle:ExecutableStatementCount") public static Arguments getCommonConsumerDefaultParameters() { final Arguments defaultParameters = new Arguments(); @@ -223,25 +227,6 @@ public static void setupConsumerSchemaRegistryProperties(final JavaSamplerContex } } - private static void setupSchemaRegistryAuthenticationProperties(final JMeterVariables context, final Map props) { - if (Objects.nonNull(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME))) { - - final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); - props.put(schemaRegistryManager.getSchemaRegistryUrlKey(), context.get(schemaRegistryManager.getSchemaRegistryUrlKey())); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); - - if (ProducerKeysHelper.FLAG_YES.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_FLAG))) { - if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BASIC_TYPE.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_KEY))) { - props.put(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE)); - props.put(SchemaRegistryClientConfig.USER_INFO_CONFIG, context.get(SchemaRegistryClientConfig.USER_INFO_CONFIG)); - } else { - props.put(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE)); - props.put(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG, context.get(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG)); - } - } - } - } - public static Properties setupCommonConsumerProperties(final JavaSamplerContext context) { final Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, context.getParameter(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG)); @@ -291,52 +276,6 @@ public static Properties setupCommonConsumerProperties(final JavaSamplerContext return props; } - private static void verifySecurity(final JavaSamplerContext context, final Properties props) { - if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.SSL_ENABLED))) { - - props.put(SslConfigs.SSL_KEY_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_KEY_PASSWORD_CONFIG)); - props.put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG)); - props.put(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG)); - props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, context.getParameter(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG)); - props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG)); - } - - if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.KERBEROS_ENABLED))) { - System.setProperty(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); - System.setProperty(ProducerKeysHelper.JAVA_SEC_KRB5_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_KRB5_CONFIG)); - props.put(ProducerKeysHelper.SASL_KERBEROS_SERVICE_NAME, context.getParameter(ProducerKeysHelper.SASL_KERBEROS_SERVICE_NAME)); - } - - if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.JAAS_ENABLED))) { - if (StringUtils.contains(context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG), File.separatorChar)) { - System.setProperty(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); - } else { - props.put(SaslConfigs.SASL_JAAS_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); - } - } - - props.put(ProducerConfig.CLIENT_ID_CONFIG, context.getParameter(ProducerConfig.CLIENT_ID_CONFIG)); - - props.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, context.getParameter(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG)); - - props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, - propertyOrDefault(context.getParameter(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG), - ProducerKeysHelper.DEFAULT_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM, - "")); - - props.put(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG, context.getParameter(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG)); - props.put(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG)); - props.put(SslConfigs.SSL_PROTOCOL_CONFIG, context.getParameter(SslConfigs.SSL_PROTOCOL_CONFIG)); - - if (!StringUtils.isBlank(context.getParameter(ProducerConfig.SECURITY_PROVIDERS_CONFIG).trim())) { - props.put(ProducerConfig.SECURITY_PROVIDERS_CONFIG, context.getParameter(ProducerConfig.SECURITY_PROVIDERS_CONFIG)); - } - - if (!StringUtils.isBlank(context.getParameter(SslConfigs.SSL_PROVIDER_CONFIG).trim())) { - props.put(SslConfigs.SSL_PROVIDER_CONFIG, context.getParameter(SslConfigs.SSL_PROVIDER_CONFIG)); - } - } - public static BaseLoadGenerator configureValueGenerator(final Properties props) { final JMeterVariables jMeterVariables = JMeterContextService.getContext().getVariables(); final BaseLoadGenerator generator; @@ -455,6 +394,75 @@ public static List populateHeaders(final List kafkaHeader return headersSB; } + private static void verifySecurity(final JavaSamplerContext context, final Properties props) { + if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.SSL_ENABLED))) { + + props.put(SslConfigs.SSL_KEY_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_KEY_PASSWORD_CONFIG)); + props.put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG)); + props.put(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG)); + props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, context.getParameter(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG)); + props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, context.getParameter(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG)); + } + + if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.KERBEROS_ENABLED))) { + System.setProperty(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); + System.setProperty(ProducerKeysHelper.JAVA_SEC_KRB5_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_KRB5_CONFIG)); + props.put(ProducerKeysHelper.SASL_KERBEROS_SERVICE_NAME, context.getParameter(ProducerKeysHelper.SASL_KERBEROS_SERVICE_NAME)); + } + + if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.JAAS_ENABLED))) { + if (StringUtils.contains(context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG), File.separatorChar)) { + System.setProperty(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); + } else { + props.put(SaslConfigs.SASL_JAAS_CONFIG, context.getParameter(ProducerKeysHelper.JAVA_SEC_AUTH_LOGIN_CONFIG)); + } + } + + props.put(ProducerConfig.CLIENT_ID_CONFIG, context.getParameter(ProducerConfig.CLIENT_ID_CONFIG)); + + props.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, context.getParameter(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG)); + + props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, + propertyOrDefault(context.getParameter(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG), + ProducerKeysHelper.DEFAULT_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM, + "")); + + props.put(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG, context.getParameter(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG)); + props.put(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG, context.getParameter(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG)); + props.put(SslConfigs.SSL_PROTOCOL_CONFIG, context.getParameter(SslConfigs.SSL_PROTOCOL_CONFIG)); + + if (!StringUtils.isBlank(context.getParameter(ProducerConfig.SECURITY_PROVIDERS_CONFIG).trim())) { + props.put(ProducerConfig.SECURITY_PROVIDERS_CONFIG, context.getParameter(ProducerConfig.SECURITY_PROVIDERS_CONFIG)); + } + + if (!StringUtils.isBlank(context.getParameter(SslConfigs.SSL_PROVIDER_CONFIG).trim())) { + props.put(SslConfigs.SSL_PROVIDER_CONFIG, context.getParameter(SslConfigs.SSL_PROVIDER_CONFIG)); + } + } + + private static void setupSchemaRegistryAuthenticationProperties(final JMeterVariables context, final Map props) { + if (Objects.nonNull(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME))) { + + final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); + props.put(schemaRegistryManager.getSchemaRegistryUrlKey(), context.get(schemaRegistryManager.getSchemaRegistryUrlKey())); + props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); + + if (ProducerKeysHelper.FLAG_YES.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_FLAG))) { + if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BASIC_TYPE.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_KEY))) { + props.put(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE)); + props.put(SchemaRegistryClientConfig.USER_INFO_CONFIG, context.get(SchemaRegistryClientConfig.USER_INFO_CONFIG)); + } else { + props.put(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE)); + props.put(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG, context.get(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG)); + } + } + } + } + + private static String propertyOrDefault(final String property, final String defaultToken, final String valueToSent) { + return defaultToken.equals(property) ? valueToSent : property; + } + private static BaseLoadGenerator getLoadGenerator(final JMeterVariables jmeterVariables) { final BaseLoadGenerator generator; diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java index 3cb2ed91..ef6b5abc 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSRRenderer.java @@ -1,49 +1,53 @@ package com.sngular.kloadgen.sampler.gui; -import com.sngular.kloadgen.extractor.model.AsyncApiSR; - -import javax.swing.*; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; import java.util.Objects; -public class AsyncApiSRRenderer extends JLabel implements javax.swing.ListCellRenderer { +import javax.swing.JLabel; +import javax.swing.JList; - public AsyncApiSRRenderer() { - setOpaque(true); - } +import com.sngular.kloadgen.extractor.model.AsyncApiSR; + +public class AsyncApiSRRenderer extends JLabel implements javax.swing.ListCellRenderer { - @Override - public Component getListCellRendererComponent(final JList list, final AsyncApiSR value, final int index, final boolean isSelected, final boolean cellHasFocus) { - if (Objects.nonNull(value)) { - setText(value.name()); - - final Color background; - final Color foreground; - - // check if this cell represents the current DnD drop location - final JList.DropLocation dropLocation = list.getDropLocation(); - if (dropLocation != null - && !dropLocation.isInsert() - && dropLocation.getIndex() == index) { - - background = Color.BLUE; - foreground = Color.WHITE; - - // check if this cell is selected - } else if (isSelected) { - background = Color.RED; - foreground = Color.WHITE; - - // unselected, and not the DnD drop location - } else { - background = Color.WHITE; - foreground = Color.BLACK; - } - - setBackground(background); - setForeground(foreground); - } - return this; + public AsyncApiSRRenderer() { + setOpaque(true); + } + + @Override + public Component getListCellRendererComponent( + final JList list, final AsyncApiSR value, final int index, final boolean isSelected, final boolean cellHasFocus) { + if (Objects.nonNull(value)) { + setText(value.name()); + + final Color background; + final Color foreground; + + // check if this cell represents the current DnD drop location + final JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + background = Color.BLUE; + foreground = Color.WHITE; + + // check if this cell is selected + } else if (isSelected) { + background = Color.RED; + foreground = Color.WHITE; + + // unselected, and not the DnD drop location + } else { + background = Color.WHITE; + foreground = Color.BLACK; + } + + setBackground(background); + setForeground(foreground); } + return this; + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index bfee9287..6101bc48 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -12,26 +12,50 @@ package com.sngular.kloadgen.sampler.gui; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Objects; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.*; +import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.extractor.model.AsyncApiSR; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.sampler.AsyncApiSampler; +import com.sngular.kloadgen.sampler.SamplerUtil; +import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; - -import javax.swing.*; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileSystemView; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.Collection; -import java.util.Objects; +import org.apache.kafka.clients.producer.ProducerConfig; public final class AsyncApiSamplerGui extends AbstractSamplerGui { @@ -58,7 +82,6 @@ public final class AsyncApiSamplerGui extends AbstractSamplerGui { private AsyncApiFile asyncApiFile; public AsyncApiSamplerGui() { - super(); init(); } @@ -82,12 +105,12 @@ public String getLabelResource() { @Override public TestElement createTestElement() { final var testElement = new AsyncApiSampler(); - configureTestElement(testElement); + modifyTestElement(testElement); return testElement; } @Override - public void modifyTestElement(TestElement element) { + public void modifyTestElement(final TestElement element) { super.configureTestElement(element); if (element instanceof AsyncApiSampler asyncApiSampler) { if (Objects.nonNull(asyncApiFile)) { @@ -101,10 +124,11 @@ public void modifyTestElement(TestElement element) { // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } } + configureTestElement(element); } @Override - public void configure(TestElement element) { + public void configure(final TestElement element) { super.configure(element); if (element instanceof AsyncApiSampler) { asyncApiFile = ((AsyncApiSampler) element).getAsyncApiFile(); @@ -132,13 +156,38 @@ private void populateData() { if (Objects.nonNull(asyncApiFile)) { asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); serverComboBox.setSelectedIndex(0); - fillTable(brokerFieldModel, asyncApiExtractor.getBrokerData(asyncApiFile).values()); - fillTable(schemaRegistryFieldModel, asyncApiExtractor.getSchemaRegistryData(asyncApiFile)); + fillTable(brokerFieldModel, prepareServer(asyncApiExtractor.getBrokerData(asyncApiFile).get(serverComboBox.getSelectedItem()))); + final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); + if (!schemaRegistryList.isEmpty()) { + fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); + } asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); topicComboBox.setSelectedIndex(0); } } + private Collection> prepareSRServer(final AsyncApiSR schemaRegistryData) { + final var srPropoMap = schemaRegistryData.getPropertiesMap(); + final var propertyList = new ArrayList>(); + propertyList.add(Pair.of(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, srPropoMap.get("url"))); + propertyList.add(Pair.of(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, srPropoMap.get("type"))); + SchemaRegistryProperties.DEFAULTS.forEach(jMeterProperty -> propertyList.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getPropertyValue()))); + return propertyList; + } + + private Collection> prepareServer(final AsyncApiServer asyncApiServer) { + final var propertylist = new ArrayList>(); + if (Objects.nonNull(asyncApiServer)) { + final var serverProps = asyncApiServer.getPropertiesMap(); + propertylist.add(Pair.of(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, serverProps.get("url"))); + CollectionUtils.select(SamplerUtil + .getCommonProducerDefaultParameters(), + property -> !property.getName().equalsIgnoreCase(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)) + .forEach(jMeterProperty -> propertylist.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getStringValue()))); + } + return propertylist; + } + private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); @@ -198,7 +247,7 @@ private JTabbedPane createAsyncApiTabs() { return tabbedPanel; } - private void fillTable(final DefaultTableModel schemaFields, final Collection schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final Collection> schemaData) { if (Objects.nonNull(schemaData)) { final var count = schemaFields.getRowCount(); for (var i = 0; i < count; i++) { @@ -220,8 +269,8 @@ private void fillTable(final DefaultTableModel sche } } - private Object[] dataToRow(final T data) { - return data.getProperties(); + private Object[] dataToRow(final Pair data) { + return new Object[] {data.getKey(), data.getValue()}; } private JPanel createBrokerPanel() { @@ -272,7 +321,6 @@ private void registryComboActionListener(ActionEvent actionEvent) { private void serverChooseActionListener(ActionEvent actionEvent) { final JComboBox cb = (JComboBox)actionEvent.getSource(); - final var selectedSchema = (AsyncApiServer) cb.getSelectedItem(); - fillTable(brokerFieldModel, selectedSchema.getProperties()); + fillTable(brokerFieldModel, prepareServer((AsyncApiServer) cb.getSelectedItem())); } } diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/DefaultPropertiesHelper.java b/src/main/java/com/sngular/kloadgen/sampler/gui/SchemaRegistryProperties.java similarity index 86% rename from src/main/java/com/sngular/kloadgen/config/schemaregistry/DefaultPropertiesHelper.java rename to src/main/java/com/sngular/kloadgen/sampler/gui/SchemaRegistryProperties.java index 74aa5238..4c782142 100644 --- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/DefaultPropertiesHelper.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/SchemaRegistryProperties.java @@ -4,7 +4,7 @@ * * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package com.sngular.kloadgen.config.schemaregistry; +package com.sngular.kloadgen.sampler.gui; import java.util.ArrayList; import java.util.Arrays; @@ -14,9 +14,9 @@ import com.sngular.kloadgen.util.ProducerKeysHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; -class DefaultPropertiesHelper { +public class SchemaRegistryProperties { - protected static final List DEFAULTS = new ArrayList<>(Arrays.asList( + public static final List DEFAULTS = new ArrayList<>(Arrays.asList( PropertyMapping.builder().propertyName(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_FLAG).propertyValue(ProducerKeysHelper.FLAG_NO).build(), PropertyMapping.builder().propertyName(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_KEY).propertyValue(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BASIC_TYPE).build(), PropertyMapping.builder().propertyName(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_USERNAME_KEY).propertyValue(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_USERNAME_DEFAULT).build(), @@ -24,7 +24,7 @@ class DefaultPropertiesHelper { PropertyMapping.builder().propertyName(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BEARER_KEY).propertyValue(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BEARER_DEFAULT) .build())); - private DefaultPropertiesHelper() { + private SchemaRegistryProperties() { } } From 9650c3685c8cc6d2272add7c7cdaf22523c938b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Fri, 13 Oct 2023 00:23:35 +0200 Subject: [PATCH 19/55] #332 Fix checkstyle issues --- .../com/sngular/kloadgen/sampler/AsyncApiSampler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 75fa5906..40de54a5 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -117,7 +117,10 @@ public final void setAsyncApiFileStr(String asyncApiFileStr) { public final AsyncApiFile getAsyncApiFile() { try { - asyncApiFile = mapper.createParser(this.getPropertyAsString("asyncapifilestr")).readValueAs(AsyncApiFile.class); + this.asyncApiFileStr = this.getPropertyAsString("asyncapifilestr"); + if (Objects.nonNull(asyncApiFileStr)) { + asyncApiFile = mapper.createParser(this.getPropertyAsString("asyncapifilestr")).readValueAs(AsyncApiFile.class); + } } catch (IOException e) { throw new RuntimeException(e); } @@ -126,7 +129,8 @@ public final AsyncApiFile getAsyncApiFile() { public final void setAsyncApiFile(final AsyncApiFile asyncApiFile) { try { - this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFile)); + this.asyncApiFileStr = mapper.writeValueAsString(asyncApiFile); + this.setProperty("asyncapifilestr", asyncApiFileStr); } catch (JsonProcessingException e) { throw new RuntimeException(e); } From 733f6e4259707c744dac346fb37f37e0f15b60fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Fri, 13 Oct 2023 00:51:44 +0200 Subject: [PATCH 20/55] #332 Fix checkstyle issues --- .../java/com/sngular/kloadgen/sampler/AsyncApiSampler.java | 3 ++- .../com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 40de54a5..7a794e98 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -18,6 +18,7 @@ import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.util.ProducerKeysHelper; +import org.apache.commons.lang3.StringUtils; import org.apache.jmeter.config.ConfigTestElement; import org.apache.jmeter.gui.GUIMenuSortOrder; import org.apache.jmeter.samplers.AbstractSampler; @@ -118,7 +119,7 @@ public final void setAsyncApiFileStr(String asyncApiFileStr) { public final AsyncApiFile getAsyncApiFile() { try { this.asyncApiFileStr = this.getPropertyAsString("asyncapifilestr"); - if (Objects.nonNull(asyncApiFileStr)) { + if (!StringUtils.isEmpty(asyncApiFileStr)) { asyncApiFile = mapper.createParser(this.getPropertyAsString("asyncapifilestr")).readValueAs(AsyncApiFile.class); } } catch (IOException e) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 6101bc48..3a61907a 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -94,6 +94,8 @@ public String getStaticLabel() { public void clearGui() { super.clearGui(); asyncApiFileTextField.setText(""); + schemaFieldModel.setNumRows(0); + brokerFieldModel.setNumRows(0); // registryUrl.setText(""); } From f46699f01088a323cd43b261488e0b82c37696ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Fri, 13 Oct 2023 01:16:33 +0200 Subject: [PATCH 21/55] #332 Fix checkstyle issues --- .../kloadgen/extractor/ApiExtractor.java | 11 ++++--- .../asyncapi/AsyncApiExtractorImpl.java | 33 ++++++++++++++----- .../extractor/model/AsyncApiFile.java | 9 +++-- .../kloadgen/sampler/AsyncApiSampler.java | 12 ++++--- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java index 76496ecd..a017d04f 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -1,18 +1,21 @@ package com.sngular.kloadgen.extractor; +import java.io.File; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import com.sngular.kloadgen.extractor.model.AsyncApiServer; -import java.io.File; -import java.util.List; -import java.util.Map; - public interface ApiExtractor { AsyncApiFile processFile(final File apiFile); + AsyncApiFile processNode(final JsonNode apiFile); + Map getBrokerData(final AsyncApiFile asyncApiFile); List getSchemaRegistryData(final AsyncApiFile asyncApiFile); diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index ac09fd34..43e08127 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -1,5 +1,17 @@ package com.sngular.kloadgen.extractor.asyncapi; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -15,11 +27,6 @@ import com.sngular.kloadgen.model.FieldValueMapping; import org.apache.commons.lang3.StringUtils; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.Map.Entry; - public class AsyncApiExtractorImpl implements ApiExtractor { private static final Set COMPLEX_TYPES = Set.of("record", "array"); @@ -33,16 +40,24 @@ public class AsyncApiExtractorImpl implements ApiExtractor { @Override public final AsyncApiFile processFile(final File apiFile) { - final var builder = AsyncApiFile.builder(); + AsyncApiFile asyncApiFile = null; try { final JsonNode openApi = om.readTree(apiFile); - builder.apiServerMap(nodeToApServer(ApiTool.getNode(openApi, SERVERS))); - builder.apiSchemaList(nodeToSchema(openApi)); + asyncApiFile = processNode(openApi); } catch (final IOException e) { throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e); } - return builder.build(); + return asyncApiFile; + } + + @Override + public final AsyncApiFile processNode(final JsonNode apiFile) { + return AsyncApiFile.builder() + .asyncApiFileNode(apiFile) + .apiServerMap(nodeToApServer(ApiTool.getNode(apiFile, SERVERS))) + .apiSchemaList(nodeToSchema(apiFile)) + .build(); } private Map nodeToSchema(final JsonNode openApi) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java index e2ee4775..f28f70df 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Builder; import lombok.Singular; import lombok.Value; @@ -11,12 +12,14 @@ @Builder public class AsyncApiFile { + JsonNode asyncApiFileNode; + @Singular("apiServer") - Map apiServerMap; + transient Map apiServerMap; @Singular("apiAsyncApiSR") - List apiAsyncApiSRList; + transient List apiAsyncApiSRList; @Singular("apiSchema") - Map apiSchemaList; + transient Map apiSchemaList; } diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 7a794e98..030be3fa 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -92,7 +92,7 @@ public final SampleResult sample(final Entry entry) { return sampleResult; } - private Map extractProps(String asyncApiServerName) { + private Map extractProps(final String asyncApiServerName) { final var properties = new HashMap(); final var asyncApiBrokerProps = apiExtractor.getBrokerData(asyncApiFile).get(asyncApiServerName).getPropertiesMap(); SamplerUtil.getCommonProducerDefaultParameters().forEach(property -> @@ -118,9 +118,11 @@ public final void setAsyncApiFileStr(String asyncApiFileStr) { public final AsyncApiFile getAsyncApiFile() { try { - this.asyncApiFileStr = this.getPropertyAsString("asyncapifilestr"); - if (!StringUtils.isEmpty(asyncApiFileStr)) { - asyncApiFile = mapper.createParser(this.getPropertyAsString("asyncapifilestr")).readValueAs(AsyncApiFile.class); + if (Objects.isNull(asyncApiFile)) { + this.asyncApiFileStr = this.getPropertyAsString("asyncapifilestr"); + if (!StringUtils.isEmpty(asyncApiFileStr)) { + asyncApiFile = apiExtractor.processNode(mapper.readTree(this.getPropertyAsString("asyncapifilestr"))); + } } } catch (IOException e) { throw new RuntimeException(e); @@ -130,7 +132,7 @@ public final AsyncApiFile getAsyncApiFile() { public final void setAsyncApiFile(final AsyncApiFile asyncApiFile) { try { - this.asyncApiFileStr = mapper.writeValueAsString(asyncApiFile); + this.asyncApiFileStr = mapper.writeValueAsString(asyncApiFile.getAsyncApiFileNode()); this.setProperty("asyncapifilestr", asyncApiFileStr); } catch (JsonProcessingException e) { throw new RuntimeException(e); From 35d07da0f77cd6aadad9678ca1aab39e88b6bdea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Sat, 14 Oct 2023 20:03:38 +0200 Subject: [PATCH 22/55] #332 Fix checkstyle issues --- .../kloadgen/loadgen/BaseLoadGenerator.java | 4 ++ .../loadgen/impl/JsonSRLoadGenerator.java | 6 +++ .../kloadgen/sampler/AsyncApiSampler.java | 37 +++++++++++----- .../sampler/gui/AsyncApiSamplerGui.java | 44 ++++++++++++++++--- 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java index 83851d01..388e3053 100644 --- a/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java +++ b/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java @@ -18,5 +18,9 @@ public interface BaseLoadGenerator { void setUpGenerator(String schema, List fieldExprMappings); + default void setUpGenerator(List fieldExprMappings) { + this.setUpGenerator(null, fieldExprMappings); + } + EnrichedRecord nextMessage(); } diff --git a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java index 55faf553..f5b9f677 100644 --- a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java +++ b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java @@ -56,6 +56,12 @@ public void setUpGenerator(final String schema, final List fi this.jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, fieldExprMappings); } + @Override + public void setUpGenerator(final List fieldExprMappings) { + + this.jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, fieldExprMappings); + } + public EnrichedRecord nextMessage() { return EnrichedRecord.builder().schemaMetadata( metadata.getLeft().getSchemaMetadataAdapter() diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 030be3fa..9b7197d8 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -16,6 +17,8 @@ import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.PropertyMapping; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.util.ProducerKeysHelper; import org.apache.commons.lang3.StringUtils; @@ -24,6 +27,7 @@ import org.apache.jmeter.samplers.AbstractSampler; import org.apache.jmeter.samplers.Entry; import org.apache.jmeter.samplers.SampleResult; +import org.apache.jmeter.testelement.property.ObjectProperty; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; @@ -44,10 +48,6 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { private String asyncApiFileStr; - private String asyncApiServerName; - - private String asyncApiSchemaName; - private transient BaseLoadGenerator generator; private final transient ObjectMapper mapper = new ObjectMapper(); @@ -67,7 +67,8 @@ public final boolean applies(final ConfigTestElement configElement) { public final SampleResult sample(final Entry entry) { final var sampleResult = new SampleResult(); - try (final KafkaProducer producer = new KafkaProducer<>(extractProps(asyncApiServerName))) { + try (final KafkaProducer producer = new KafkaProducer<>(extractProps(getAsyncApiServerName()))) { + generator.setUpGenerator(getSchemaFieldConfiguration()); final var messageVal = generator.nextMessage(); if (Objects.nonNull(messageVal)) { final var producerRecord = getProducerRecord(messageVal, enrichedKeyFlag(), enrichedValueFlag()); @@ -99,7 +100,7 @@ private Map extractProps(final String asyncApiServerName) { properties.put(property.getName(), property.getStringValue())); properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, asyncApiBrokerProps.get("url")); properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "GenericJsonRecordSerializer.class"); - properties.put(ProducerKeysHelper.KAFKA_TOPIC_CONFIG, asyncApiSchemaName); + properties.put(ProducerKeysHelper.KAFKA_TOPIC_CONFIG, getAsyncApiSchemaName()); return properties; } @@ -141,26 +142,40 @@ public final void setAsyncApiFile(final AsyncApiFile asyncApiFile) { } public final String getAsyncApiServerName() { - return asyncApiServerName; + return this.getPropertyAsString("asyncApiServerName"); } public final void setAsyncApiServerName(final String asyncApiServerName) { this.setProperty("asyncApiServerName", asyncApiServerName); - this.asyncApiServerName = asyncApiServerName; + } + + public final void setSchemaFieldConfiguration(final List asyncApiServerName) { + this.setProperty(new ObjectProperty("schemaFieldConfiguration", asyncApiServerName)); + } + + public final List getSchemaFieldConfiguration() { + return (List) this.getProperty("schemaFieldConfiguration").getObjectValue(); + } + + public final void setBrokerConfiguration(final List asyncApiServerName) { + this.setProperty(new ObjectProperty("schemaFieldConfiguration", asyncApiServerName)); + } + + public final List getBrokerConfiguration() { + return (List) this.getProperty("schemaFieldConfiguration").getObjectValue(); } public final String getAsyncApiSchemaName() { - return asyncApiSchemaName; + return this.getPropertyAsString("asyncApiServerName"); } public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { this.setProperty("asyncapischemaname", asyncApiSchemaName); - this.asyncApiSchemaName = asyncApiSchemaName; } private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean keyFlag, final boolean valueFlag) { final ProducerRecord producerRecord; - producerRecord = new ProducerRecord<>(asyncApiSchemaName, getObject(messageVal, valueFlag)); + producerRecord = new ProducerRecord<>(getAsyncApiSchemaName(), getObject(messageVal, valueFlag)); return producerRecord; } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 3a61907a..956f6ead 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -20,7 +20,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Objects; +import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -46,6 +48,7 @@ import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import com.sngular.kloadgen.extractor.model.AsyncApiServer; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.PropertyMapping; import com.sngular.kloadgen.sampler.AsyncApiSampler; import com.sngular.kloadgen.sampler.SamplerUtil; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; @@ -119,9 +122,12 @@ public void modifyTestElement(final TestElement element) { asyncApiSampler.setAsyncApiFile(asyncApiFile); if (serverComboBox.getSelectedIndex() > -1) { asyncApiSampler.setAsyncApiServerName(((AsyncApiServer) serverComboBox.getSelectedItem()).getName()); + asyncApiSampler.setBrokerConfiguration(mapVectorConf(brokerFieldModel.getDataVector())); } if (topicComboBox.getSelectedIndex() > -1) { - asyncApiSampler.setAsyncApiSchemaName(((AsyncApiSchema) topicComboBox.getSelectedItem()).getTopicName()); + final var selectedSchema = (AsyncApiSchema) topicComboBox.getSelectedItem(); + asyncApiSampler.setAsyncApiSchemaName(selectedSchema.getTopicName()); + asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } @@ -129,6 +135,31 @@ public void modifyTestElement(final TestElement element) { configureTestElement(element); } + private List mapVectorConf(final Vector dataVector) { + final var mapResult = new ArrayList(); + for (Vector v : dataVector) { + mapResult.add(PropertyMapping + .builder() + .propertyName(v.get(0).toString()) + .propertyValue(v.get(1).toString()) + .build()); + } + return mapResult; + } + + private List mapVector(final Vector dataVector) { + final var mapResult = new ArrayList(); + for (Vector v : dataVector) { + mapResult.add(FieldValueMapping + .builder() + .fieldName(v.get(0).toString()) + .fieldType(v.get(1).toString()) + .fieldValueList(v.get(3).toString()) + .build()); + } + return mapResult; + } + @Override public void configure(final TestElement element) { super.configure(element); @@ -178,16 +209,16 @@ private Collection> prepareSRServer(final AsyncApiSR schema } private Collection> prepareServer(final AsyncApiServer asyncApiServer) { - final var propertylist = new ArrayList>(); + final var propertyList = new ArrayList>(); if (Objects.nonNull(asyncApiServer)) { final var serverProps = asyncApiServer.getPropertiesMap(); - propertylist.add(Pair.of(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, serverProps.get("url"))); + propertyList.add(Pair.of(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, serverProps.get("url"))); CollectionUtils.select(SamplerUtil .getCommonProducerDefaultParameters(), property -> !property.getName().equalsIgnoreCase(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)) - .forEach(jMeterProperty -> propertylist.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getStringValue()))); + .forEach(jMeterProperty -> propertyList.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getStringValue()))); } - return propertylist; + return propertyList; } private void init() { @@ -308,7 +339,8 @@ private JPanel createSchemaTab() { topicComboBox.setRenderer(new ApiSchemaRenderer()); topicComboBox.addActionListener(this::topicComboActionListener); schemaTab.add(topicComboBox, BorderLayout.NORTH); - schemaTab.add(new JScrollPane(new JTable(schemaFieldModel)), BorderLayout.CENTER); + final var schemaTable = new JTable(schemaFieldModel); + schemaTab.add(new JScrollPane(schemaTable), BorderLayout.CENTER); return schemaTab; } From a29c662b31f5ddfbc3ff59b325e9ed04cc75931e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 16 Oct 2023 14:09:09 +0200 Subject: [PATCH 23/55] #332 Fix checkstyle issues --- .../kloadgen/common/tools/ApiTool.java | 18 ++-- .../asyncapi/AsyncApiExtractorImpl.java | 28 +++--- .../loadgen/impl/JsonSRLoadGenerator.java | 14 ++- .../kloadgen/model/FieldValueMapping.java | 2 +- .../kloadgen/processor/SchemaProcessor.java | 4 +- .../impl/JsonObjectCreatorFactory.java | 2 +- .../kloadgen/sampler/AsyncApiSampler.java | 98 +++++++++---------- .../sampler/gui/AsyncApiSamplerGui.java | 61 ++++++++++-- 8 files changed, 139 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java index b58aec34..f4c8de13 100644 --- a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -1,14 +1,20 @@ package com.sngular.kloadgen.common.tools; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.collections4.Transformer; import org.apache.commons.lang3.StringUtils; -import java.util.*; -import java.util.Map.Entry; - public final class ApiTool { public static final String FORMAT = "format"; @@ -255,10 +261,6 @@ public static boolean isDateTime(final JsonNode schema) { return isDateTime; } - public static List findContentSchemas(final JsonNode schema) { - return hasNode(schema, "content") ? schema.findValues("schema") : Collections.emptyList(); - } - public static boolean checkIfRequired(final JsonNode schema, final String fieldName) { boolean isRequired = false; if (hasNode(schema, REQUIRED)) { @@ -274,6 +276,4 @@ private static Transformer getTextValue() { return JsonNode::asText; } -/* protected static String findValue(final JsonNode message, final String key) { - }*/ } diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 43e08127..1c536f8b 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -124,19 +124,21 @@ private List processPayload(final JsonNode finalPayload, fina for (Iterator> it = ApiTool.getProperties(finalPayload); it.hasNext();) { final var property = it.next(); final var propertyDef = property.getValue(); + final var propertyName = calculateName(property.getKey(), root); if (ApiTool.hasRef(propertyDef)) { final var solvedPayload = solveRef(propertyDef, components, antiLoopList, "schemas"); if (Objects.nonNull(solvedPayload)) { - fieldList.addAll(processPayload(solvedPayload, calculateName(property.getKey(), root), components, antiLoopList)); + fieldList.addAll(processPayload(solvedPayload, propertyName, components, antiLoopList)); } } else if (COMPLEX_TYPES.contains(ApiTool.getType(propertyDef)) || ApiTool.hasAdditionalProperties(propertyDef)) { - fieldList.addAll(calculatePayload(propertyDef, calculateName(property.getKey(), root), components, antiLoopList)); + fieldList.addAll(calculatePayload(propertyDef, propertyName, components, antiLoopList)); } else { fieldList.add(FieldValueMapping .builder() - .fieldName(calculateName(property.getKey(), root)) - .fieldType(ApiTool.getType(propertyDef)) + .fieldName(propertyName) + .fieldType(getType(propertyDef)) .fieldValueList(hasValues(propertyDef)) + .required(ApiTool.checkIfRequired(propertyDef, property.getKey())) .constraints(getConstraints(propertyDef)) .build()); } @@ -147,22 +149,24 @@ private List processPayload(final JsonNode finalPayload, fina .fieldName(calculateName(null, root)) .fieldType(getType(finalPayload)) .fieldValueList(hasValues(finalPayload)) + .required(true) .constraints(getConstraints(finalPayload)) .build()); } return fieldList; } - private String getType(JsonNode finalPayload) { + private String getType(final JsonNode finalPayload) { String type = ApiTool.getType(finalPayload); if (ApiTool.hasFormat(finalPayload)) { - type = switch (ApiTool.getFormat(finalPayload)) { - case "date-time" -> "datetime"; - case "int64" -> "long"; - case "double" -> "double"; - case "date" -> "date"; - default -> ApiTool.getType(finalPayload); - }; + type = switch (ApiTool.getFormat(finalPayload)) { + case "date-time" -> "datetime"; + case "int64" -> "long"; + case "double" -> "double"; + case "date" -> "date"; + case "string" -> ApiTool.isEnum(finalPayload) ? "enum" : "string"; + default -> ApiTool.getType(finalPayload); + }; } return type; diff --git a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java index f5b9f677..5f45062c 100644 --- a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java +++ b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java @@ -10,6 +10,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; @@ -63,9 +64,16 @@ public void setUpGenerator(final List fieldExprMappings) { } public EnrichedRecord nextMessage() { - return EnrichedRecord.builder().schemaMetadata( - metadata.getLeft().getSchemaMetadataAdapter() - ).genericRecord(jsonSchemaProcessor.next()).build(); + final EnrichedRecord.EnrichedRecordBuilder builder = EnrichedRecord.builder(); + + if (Objects.nonNull(metadata)) { + builder.schemaMetadata( + metadata.getLeft().getSchemaMetadataAdapter() + ); + } + builder.genericRecord(jsonSchemaProcessor.next()).build(); + + return builder.build(); } } diff --git a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java index eccd3438..48da718f 100644 --- a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java +++ b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java @@ -169,7 +169,7 @@ public final void setConstraints(final Map constrain } public final Object[] getProperties() { - return new Object[] {getFieldName(), getFieldType(), getValueLength(), getFieldValuesList()}; + return new Object[] {getFieldName(), getFieldType(), getValueLength(), getRequired(), getFieldValuesList()}; } public static final class FieldValueMappingBuilder { diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index 5b6d3c58..a278e650 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -21,6 +21,7 @@ import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import lombok.SneakyThrows; +import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.RandomUtils; public class SchemaProcessor { @@ -166,8 +167,7 @@ private void makeFieldValueMappingRequired(final FieldValueMapping fieldValueMap private ArrayDeque calculateFieldsToProcess() { final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); - return initialFieldExpMappingsQueue.stream().filter(fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue)) - .collect(Collectors.toCollection(ArrayDeque::new)); + return new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); } private boolean shouldProcessField(final FieldValueMapping fieldValueMapping, final ArrayDeque initialFieldExpMappingsQueue) { diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/JsonObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/JsonObjectCreatorFactory.java index d9b97298..909e2d40 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/JsonObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/JsonObjectCreatorFactory.java @@ -123,7 +123,7 @@ public final boolean isOptionalFieldAccordingToSchema(final String completeField } @Override - public Object getRootNode(final String rootNode) { + public final Object getRootNode(final String rootNode) { return entity.get(rootNode); } diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 9b7197d8..4a257ab4 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.Serializable; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -10,6 +11,7 @@ import java.util.concurrent.ExecutionException; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; @@ -20,14 +22,15 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.model.PropertyMapping; import com.sngular.kloadgen.serializer.EnrichedRecord; -import com.sngular.kloadgen.util.ProducerKeysHelper; -import org.apache.commons.lang3.StringUtils; +import com.sngular.kloadgen.serializer.GenericJsonRecordSerializer; +import com.sngular.kloadgen.util.PropsKeysHelper; import org.apache.jmeter.config.ConfigTestElement; import org.apache.jmeter.gui.GUIMenuSortOrder; import org.apache.jmeter.samplers.AbstractSampler; import org.apache.jmeter.samplers.Entry; import org.apache.jmeter.samplers.SampleResult; -import org.apache.jmeter.testelement.property.ObjectProperty; +import org.apache.jmeter.testelement.property.CollectionProperty; +import org.apache.jmeter.testelement.property.TestElementProperty; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; @@ -42,11 +45,9 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; - private transient AsyncApiFile asyncApiFile; - private transient ApiExtractor apiExtractor; - private String asyncApiFileStr; + private JsonNode asyncApiFileNode; private transient BaseLoadGenerator generator; @@ -54,12 +55,11 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { public AsyncApiSampler() { apiExtractor = new AsyncApiExtractorImpl(); + generator = new JsonSRLoadGenerator(); } @Override public final boolean applies(final ConfigTestElement configElement) { - - generator = new JsonSRLoadGenerator(); return super.applies(configElement); } @@ -67,7 +67,8 @@ public final boolean applies(final ConfigTestElement configElement) { public final SampleResult sample(final Entry entry) { final var sampleResult = new SampleResult(); - try (final KafkaProducer producer = new KafkaProducer<>(extractProps(getAsyncApiServerName()))) { + sampleResult.sampleStart(); + try (final KafkaProducer producer = new KafkaProducer<>(extractProps())) { generator.setUpGenerator(getSchemaFieldConfiguration()); final var messageVal = generator.nextMessage(); if (Objects.nonNull(messageVal)) { @@ -88,61 +89,39 @@ public final SampleResult sample(final Entry entry) { LOG.error("Failed to send message", e); fillSampleResult(sampleResult, e.getMessage() != null ? e.getMessage() : "", false); } - sampleResult.sampleStart(); return sampleResult; } - private Map extractProps(final String asyncApiServerName) { + private Map extractProps() { final var properties = new HashMap(); - final var asyncApiBrokerProps = apiExtractor.getBrokerData(asyncApiFile).get(asyncApiServerName).getPropertiesMap(); - SamplerUtil.getCommonProducerDefaultParameters().forEach(property -> - properties.put(property.getName(), property.getStringValue())); - properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, asyncApiBrokerProps.get("url")); - properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "GenericJsonRecordSerializer.class"); - properties.put(ProducerKeysHelper.KAFKA_TOPIC_CONFIG, getAsyncApiSchemaName()); + getBrokerConfiguration().forEach(property -> properties.put(property.getPropertyName(), property.getPropertyValue())); + properties.put(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY, Boolean.FALSE); + properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); + properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); return properties; } - public final String getAsyncApiFileStr() throws JsonProcessingException { - return mapper.writeValueAsString(asyncApiFileStr); - } - - public final void setAsyncApiFileStr(String asyncApiFileStr) { - this.asyncApiFileStr = asyncApiFileStr; - try { - this.asyncApiFile = mapper.createParser(asyncApiFileStr).readValueAs(AsyncApiFile.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public final AsyncApiFile getAsyncApiFile() { + public final AsyncApiFile getAsyncApiFileNode() { + AsyncApiFile asyncApiFile = null; try { - if (Objects.isNull(asyncApiFile)) { - this.asyncApiFileStr = this.getPropertyAsString("asyncapifilestr"); - if (!StringUtils.isEmpty(asyncApiFileStr)) { - asyncApiFile = apiExtractor.processNode(mapper.readTree(this.getPropertyAsString("asyncapifilestr"))); - } + this.asyncApiFileNode = mapper.readTree(this.getPropertyAsString("asyncapifilestr")); + if (Objects.nonNull(asyncApiFile)) { + asyncApiFile = apiExtractor.processNode(asyncApiFileNode); } } catch (IOException e) { - throw new RuntimeException(e); + throw new KLoadGenException(e); } return asyncApiFile; } - public final void setAsyncApiFile(final AsyncApiFile asyncApiFile) { + public void setAsyncApiFileNode(final JsonNode asyncApiFileNode) { + this.asyncApiFileNode = asyncApiFileNode; try { - this.asyncApiFileStr = mapper.writeValueAsString(asyncApiFile.getAsyncApiFileNode()); - this.setProperty("asyncapifilestr", asyncApiFileStr); + this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFileNode)); } catch (JsonProcessingException e) { - throw new RuntimeException(e); + throw new KLoadGenException(e); } - this.asyncApiFile = asyncApiFile; - } - - public final String getAsyncApiServerName() { - return this.getPropertyAsString("asyncApiServerName"); } public final void setAsyncApiServerName(final String asyncApiServerName) { @@ -150,19 +129,38 @@ public final void setAsyncApiServerName(final String asyncApiServerName) { } public final void setSchemaFieldConfiguration(final List asyncApiServerName) { - this.setProperty(new ObjectProperty("schemaFieldConfiguration", asyncApiServerName)); + this.setProperty(new CollectionProperty("schemaFieldConfiguration", asyncApiServerName)); } public final List getSchemaFieldConfiguration() { - return (List) this.getProperty("schemaFieldConfiguration").getObjectValue(); + final List propertyList = new ArrayList<>(); + for (TestElementProperty elementProperty : (List) this.getProperty("schemaFieldConfiguration").getObjectValue()) { + propertyList.add(FieldValueMapping + .builder() + .fieldName(elementProperty.getElement().getPropertyAsString("fieldName")) + .fieldType(elementProperty.getElement().getPropertyAsString("fieldType")) + .required(elementProperty.getElement().getPropertyAsBoolean("required", false)) + .valueLength(elementProperty.getElement().getPropertyAsInt("valueLength", 0)) + .fieldValueList(elementProperty.getElement().getPropertyAsString("fieldValueList")) + .build()); + } + return propertyList; } public final void setBrokerConfiguration(final List asyncApiServerName) { - this.setProperty(new ObjectProperty("schemaFieldConfiguration", asyncApiServerName)); + this.setProperty(new CollectionProperty("brokerConfiguration", asyncApiServerName)); } public final List getBrokerConfiguration() { - return (List) this.getProperty("schemaFieldConfiguration").getObjectValue(); + final List propertyList = new ArrayList<>(); + for (TestElementProperty elementProperty : (List) this.getProperty("brokerConfiguration").getObjectValue()) { + propertyList.add(PropertyMapping + .builder() + .propertyName(elementProperty.getElement().getPropertyAsString("propertyName")) + .propertyValue(elementProperty.getElement().getPropertyAsString("propertyValue")) + .build()); + } + return propertyList; } public final String getAsyncApiSchemaName() { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 956f6ead..98f7aa74 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -54,8 +54,10 @@ import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; +import org.apache.jmeter.config.Argument; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.testelement.property.JMeterProperty; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; @@ -70,7 +72,7 @@ public final class AsyncApiSamplerGui extends AbstractSamplerGui { private JTextField asyncApiFileTextField; - private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Field Values List"}, 20); + private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Required", "Field Values List"}, 20); private final DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); @@ -119,18 +121,18 @@ public void modifyTestElement(final TestElement element) { super.configureTestElement(element); if (element instanceof AsyncApiSampler asyncApiSampler) { if (Objects.nonNull(asyncApiFile)) { - asyncApiSampler.setAsyncApiFile(asyncApiFile); - if (serverComboBox.getSelectedIndex() > -1) { + asyncApiSampler.setAsyncApiFileNode(asyncApiFile.getAsyncApiFileNode()); + if (serverComboBox.getItemCount() > 0) { asyncApiSampler.setAsyncApiServerName(((AsyncApiServer) serverComboBox.getSelectedItem()).getName()); asyncApiSampler.setBrokerConfiguration(mapVectorConf(brokerFieldModel.getDataVector())); } - if (topicComboBox.getSelectedIndex() > -1) { - final var selectedSchema = (AsyncApiSchema) topicComboBox.getSelectedItem(); + final var selectedSchema = (AsyncApiSchema) topicComboBox.getSelectedItem(); + if (Objects.nonNull(selectedSchema)) { asyncApiSampler.setAsyncApiSchemaName(selectedSchema.getTopicName()); asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } - // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } + // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } configureTestElement(element); } @@ -154,7 +156,9 @@ private List mapVector(final Vector dataVector) { .builder() .fieldName(v.get(0).toString()) .fieldType(v.get(1).toString()) + .valueLength(Integer.parseInt(v.get(2).toString())) .fieldValueList(v.get(3).toString()) + .required(true) .build()); } return mapResult; @@ -164,8 +168,10 @@ private List mapVector(final Vector dataVector) { public void configure(final TestElement element) { super.configure(element); if (element instanceof AsyncApiSampler) { - asyncApiFile = ((AsyncApiSampler) element).getAsyncApiFile(); - populateData(); + asyncApiFile = ((AsyncApiSampler) element).getAsyncApiFileNode(); + if (Objects.nonNull(asyncApiFile)) { + populateData((AsyncApiSampler) element); + } } } @@ -185,11 +191,29 @@ private void actionFileChooser(final ActionEvent event) { } } + private void populateData(final AsyncApiSampler element) { + + asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); + serverComboBox.setSelectedIndex(0); + final Collection> propertyList = new ArrayList<>(); + element.getBrokerConfiguration() + .forEach(propertyMapping -> + propertyList.add(Pair.of(propertyMapping.getPropertyName(), propertyMapping.getPropertyValue()))); + fillTable(brokerFieldModel, propertyList); + /*final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); + if (!schemaRegistryList.isEmpty()) { + fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); + }*/ + asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); + topicComboBox.setSelectedIndex(0); + fillTable(schemaFieldModel, element.getSchemaFieldConfiguration()); + } + private void populateData() { if (Objects.nonNull(asyncApiFile)) { asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); serverComboBox.setSelectedIndex(0); - fillTable(brokerFieldModel, prepareServer(asyncApiExtractor.getBrokerData(asyncApiFile).get(serverComboBox.getSelectedItem()))); + fillTable(brokerFieldModel, prepareServer((AsyncApiServer) serverComboBox.getSelectedItem())); final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); if (!schemaRegistryList.isEmpty()) { fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); @@ -216,11 +240,16 @@ private Collection> prepareServer(final AsyncApiServer asyn CollectionUtils.select(SamplerUtil .getCommonProducerDefaultParameters(), property -> !property.getName().equalsIgnoreCase(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)) - .forEach(jMeterProperty -> propertyList.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getStringValue()))); + .forEach(jMeterProperty -> extractArgument(jMeterProperty, propertyList)); } return propertyList; } + private static boolean extractArgument(final JMeterProperty jMeterProperty, final ArrayList> propertyList) { + final var argument = (Argument) jMeterProperty.getObjectValue(); + return propertyList.add(Pair.of(argument.getPropertyAsString("Argument.name"), argument.getPropertyAsString("Argument.value"))); + } + private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); @@ -302,6 +331,18 @@ private void fillTable(final DefaultTableModel sche } } + private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + for (var data : schemaData) { + schemaFields.addRow(data.getProperties()); + } + } + } + private Object[] dataToRow(final Pair data) { return new Object[] {data.getKey(), data.getValue()}; } From 7549d3a636ffea8285850f797e1eb0297a4d5ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 16 Oct 2023 19:43:45 +0200 Subject: [PATCH 24/55] #332 Fix checkstyle issues --- .../kloadgen/sampler/AsyncApiSampler.java | 25 +++++++++++-------- .../sampler/gui/AsyncApiSamplerGui.java | 20 +++++++++------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 4a257ab4..ab34c94f 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -45,11 +45,11 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; - private transient ApiExtractor apiExtractor; + private final transient ApiExtractor apiExtractor; private JsonNode asyncApiFileNode; - private transient BaseLoadGenerator generator; + private final transient BaseLoadGenerator generator; private final transient ObjectMapper mapper = new ObjectMapper(); @@ -67,6 +67,7 @@ public final boolean applies(final ConfigTestElement configElement) { public final SampleResult sample(final Entry entry) { final var sampleResult = new SampleResult(); + sampleResult.setThreadName("AsyncApi Sampler"); sampleResult.sampleStart(); try (final KafkaProducer producer = new KafkaProducer<>(extractProps())) { generator.setUpGenerator(getSchemaFieldConfiguration()); @@ -104,22 +105,24 @@ private Map extractProps() { public final AsyncApiFile getAsyncApiFileNode() { AsyncApiFile asyncApiFile = null; - try { - this.asyncApiFileNode = mapper.readTree(this.getPropertyAsString("asyncapifilestr")); - if (Objects.nonNull(asyncApiFile)) { - asyncApiFile = apiExtractor.processNode(asyncApiFileNode); + if (Objects.isNull(asyncApiFileNode)) { + try { + asyncApiFileNode = mapper.readTree(this.getPropertyAsString("asyncapifilestr")); + } catch (final IOException e) { + throw new KLoadGenException(e); } - } catch (IOException e) { - throw new KLoadGenException(e); + } + if (Objects.nonNull(asyncApiFileNode) && !asyncApiFileNode.isMissingNode()) { + asyncApiFile = apiExtractor.processNode(asyncApiFileNode); } return asyncApiFile; } - public void setAsyncApiFileNode(final JsonNode asyncApiFileNode) { + public final void setAsyncApiFileNode(final JsonNode asyncApiFileNode) { this.asyncApiFileNode = asyncApiFileNode; try { this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFileNode)); - } catch (JsonProcessingException e) { + } catch (final JsonProcessingException e) { throw new KLoadGenException(e); } } @@ -164,7 +167,7 @@ public final List getBrokerConfiguration() { } public final String getAsyncApiSchemaName() { - return this.getPropertyAsString("asyncApiServerName"); + return this.getPropertyAsString("asyncapischemaname"); } public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 98f7aa74..a4d176d0 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -111,9 +111,7 @@ public String getLabelResource() { @Override public TestElement createTestElement() { - final var testElement = new AsyncApiSampler(); - modifyTestElement(testElement); - return testElement; + return new AsyncApiSampler(); } @Override @@ -157,8 +155,8 @@ private List mapVector(final Vector dataVector) { .fieldName(v.get(0).toString()) .fieldType(v.get(1).toString()) .valueLength(Integer.parseInt(v.get(2).toString())) - .fieldValueList(v.get(3).toString()) - .required(true) + .fieldValueList(v.get(4).toString()) + .required((Boolean) v.get(3)) .build()); } return mapResult; @@ -193,6 +191,7 @@ private void actionFileChooser(final ActionEvent event) { private void populateData(final AsyncApiSampler element) { + serverComboBox.removeAllItems(); asyncApiFile.getApiServerMap().forEach((name, value) -> serverComboBox.addItem(value)); serverComboBox.setSelectedIndex(0); final Collection> propertyList = new ArrayList<>(); @@ -204,6 +203,7 @@ private void populateData(final AsyncApiSampler element) { if (!schemaRegistryList.isEmpty()) { fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); }*/ + topicComboBox.removeAllItems(); asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); topicComboBox.setSelectedIndex(0); fillTable(schemaFieldModel, element.getSchemaFieldConfiguration()); @@ -388,14 +388,18 @@ private JPanel createSchemaTab() { private void topicComboActionListener(final ActionEvent event) { final JComboBox cb = (JComboBox)event.getSource(); final var selectedSchema = (AsyncApiSchema) cb.getSelectedItem(); - fillTable(schemaFieldModel, selectedSchema.getProperties()); + if (Objects.nonNull(selectedSchema)) { + fillTable(schemaFieldModel, selectedSchema.getProperties()); + } } private void registryComboActionListener(ActionEvent actionEvent) { } private void serverChooseActionListener(ActionEvent actionEvent) { - final JComboBox cb = (JComboBox)actionEvent.getSource(); - fillTable(brokerFieldModel, prepareServer((AsyncApiServer) cb.getSelectedItem())); + final JComboBox serverChoose = (JComboBox)actionEvent.getSource(); + if (Objects.nonNull(serverChoose)) { + fillTable(brokerFieldModel, prepareServer((AsyncApiServer) serverChoose.getSelectedItem())); + } } } From 09acc9c5699021ed9d8df8768f204365de2137af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 16 Oct 2023 23:07:28 +0200 Subject: [PATCH 25/55] #332 Fix checkstyle issues --- src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java | 2 +- .../com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java | 2 ++ .../com/sngular/kloadgen/sampler/asyncapisampler.properties | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index ab34c94f..7ccd35b1 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -38,7 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@GUIMenuSortOrder(Integer.MAX_VALUE) +@GUIMenuSortOrder(Integer.MIN_VALUE) public class AsyncApiSampler extends AbstractSampler implements Serializable { private static final Logger LOG = LoggerFactory.getLogger(AsyncApiSampler.class); diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index a4d176d0..d39b52f9 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -55,6 +55,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.config.Argument; +import org.apache.jmeter.gui.TestElementMetadata; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.JMeterProperty; @@ -62,6 +63,7 @@ import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; +@TestElementMetadata(labelResource = "async_api_sampler") public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); diff --git a/src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties b/src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties new file mode 100644 index 00000000..972891dd --- /dev/null +++ b/src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties @@ -0,0 +1 @@ +async_api_sampler=AsyncApi Sampler \ No newline at end of file From e78d5702a23e62615d5e25ae7e923c2db461fdf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Thu, 19 Oct 2023 09:07:03 +0200 Subject: [PATCH 26/55] #332 Fix checkstyle issues --- pom.xml | 4 +- .../asyncapi/AsyncApiExtractorImpl.java | 12 ++--- .../extractors/ExtractorFactory.java | 50 +++++++------------ .../avro/AvroConfluentExtractor.java | 7 +-- .../kloadgen/sampler/AsyncApiSampler.java | 4 +- .../sampler/gui/AsyncApiSamplerGui.java | 25 ++++------ .../impl/ConfluentParsedSchemaMetadata.java | 19 +++---- ...es => AsyncApiSamplerResources.properties} | 0 .../avro/AvroConfluentExtractorTest.java | 19 +++---- 9 files changed, 60 insertions(+), 80 deletions(-) rename src/main/resources/com/sngular/kloadgen/sampler/{asyncapisampler.properties => AsyncApiSamplerResources.properties} (100%) diff --git a/pom.xml b/pom.xml index 74286d73..5ad1f706 100644 --- a/pom.xml +++ b/pom.xml @@ -305,7 +305,7 @@ 5.8.2 7.1.1 2.4.1.Final - 3.1.0 + 3.5.1 1.18.22 0.9.5 4.2.0 @@ -464,7 +464,7 @@ com.github.everit-org.json-schema org.everit.json.schema - 1.14.0 + 1.14.2 diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java index 1c536f8b..6a91e9ae 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java +++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java @@ -40,7 +40,7 @@ public class AsyncApiExtractorImpl implements ApiExtractor { @Override public final AsyncApiFile processFile(final File apiFile) { - AsyncApiFile asyncApiFile = null; + AsyncApiFile asyncApiFile; try { final JsonNode openApi = om.readTree(apiFile); asyncApiFile = processNode(openApi); @@ -80,7 +80,7 @@ private AsyncApiSchema mapNodeToSchema(final Map components, f final var message = ApiTool.findNodeValue(node, "message"); if (ApiTool.hasNode(message, "bindings")) { builder.key(true); - // builder.keyType(ApiTool.findValue(message, "key")); + // builder.keyType(ApiTool.findValue(message, "key")); } builder.model(messageToFieldList(message, components, antiLoopList)); return builder.build(); @@ -138,7 +138,7 @@ private List processPayload(final JsonNode finalPayload, fina .fieldName(propertyName) .fieldType(getType(propertyDef)) .fieldValueList(hasValues(propertyDef)) - .required(ApiTool.checkIfRequired(propertyDef, property.getKey())) + .required(ApiTool.checkIfRequired(finalPayload, property.getKey())) .constraints(getConstraints(propertyDef)) .build()); } @@ -172,8 +172,8 @@ private String getType(final JsonNode finalPayload) { return type; } - private Map getConstraints(JsonNode finalPayload) { - Map constraints = new EnumMap<>(ConstraintTypeEnum.class); + private Map getConstraints(final JsonNode finalPayload) { + final Map constraints = new EnumMap<>(ConstraintTypeEnum.class); if (ApiTool.hasNode(finalPayload, "minLength")) { constraints.put(ConstraintTypeEnum.MIN_LENGTH, ApiTool.getNodeAsString(finalPayload, "minLength")); } @@ -199,7 +199,7 @@ private Map getConstraints(JsonNode finalPayload) { return constraints; } - private String hasValues(JsonNode propertyDef) { + private String hasValues(final JsonNode propertyDef) { String values = null; if (ApiTool.isEnum(propertyDef)) { values = String.join(",", ApiTool.getEnumValues(propertyDef)); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index 3c1e143b..15193f05 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -21,41 +21,31 @@ import org.apache.jmeter.threads.JMeterContextService; public final class ExtractorFactory { - private static AvroExtractor avroExtractor = new AvroExtractor(); + private static final AvroExtractor avroExtractor = new AvroExtractor(); - private static JsonExtractor jsonExtractor = new JsonExtractor(); + private static final JsonExtractor jsonExtractor = new JsonExtractor(); - private static ProtobuffExtractor protobuffExtractor = new ProtobuffExtractor(); + private static final ProtobuffExtractor protobuffExtractor = new ProtobuffExtractor(); private ExtractorFactory() { } public static ExtractorRegistry getExtractor(final String schemaType, final String schemaRegistryEnum) { - SchemaRegistryEnum registryEnum = getSchemaRegistry(schemaRegistryEnum); - if (schemaType != null && EnumUtils.isValidEnum(SchemaTypeEnum.class, schemaType.toUpperCase())) { - final ExtractorRegistry response; - switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) { - case JSON: - response = jsonExtractor; - break; - case AVRO: - response = avroExtractor; - break; - case PROTOBUF: - response = protobuffExtractor; - break; - default: - throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); - } + final ExtractorRegistry response = switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) { + case JSON -> jsonExtractor; + case AVRO -> avroExtractor; + case PROTOBUF -> protobuffExtractor; + default -> throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); + }; return response; } else { throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); } } - public static SchemaRegistryEnum getSchemaRegistry(String schemaRegistryEnum) { + public static SchemaRegistryEnum getSchemaRegistry(final String schemaRegistryEnum) { if (schemaRegistryEnum != null && EnumUtils.isValidEnum(SchemaRegistryEnum.class, schemaRegistryEnum.toUpperCase())) { return SchemaRegistryEnum.valueOf(schemaRegistryEnum.toUpperCase()); } else { @@ -67,9 +57,8 @@ public static Pair> flatPropertiesList(final Str final Properties properties = JMeterContextService.getContext().getProperties(); final var schemaParsed = JMeterHelper.getParsedSchema(subjectName, properties); final String registryName = properties.getProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); - String schemaType = null; final ParsedSchemaAdapter parsedSchemaAdapter = schemaParsed.getParsedSchemaAdapter(); - schemaType = parsedSchemaAdapter.getType(); + final String schemaType = parsedSchemaAdapter.getType(); List attributeList = new ArrayList<>(); SchemaRegistryEnum schemaRegistryEnum = SchemaRegistryEnum.valueOf(registryName.toUpperCase()); @@ -77,17 +66,12 @@ public static Pair> flatPropertiesList(final Str Object schema = null; if (Objects.nonNull(registryName)) { //TODO change parser - switch (schemaRegistryEnum) { - case APICURIO: - schema = ((ApicurioParsedSchemaMetadata) parsedSchemaAdapter).getSchema(); - break; - case CONFLUENT: - schema = parsedSchemaAdapter.getRawSchema(); - break; - default: - throw new KLoadGenException("Schema Registry Type nos supported " + registryName.toUpperCase()); - } - attributeList = getExtractor(schemaType,registryName.toUpperCase()).processSchema(schema, schemaRegistryEnum); + schema = switch (schemaRegistryEnum) { + case APICURIO -> ((ApicurioParsedSchemaMetadata) parsedSchemaAdapter).getSchema(); + case CONFLUENT -> parsedSchemaAdapter.getRawSchema(); + default -> throw new KLoadGenException("Schema Registry Type nos supported " + registryName.toUpperCase()); + }; + attributeList = getExtractor(schemaType, registryName.toUpperCase()).processSchema(schema, schemaRegistryEnum); } return Pair.of(schemaType, attributeList); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java index 7405c3ab..4dc1513b 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java @@ -5,11 +5,12 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import io.confluent.kafka.schemaregistry.avro.AvroSchema; +import org.apache.avro.Schema; -public class AvroConfluentExtractor extends AbstractAvroFileExtractor implements Extractor { +public class AvroConfluentExtractor extends AbstractAvroFileExtractor implements Extractor { - public final List processSchema(final AvroSchema schema) { - return this.processSchemaDefault(schema.rawSchema()); + public final List processSchema(final Schema schema) { + return this.processSchemaDefault(schema); } public final List getSchemaNameList(final String schema) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 7ccd35b1..8843eed4 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -142,9 +142,9 @@ public final List getSchemaFieldConfiguration() { .builder() .fieldName(elementProperty.getElement().getPropertyAsString("fieldName")) .fieldType(elementProperty.getElement().getPropertyAsString("fieldType")) - .required(elementProperty.getElement().getPropertyAsBoolean("required", false)) + .required(elementProperty.getElement().getPropertyAsBoolean("required", true)) .valueLength(elementProperty.getElement().getPropertyAsInt("valueLength", 0)) - .fieldValueList(elementProperty.getElement().getPropertyAsString("fieldValueList")) + .fieldValueList(elementProperty.getElement().getPropertyAsString("fieldValuesList")) .build()); } return propertyList; diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index d39b52f9..f0ec87fc 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -42,7 +42,6 @@ import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.AsyncApiAbstract; import com.sngular.kloadgen.extractor.model.AsyncApiFile; import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.extractor.model.AsyncApiSchema; @@ -55,7 +54,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.config.Argument; -import org.apache.jmeter.gui.TestElementMetadata; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.JMeterProperty; @@ -63,7 +61,6 @@ import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; -@TestElementMetadata(labelResource = "async_api_sampler") public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); @@ -185,7 +182,7 @@ private void actionFileChooser(final ActionEvent event) { asyncApiFileTextField.setText(apiFile.getAbsolutePath()); asyncApiFile = asyncApiExtractor.processFile(apiFile); populateData(); - } catch (KLoadGenException ex) { + } catch (final KLoadGenException ex) { JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); } } @@ -230,7 +227,7 @@ private Collection> prepareSRServer(final AsyncApiSR schema final var propertyList = new ArrayList>(); propertyList.add(Pair.of(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, srPropoMap.get("url"))); propertyList.add(Pair.of(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, srPropoMap.get("type"))); - SchemaRegistryProperties.DEFAULTS.forEach(jMeterProperty -> propertyList.add(Pair.of(jMeterProperty.getName(), jMeterProperty.getPropertyValue()))); + SchemaRegistryProperties.DEFAULTS.forEach(jmeterproperty -> propertyList.add(Pair.of(jmeterproperty.getName(), jmeterproperty.getPropertyValue()))); return propertyList; } @@ -242,14 +239,14 @@ private Collection> prepareServer(final AsyncApiServer asyn CollectionUtils.select(SamplerUtil .getCommonProducerDefaultParameters(), property -> !property.getName().equalsIgnoreCase(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)) - .forEach(jMeterProperty -> extractArgument(jMeterProperty, propertyList)); + .forEach(jmeterproperty -> extractArgument(jmeterproperty, propertyList)); } return propertyList; } - private static boolean extractArgument(final JMeterProperty jMeterProperty, final ArrayList> propertyList) { - final var argument = (Argument) jMeterProperty.getObjectValue(); - return propertyList.add(Pair.of(argument.getPropertyAsString("Argument.name"), argument.getPropertyAsString("Argument.value"))); + private static void extractArgument(final JMeterProperty jmeterproperty, final ArrayList> propertyList) { + final var argument = (Argument) jmeterproperty.getObjectValue(); + propertyList.add(Pair.of(argument.getPropertyAsString("Argument.name"), argument.getPropertyAsString("Argument.value"))); } private void init() { @@ -311,7 +308,7 @@ private JTabbedPane createAsyncApiTabs() { return tabbedPanel; } - private void fillTable(final DefaultTableModel schemaFields, final Collection> schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final Collection> schemaData) { if (Objects.nonNull(schemaData)) { final var count = schemaFields.getRowCount(); for (var i = 0; i < count; i++) { @@ -321,7 +318,7 @@ private void fillTable(final DefaultTableModel sche } } - private void fillTable(final DefaultTableModel schemaFields, final Object[] schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final Object[] schemaData) { if (Objects.nonNull(schemaData)) { final var count = schemaFields.getRowCount(); for (var i = 0; i < count; i++) { @@ -333,7 +330,7 @@ private void fillTable(final DefaultTableModel sche } } - private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { + private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { if (Objects.nonNull(schemaData)) { final var count = schemaFields.getRowCount(); for (var i = 0; i < count; i++) { @@ -395,10 +392,10 @@ private void topicComboActionListener(final ActionEvent event) { } } - private void registryComboActionListener(ActionEvent actionEvent) { + private void registryComboActionListener(final ActionEvent actionEvent) { } - private void serverChooseActionListener(ActionEvent actionEvent) { + private void serverChooseActionListener(final ActionEvent actionEvent) { final JComboBox serverChoose = (JComboBox)actionEvent.getSource(); if (Objects.nonNull(serverChoose)) { fillTable(brokerFieldModel, prepareServer((AsyncApiServer) serverChoose.getSelectedItem())); diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java index a24ea866..799baf16 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java @@ -14,31 +14,27 @@ public class ConfluentParsedSchemaMetadata extends ParsedSchemaAdapter { private String canonicalString; - private Object rawSchema; + private Object rawSchema; - private ConfluentParsedSchemaMetadata(ParsedSchema parsedSchema){ + private ConfluentParsedSchemaMetadata(final ParsedSchema parsedSchema) { this.schemaType = parsedSchema.schemaType(); this.name = parsedSchema.name(); this.canonicalString = parsedSchema.canonicalString(); this.rawSchema = parsedSchema.rawSchema(); } - private ConfluentParsedSchemaMetadata(Schema schema){ + private ConfluentParsedSchemaMetadata(final Schema schema) { this.schemaType = schema.getType().getName(); this.name = schema.getName(); } - public ConfluentParsedSchemaMetadata(ProtobufSchema schema){ + public ConfluentParsedSchemaMetadata(final ProtobufSchema schema) { this.schemaType = schema.schemaType(); this.name = schema.name(); this.rawSchema = schema.rawSchema(); this.canonicalString = schema.canonicalString(); } - public ConfluentParsedSchemaMetadata() { - - } - public static ParsedSchemaAdapter parse(final ParsedSchema parsedSchema) { return new ConfluentParsedSchemaMetadata(parsedSchema); } @@ -46,17 +42,18 @@ public static ParsedSchemaAdapter parse(final ParsedSchema parsedSchema) { public static ParsedSchemaAdapter parse(final Schema schema) { return new ConfluentParsedSchemaMetadata(schema); } - public static ParsedSchemaAdapter parse (final ProtobufSchema schema){ + + public static ParsedSchemaAdapter parse (final ProtobufSchema schema) { return new ConfluentParsedSchemaMetadata(schema); } @Override - public String getType() { + public final String getType() { return this.schemaType; } @Override - public Object getRawSchema() { + public final Object getRawSchema() { return this.rawSchema; } } diff --git a/src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties b/src/main/resources/com/sngular/kloadgen/sampler/AsyncApiSamplerResources.properties similarity index 100% rename from src/main/resources/com/sngular/kloadgen/sampler/asyncapisampler.properties rename to src/main/resources/com/sngular/kloadgen/sampler/AsyncApiSamplerResources.properties diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java index 16c6d67c..6977c561 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java @@ -6,6 +6,7 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; import io.confluent.kafka.schemaregistry.avro.AvroSchema; +import org.apache.avro.Schema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,7 +16,7 @@ class AvroConfluentExtractorTest { private final FileHelper fileHelper = new FileHelper(); - private final Extractor avroConfluentExtractor = new AvroConfluentExtractor(); + private final Extractor avroConfluentExtractor = new AvroConfluentExtractor(); @Test @@ -24,7 +25,7 @@ void testFlatPropertiesEmbeddedAvros() throws Exception { final String testFile = fileHelper.getContent("/avro-files/embedded-avros-example-test.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(4) @@ -45,7 +46,7 @@ void testOptionalEnum() throws Exception { final String testFile = fileHelper.getContent("/avro-files/optionalEnum.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(1) @@ -68,7 +69,7 @@ void testFlatPropertiesOptionalMapArray() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testOptionalMap.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(8) @@ -97,7 +98,7 @@ void testFlatPropertiesOptionalMapArray() throws Exception { void testFlatPropertiesMap() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testMap.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(9) @@ -129,7 +130,7 @@ void testFlatPropertiesLogicalTypes() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testLogicalTypes.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(10) @@ -159,7 +160,7 @@ void testFlatPropertiesOptionalArray() throws Exception { final String testFile = fileHelper.getContent("/avro-files/issue.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -179,7 +180,7 @@ void testFlatPropertiesUnionRecordAvros() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testUnionRecord.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(8) @@ -209,7 +210,7 @@ void testFlatPropertiesRecordUnionReverseOrder() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testUnionReverseOrder.avsc"); final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); Assertions.assertThat(fieldValueMappingList) .hasSize(5) From 1b5836939fb550c0661bfde1cd9e2b45ffefd5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 25 Oct 2023 20:44:18 +0200 Subject: [PATCH 27/55] #384 Add documentation --- docs/_Sidebar.md | 1 + docs/asyncapi.md | 22 ++++++++++++++++++ docs/images/AsyncApiComponent-ComboBroker.png | Bin 0 -> 493241 bytes docs/images/AsyncApiComponent-FileLoaded.png | Bin 0 -> 439843 bytes .../images/AsyncApiComponent-SchemaLoaded.png | Bin 0 -> 382136 bytes docs/images/AsyncapiComponent.png | Bin 0 -> 236445 bytes 6 files changed, 23 insertions(+) create mode 100644 docs/asyncapi.md create mode 100644 docs/images/AsyncApiComponent-ComboBroker.png create mode 100644 docs/images/AsyncApiComponent-FileLoaded.png create mode 100644 docs/images/AsyncApiComponent-SchemaLoaded.png create mode 100644 docs/images/AsyncapiComponent.png diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index d6dc8f20..4a828bb7 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -16,6 +16,7 @@ - [Consumer configuration](consumer-configuration.md) - [Schemas](schemas.md) - [Schema Registry](schema-registry.md) + - [Asyncapi support](asyncapi.md) # Knowledge center - [How to run a test plan](how-to-run.md) diff --git a/docs/asyncapi.md b/docs/asyncapi.md new file mode 100644 index 00000000..5953c6eb --- /dev/null +++ b/docs/asyncapi.md @@ -0,0 +1,22 @@ +# Asyncapi Support + +Here you can find the way to use your asyncapi.yml definition to produce a performance load test. +The only requirement is to use the AsyncApi Sampler component. There you can load the asyncapi file into the plugin. + +![AsyncApi Component](images/AsyncapiComponent.png) + +Once the file is loaded, information will appear in the elements below. +First tab you can see the broker configuration where you can choose to which broker you want to connect to. + +![Broker Selection](images/AsyncApiComponent-ComboBroker.png) + +Once the broker has been choose the data will be loaded. By default the first server configuration will be selected + +![Developemnt Broker](images/AsyncApiComponent-FileLoaded.png) + +In order to choose which payload you want to use for the test just move to the second tab and use the combo to select which topic you want to use. +As for in AsyncApi specification channel/topic contains the payload will be transmitted. + +![Payload configuration](images/AsyncApiComponent-SchemaLoaded.png) + +Data generation use the same engine than the rest of the samplers so information from [schemas page](schemas.md) applu \ No newline at end of file diff --git a/docs/images/AsyncApiComponent-ComboBroker.png b/docs/images/AsyncApiComponent-ComboBroker.png new file mode 100644 index 0000000000000000000000000000000000000000..cd363ab5721414525dc8ac906a36c8372bdef8fd GIT binary patch literal 493241 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

(JBnK>IL^W4gNoy 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%0ApOCCs|PVFQ30tiv!KurNAshJ{tXTw9G_OR}rg+ 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‡z>+>Hw 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 NJYD@<);T3K0RUJMAT60zGL4flw|{k%2Yu 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

(JBnK>IL^W4gNoy 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 K@OKE+t5lHD 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ðKQ)Kd>(ZhJ$j}{UVfs~Jn7D(ExHz4; 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 z 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 z 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 z zvL7HsR1u^6D3lImnUb6|nv|Mx+aw>XN?t=+A;{3QEMVL#Yx8HCw-^>5Dqa3DT)Jsf zwZ@3Y%okLzZ7DG_?o#Knwy6Pob_u6rN8@+#z3Bz%!9MzuC=F1U#hHKqK(w%}8vLBO zx9P%E5*wc870v1Zl}Sa_Q0gNxT_fEm)narL2_B~eZN?$?TP>`Ph^kb>e5IhJkA6}I zHjk`cFUkY0KzYlN=AurjejEb+&sn2Saymm!Uv{2#NF+Kn)djeVy{S?o1z(5m5)xWE z97J;i@KzL#SxFA1tgkav&VdDZae|A_d{x3Bt@loP0R8CdlprL^X#6N%b5R~Zqhgi7 zO7|ge%En8wT3UwC#X`Wbx+TvQ;j^tBo#rD}Jq=L2SBXWy8IA;Y;`p3W%?s_P z{v2JdyXGT)5soZ9*?VRdKe!avmhXVcr@=Oqhl!%9tBQ&qMV__4Y!ySICD~}YMEN?o zoB@(@!Y)1q&gy>l#|lz0rEF^2_VMH&Sb#OcvL?E==so*@>TF zG?JCBBbU?+KT&mqUwE%289#yo&sj%jU3`KADP2Ae&d0kPks{7*VU{BLKWB?!X7jCZ z-z{L^ky-{>gb{5s709zhz0r(=H-Oh$G#fmW7Q@_VBdN{54?05s;{?vTJImVBw1gJ& zs1FSY0m$RH0#)&xK-T>wm}Lz{%=|#$b`eyOd5dpN;qlC3?=GBgs?k1c`y)(43TVC) z#tXJ!iu1$TtR3ijxQG^)28;P0onwvwLpdujdOO|$RKQf-hWWBH_j4}B&;9AZ?x^aO zty&4;HtuZ(w{=btLu;DIEMHH7A=06r7X#Vv%+Iyte`*(Hd0W%PRB!n*Wd32k>sdTsO9ks;L-fbAOrC`QdC>tz=|Q3Fi#Eo^3@Km!TJS$2XYB^=r2*bO7&ai)IVS zN>{(!EY&1KQnwXoiLCk3UDV9)srwEzQ7?5?1n>PAR|v86PSp}Drg>0D=IZnNDdY|n z3Mte+!vP6>G8`B}j%`CJPU97U9FgTZV7fn}&EVrkLipC8qr#3zDDAUXPF)7y65CO> zFY}~K3Hq(A*{6rj`&5PrD7(giUVbo8l;E@j=vj6HJ#@L-Wq2Icxq<#xGsTfp0eKG` zikn(_tOMjbtp;mhw)T`uS{!VNZ&r^yiw4e(jhebAPvO2jruvUz7cB#=LX~rvI~|&% zggP%XYZieat7qDe8*2J@$!05n0eXkGP6g@q2Le)A6V`z+Z*qg<6!OD68D2mFVZMEV z5SXU=BJ!JZ-qL4qB=}fuGAh46%_RieMZ*Eq=;L`uA9q^4+^@AL#a9@qMUwy#3Y0=UF#$d ztR}y~mGynJcq`nJE?}aUe|WG%a*T?-+x02MdtaabW1}L~4QkSU8@}Y60K+6ygU&?W zK~#QyD1qkJ%{!6HsN;C2J$UwiBo8=)>wB$5WB?wzy`=3yX7tq($EFdj&5_ksN3F5x zrL}cF2v4h)Q*2ebP=dLWH;Yn~8$b1xAX_D8zGf8-D`gU9Oj&_W2=$RwqtLb-GY$oF zA9W(BiaN97Ch;1@E-QL~Z5*+9^6Vg=0@N!eMR!MpZiCOP9tfs;cN&}-vED*!Sig6M zo=J}=Y?DR=HnaPP33inT%P;rnCgHp2&Q0@%>vY^e%C-@8RVhs(1K`q%KtAUyRy%&3 zlO1aogOwwWy`IcYKvSU@&bkT`Ohb%2OAbsMi1Z=hpti6Zo!x1YUthI^MR~Z<%7>Rc zbo(W^V;HpMPB7oK#YIn4gbU@Q1AtdF6yeCuShygj_E*Nf>YhEgc()bviFye^jn`Tk zpJ<=$@lo7m_4yKDbM4kPYFfun06p)A^&KR`{@!paulIQsSU)znSuizSpneAo!+vYB zy4=OfmZEGDhVm#)+F96Pc2ans9q=CzTSp^2=iK4qT05(t^eEpq zm8;y-9+wYB{v_L&3OP(Z^el*^h6be0ZCh37XS-Vby0uA{r;z$YU*VxiwvX@RUEi+e z-AiAIpz>k)Sc;^nj#)W7oxjlY-oE;{ac#}trFe2MV>v{v*ci~Q={079T?7CfBIjiK z19|J?_S4n-sW%^9v()hD-w;3R=8vG!Ehx17Ie9&6>1i4-O3h@slIXKwk-2iUftj^u zPk61mSh)CJgZLfc;!Wf~Jnak(#qI~oU!fK#J#Fwd_%Ut$_n0(`Sgs(!QVx{GFjXBi zN_r$%UF}v=(m-0JU)#yJxfQFX5Evr`H`#%Tn+e?BFMT`txlQ!?jwj#GUCZI?NR72N zCu0jXys}0ywlmu#u&W)GimB?Qdco1JiV9Sk4&A=f1hp3t>CtWceynB4e?pB;_-^lg zem|xl+mC<-X9-@+O{wnRjxvo<`m4-g_Ray3bX-wh+Y>G#50thWCUdcJInl+VzDee0 zYZy5@vNqeZA{Eo^V8wG)OOh{MUM*hb=E}aiQ@xT|d!AEM`S<3;_wXNJd zDH*TtV2dJA14K@Mby^yn2;@Hl`LG<)o%ZDUkn%r0Pi%GcPm`=ao;X!mCLXa>pWhwz zo!|?U#P7ya9||FAX~lA(Nlm95;1AR7^^9Jia*ZphC1r~SnPsNKoC$TuWmq;`8p+jB zNz_k@yZi!P3*5W(1aaeHMMGt z;!z>8NO5|wij}VN65vja`$M9Rqx~MS=igZa!z2J)8<9ErhXk4XJNS>CmTc0f!Fd{s{ee?LfFY!Z+uG;@bnrxyPUoEzu)5@zu@{`FwWs$&eu6{q=etX zecJ}3au3nz-31% zhrdTseV6bO)*qmrm%ef8i;Gb8c zN9B$ZSfOyZZUT;78t*6GwG*2(r|XE;nTaB@8fb)|w<3wGVMgX*fFH>~uEzkfmxaEG zEN&Sf$pHwNdZEJwC*v%JcJFMVm=?~~y1sG!yr;U^%gH?!r z8vHf+{V#pcF&cEQ)FNau zmYkwKEFCUDA3=6-thao1CK)#Ls$#u9$Z_Zu4y z1AI#hVb8kGg^j723>ax3^UgZ`ucWW{ywwVJi#SP$J#0JXBUXS9U4RbxD|8_7&?`;@ zf+bVrv`DP?H=Hy|fd5`8g!{tV@c;jQO5edJxdBwMhYfYjC?rey zv=8-f2Da!(vqV;#B!M2g^w<{LTsA1?qma(2ZrRJ^o;*bjosx=AaIbR^ocoy-IbtHXAOzkQ46 zc|FimkG(4s!1B>kdSV*8&|KxHy>R|LSxt#_A6g1%7UK<1`k7&kEo@{d4d2G-Uh z*t(dgI@Osm=(w)D1sxr~-kfQ{l$4(W$LO*XVEX40`i>DSsr9YchX%hdWZu9v5E`}i z?AbUyhXLaUQRTJ4>hN3JS+2f`g8AtuQuZ)Fu}HNFV4zP_NO#NOpsuefYsoV(LMF{L zisz;pgw1qkVmE+&{a!*pd;nkw*7XFPZ5fE)Bn~w7iv1rO(|kA$(hJ0Gsaq)Md>41NeYZ=K+(zaXxCxhoEFFR3{|sk_Pm&x*8^#6Bm}I;B&jsR#ta#3c6<#j8un zXMvo<2_c-+n$%B29ng`EwUZPE5zlA<$lh$SGUcG=?gu|VKJim|U!PG*)J*_#NkxIR zhoMnb23g;52~EDbj$;aYNDd5buo!6)S8S0wn@`4iS;hcN5CqYGa$>E`L$lr(zXuX+2 zQywGv6!}D8F<%PZv-(nV$nwGVyUnq6yd_ypk-LWpXyci;TG&xugn*gzTu+4KkKJ0q zk{%`np*g>U}CCx1K{$Dg$f!3tHHfuV@lHZ1yMx|5HlT^fXpC}Ls7QUfQQTZNG7raT_oT- z3EgFC3>OeZ>YCKO7=%qmlUd_Yyj6M9H*jo3#CCyn2Eh{_^P3Vcod@>>Q!*#HNRiIM zIM(vv?fiKZ2TqG=JI|>sgj6RjfucM#>HvjT9UH?VY4@WhX<2Eb@4(u>&VkGftRuOS zzYQFw~s8K0oKgON+qeBTdf<6yf4qF?1_rG?N<@PhCRMTZVc9I*ilqbHC~ zTcX9*5-~(ry5l8q+o244LH{V4+IzS^1)zG_tidtGz-ag^OH7@J?3$D?W=zqn( zaO!)`7w5XRYC04ElaR{Q*W$FLM8~G$a)>BOOSk`^_-p)|lZ=cE_Sb zeHmsqTLLf>3`(Sej&?TC$;A$QLu=j#<#M~M%&BEvd`3n(fHoJ?&XW$Vol;(hSioG% zziLmGMx59S6sibus1j1i79^2q<+FH#WU^|}!!-~!cuCcx4eA@dRani*v+GxCQ zaZeze1{j$fF~z{ZvQ7?+n6NVY@COfagc03es3%a6BPR?*m7hY`z!QbNF}SiiQ`j@X zqN_bbVLCcAAj@UNfknH(F8h-Y;Us_k7E5o#Hy!tf73ek%Yc)59wcfoj)$9-~i-D8M zqNju?=P%ipCyzr!gwOw24)S6iY%R;TX6$QFiZom_jg8WyYP%#4p37|}8w3aG`F|id zWF4)BsjVLcvFE2Fm!lrTnm+{ZnHkYs=2l=lQ6$kZHV=v8m!| z2@K0%w%6g^lNR7RkV_oTCsEl4B{7{?`hBZ82qB*6;s92OF zJnmRU$;Q#>7X6x*HLiqM&1Z17N(Iq-zVLU8wFL(ay|Hs z_(5(PHWTPV(&g{}R1<7F7KXoHAFSCZ2$g`G0UIqp2cmlxCc87i%F3+_7itMxf?y*Q zhc$1J+3jDye!rB^{Q`c1gohG@YMJ`NoLuQ|NCDxC0FEaRwI~bL&cghO&qFeMgA{Nz zhBZZ^?Xtxi_oGl+y#?D~rl>?PX}D+=Put0B)^!S2KT*q^7>OH_wpY8t7|;UF^-$+@ z-2cJfg#}0$#3<-sxcUzQ1-71i2N!jgxy1$)G;49dGSm;*YGpog{vE$G%gi zN33}Kfp2t5_vL;wVN@vBx%pfrb1r~c6y&FWadQ}c!Uc^OIsg72C5~&leBm#FleOr} zbb&IEi4+jr6Npmq%Yo zPh?tqerkGmp?w(`Hgp^sUaMXZGYexTeT9)zZ;>d>QGjQ{YR7d#fh!b~6^v9src&{<27npVgIQ)vCB%5k^O&s0e4Lcr1n#pLZZrOPQcf zaE6OXZD7NW#{i~45;jPHKx4=l_uYBn0+vz{cD>}mg4Rg_t1vYjfb!$aat0(r@kWWO zDNUs*)dLqF)u1f4P*58*(OOP+i$+g}i#T6fU1}-*3U7<<<&nw+0C4<(|C_IlCICo~ zEzoRuo&<|V$X?!u1a3@6psK^Ze>b0ZXPsLZ=p%F81sq(Uij85-w#%_QWHq->>yu;- zFakcMu*a63&KnW)2e2Wy$&kB5|JTo{dT8`4Ctzx0FtA_v)wh(?Ejn`gM) z#&gK=ZdPe%pC2wtn?==zrGj^pmPeEoO%S4BLc#32rR-z70$U^n!JCI3#PKLUr*BQ# z-FAHxb>y4{p$hl!f~w3I%v~yjxxP5cz$tKiouX$od(UM@MsnHc-S-v)5?jr!hHJ%V zg?0E=_CNdAqdz_z6Zu&kuEihjj&04cUmN{8E(DSku~Gf<(Y*Ntfh{vZqT zIz6(GI6K+sfIp`-jX z98EG%65m#RZ~pxrO1UKcY*g~B(_*Na4K`{6sV3K7eTV0*N^n3|zD2AutCw4Pc#7Z1 zK99H(RLUK+>T?|+DT{+vFOQY3U<&LyzC!oG4#geU(5xb`ui|ZSU8r`dE1EKW5mqo_ zCCU)!za|5_^qOQ$9e)==EKNl=0yrKy0!Y@#-&29n~rg+WQurd;mQXKa{xj-Rk> zVstAxzSnMbai}V1XJLF=Sv~M6-STy;n^ds61E{qHD$Z8TtgTDVAJY!SigV;~t_S_u zQff^|ss&SYSy@o7bVYSD&E}I6&Q|eHq-o=cT&rmyw2bK4vjaa=o17vovCAI^VANo4 zzm`@U*cV<-R62qi(1U$SQMKf_U^G_<;J!^MxiMT}WLtem)%qZKDG)l5(1vcOndj8*#_*EZ4C#PjK7lPDuDY?oCas6vj*`n6GKIX(|cK+R+QP}`+MybW}3EM7N zBntvTx5q19%-|ktjfchZz!%U5*9ikm85m7+IXQF5Zi%&~0JjkJHfdpke+}E-V^uK{ z9jiTi!VjD$(YA`&+4=byEfWm89=|(K|98`wxXbuP`=yWGCf|U^r|{oI2m}m^_MU^I zP=_3c*Ee5A5R}~j$SQKTO8eatJB21SZsnV}mG1YcYGIdCh0c>!#3^@nv`H3Zu0IMt zifrB&;7*GP;t8^GOq`ONCMl2cFNz`wWNNRe)ot*&`>R6Lz-o>IwOP*5{)`#9doX{I z5Skc3EDNc~>d%`fVjT$yKt#e0u(K~La>EA+oAwC&oa;Pd(ZfV1(KMQq-~~YZ`t>QW zvn)n#G-3+MN@-Y|pN3}2QBe#}M^?+dpO-izPXy9I4KPYTyac~~DoKKk=pUzSjGg$E zQvW>Y-lhk71@C>}%CODtd-s;Vxp(V*{2%|R!`od-m`PnE{0i>;8`$hwV%=W5$7P#C zDF67Rjr-uEzwyeBGl~60@EzS{neZ=)BX|%PM+p7+*B^NRKREELi_9h_II+v#Y}AVT zA(8m{VU?4AQ>p(AXavG1BK)`H)E!bfPH^FjFE(Zo+Q%{27ZIjy|N2{Y;lJewoBSf- zJF#y+{yaZSO01jtQ*;{`I{v%oL$wjyD0h2v%l3G~$|H~ogKcJhJWKEc|Bp{s-^lo8 z72T3eVA4&MOS&Iz(^?nL6V6kgvEZNgf+9@#j9b#eQKku+ zsUx@9&rU&{=Bc12+k#-ty)2g{fCu2?e(Pcr!G{n$?%xe*+$-_gn|_| zd_eO4#s|b8Z|GF&$+Mf>KiKCXy2T#=s4^Ng%_CpD4|@w9CMS4%|M80eRb^uh+4PfL06pOcmIYiN4*DTbFX5 z%XRfv;!~KynVj51cxV3cnV!LKXdgdH-5~s8?pHT1L4X)!FZVbvI1uY{UJ$(`OZdP2 z!`&%!!mo+obX+1~o#*pV5%v2DR0-<)*j!-~Mr6O&s;MDowkgEvj}E4)nbQeVzGTl8 zDP2^EILiW(l^1}I)OYCMcFSTa5kYBsKi;ZAupBDaNj73Hk1;=AMKOcF>An8$2DrmO~5{;zlp>#*EEoh`F z{x?U$LJ77jF_yt@rUqO~kT69(+vr7@u%oKB)08AFw~}8 z+RXtNnb~^W0i6shf~9~wS^*R3JN0fl6q)b8KRj3|kh-j8+exDo31vQMTuVtTv`=5r z;0FZK+%3quL|Ku7F67M3hr?4-eP2kXTRmV>CJoh+9y}#e7YdiU)q^5Vc1h0T&ObK| zn15f-zu&+;GWc5Kg~Q8tgxfdrXFwK4xG=bH*K$nR0KVgS0A?vlNmpLqP!$(&Udkq4 zwHr&#A$AaLo`vDoHzyzq1OP&SOuvaoukT`T{dG5(+t^pw%Jt4Fa9M+2Diwi1eIbMo zBjus~pD9!eG+FFGh7AN&?bEc!F&f~OsRy1uF(T;&(@#*$>);s$fUnz%B$aBsD%tUDKL`jtMaRGd5ZOLuIXolF`{^WN4F0`N zz}dt~4ge?TE}(;^Q^fTCOYesw%ly<@8{5x z*Mxlmc(f;BS`&CkzykIAmDb9&u4~_xzF9^)jq|wtyNw;Ro4~9cx1*r9ybDuc5GY&? z;mLt$1tNWVQJ1ql{5)G*!-&p{u;~s~1}7Y%SNdyH_2DzMvBwp8GGh#2goQ|V$|XSa zKw;RAztsW6^5HhR-4{L{w4XM1t3bq$+9+`%b*l$7TAdO(O37j0mPh9tf4si{sijQR zwXt7p8f@2)e*cikn+jOZ6UP^FfbW1U!NLqFMw|tO00Qy74DPP+y~~sgXN~Tu-6o?D z%;?_3J&9&egTATWE#D!7#1}O6otlUF&7;({J_p1WgA;c0U*8GE`^HhUvu=Jp(@b$}r1Q4((M7w4tbbY99ot|N#mt?WAha;!4B7yX&p^X# zR1KcS=fQ&pH*e~>=Xe|-9at(Xf7H>4S>D_~F) zDb^JtcJ)9f6q8&zJpC4~obtr^UGP#I%jvWU6<7nz=3p{%pK4M;=N_BJJ8pd=V%&BC zgu=sO32|CtzT#~4DF9BCQ0~0TvWd$Vw!76ia==il@Ir1l03#@snuPsPlA;*#zdZ~8 zg=N>#F3f?d6~I?e%Y=amxDu4xbuv;B^X{X0)4$ zlwUE>&of~llx6W1-j97g-3*9NfTW+4)}Mj^aS2|5*>CwrPwL}9I>-J@08}4qZUh@2 z;9h5t?-8_#E&HfBF$pl=Ms8b@1+H9cLNlz}_b44+-e|@=lCpMWkUhx71 zRhO6)^#;0!zGl z5dz7rWz{NZqP2nt)<^x^Lp70s0M@qm|1gWg1VO%38HiO+A#`q`>LqJnC`Wv_(wq#- zu9knhTjD3gGI84RY=l=#wt;5~F~21`{q8A`TOa6R1JR0Hmq=zqR+6^DeCXvRI}*0b zUu}Q=ybGhfTsTJTVFEGm*DleWi5eFdd8QyUbbu`Bc2|Kq@Q#ST)_MTQps{JHQHTTH zGaCT(yo(Xe^Xf)^Dg@`;2xtc_f^zSTDytR+qe> zW(}j@_X0yJ)JY;CY8AEe3m)NXi#4txJ)wYF+~4Uol?N#J^Mvrc5P5Em#3czoZ*GF; z`uDp&{4ZiLcxe0BMelmTI50+!|B&SO0>TO-6g@C*0lMe@I?VP?KvR$svU$)Ph+)L{ByR%+|G)n=>PD_*3XZK2*Xf;bw>7i>LCA zUPQ_nU<{TM>)l?JhQa6)S>Te$l{_KKg@vXKCVj7Re89diw1@il2||u5WX!DAbm&xM zpdbKdDEo3A{V+>hLiD_q)M1f9xrzxiSst?E{HD{r(C#2a#)D>+f_ z;_xVVzrY^z0vXw$&DHzt^kV_Twfjllg`fWhi(ZF6H~k0DsP$lm{}(B-@=2<|j2EbqPTHqCB>;+fO0cPzl;5Z1n ziHkH}m`kWz`5oQ&CG*}u_vzD$R~^(L;{nR+)BO3|W?dax*QL}l1b|RyRCq7Pd=9z_ zrOXn#P_^f9*N=nT*}jZMmph#7JzCNf*stJohU8`3Cy>N6AyFy0{(iD|A>SV~6~d+R zpO;K52H#g7b5Lv$A!s*yI5%Kn`rU*;J$3H&d~TRW!;tTSJtPywL)6QBHgZ5}PEwJD z*{UwFB=_TwrhFad9x0md>kq**YE99*0lp%9VzIx0;-PU+lpDMZ0Zcq^s6goZk1_e1 z3p|heA-I#<9h*n@v=dPRQ9)bkvGr-l{WgGd+jrD2@jrBzq(caEbO`V;4IS* zoLOu-S*?-o^E51=p@)(9doQc19PrEbWsbvQD?@c397jaP8*>0`*~sCwpBKcst~wEO zT5Nhj{^_^J9^*&S_pDA-5q4IbNgGwgc?6>`&u_r!1Dj!VvF*%2rA2AJuWiB55G*dw zlpceYK|1>WH;!A3<QvL#=6eH5z9r-eTJmQZTf723iYM4Qarm)X!^D_5h*5v_zUvVV$Nzcf+@R3A3%*Psd>v>nZS0)kK-JRA7NG<{yKYq4`5!-O(_e6=<8RC0 z#Ca1hf;~%b`v$Wif16wRUT?OS|8ke7Dr3aM8nkie6Uhi5AD_gHerp$y^Ai;XC;sK- zQ%P?mD9+Z#%MrZm7$Pd%P zasK}2fIWTK*p($b_hG2t^}YY6H;nMXpq-u$zthJNVI?>H<^2uN^Z7P6^0gFm!nSnd z^>knR(&g+Xb19DEkZZYm%+V9H{xn-&MkO-Z9zOcj{^3mj4=UX)Jz8N9~ zo-CXMFX8|3Eh9EQQk~lTI>BoeWxj3wx=ZJ=m<02Vg+@X{sQ=?z3U9#PQ^)obd?LpE z1o1nPi(u^W7!!1YZ#&`q>i4SY_lrhI=wn8_=7;E!7Qtm>h)1aL*PQ^9BwW`~X2Ku% zkDuv&k7NB4l_%Rn=m-%}`;)ptpq?TPJ)%sai%l&FR^Q@4ag@QCh3F zN(psbaEBjg^}sM3GPy@Iuk*Y7%0+h0sV()>fhSciKH1CS+w4@n^N%mI9lRu6B`|WO zX17cTovr&{yG;PFMSc6B9EF>}OeL2-w7d17ZULmvC8CQ<^H(u(c7-e3)y?7*#&pu9 z`3Y7qr=PK21o9KgrmlQXLbj92nb!)esK1`yCG4++`e8rj2)hqwb6Ual`bxUC79F4I zDRp&qi#o~uGCepOs2=8Qn`S$US9@M_lgg2eS}-MK(Q_;QMQZLBZ@VqJ?_8&>mRuzc+a@!!5_ z>ezqY9bm?g5*ks-mMCvPE`pVLCT~J#h_%y)N$1_HeBjd|_|iKh4Hzw%Kt@aaLM<=} z?QI2&emTJQNkw`Zn1toP#$m|hXr&N#1uFU_MHFp<+?neE4M;TR|C`nF@4k6Oz#@NQgXUzY$AEhsoD9ti_kFA1Yc2i4`hzk z>2B!E4{G{N=-w0J?vb29Bpl>5dHMC_l9eQH})v*7Mz4wmCy8Zu$Pa{&A zDxstlAtR@Vtja8-QVAJloGK%GueKg$ zwmBnTO&v%Iikt_t#q$b~BpU}Qec$=z_#D_>_PL0Q!=~=={|$5833%s%1)c)uR{{d- zM;P7Gc01;8-(Qmv02(w+FbE7C-czw!#$DhGO+;|vzEjWA^z-R4lYlVEz)0#Gsa9_H zhhCPTM0sPeX(4D;u)4MBZu;>w)>16n;w;*A4GfAlpbRx+)WloTC6 zl3B*SRPxd!j4c?P3y`TgliOQ#F}BLflo|LyD4>h(jAcAqDy9T<5z6=(zu%+Dh?}9Bg91)F+y8p@(aH1kQRD$jF546T#Mz%6V1D?^1lCpf2jOEcO?p{QW-iO3X^djRPgw+? zHi@)RdOHgVAl(v)motpitun#~=L~6QBjYy|Bv7rqr0UYaK=)?2mU5$8-+KV&Bo^Oo zASqF`xvW;DX1TG=mRYcA7t zEV$J;;;~2~G-jrss8~yYdvxyGEditKeik|bqmUMJv0-=#o${emyMhM8vw>)xOw5NG zE`x8N;Y(!@F9Sv97)r$nJt-9cTPmng<2!2&CQxVc6s_qBl00zbOx&c(xM}K2_55-;GNoN!kgm8=s!ZlMRS}nc)4WC! zU7$e%{sZa2Js#qw)v$gQ_pohHU*l&0X8#YZjdeUz>e^$5Z{36c498;gg~529D&a}@ zK6ma`N!%rXVP4woLnJO_RFeC&A{7s0^1v!EeY*&3PFK%POJ-I*XF>b9H6pJbMJt>} zWxz`Vb6EhcSayg^c`{^bmlYD_&k^>_&UO6Fd;8*s<*#KSluNS9YhWiC^lw$wVFI9zXmG&BaYp2;Ty5id>*n}t@grkK@8Asdhj;XhYTEaV z@`7w43ry60ScRL#N?_|I3o`Y{7%!bHhYKx zV^YsHKWWq7zPmy>k->1>?qEgL!cGj0e8BRCGk$YdsJH_7kR_nD31D0_)z0zz-phh) zazh0(Zf2Q|tgLTsN!)#;sI*~wDstL#=tfO|Z(n59$tgkE=wqy;T5!M}qqnEY7oP9( ziD66*i+dFQng6dNdXEOlnbt>`z)yBNE}0SCeoV^b29&;-K&Fgv@E1HQLBE& zq(W}+t+BulR4JN%rNcFxABoLxoC4)6wh4%ByA}(XuVdWX>`!gRP4(6Es0vNW!T7M* zR6-R!uCfJ*6gP9unGIDJoRT9{UFI0~1Vjo}_rD^VsW%M1zQN$$Ku+gh1~SP@;G{AlwVV1y|164o z`yHqktuHtHiv-~uszJ^$BB&I>q3{Y^kjcKvZ*K2qH7@ElJ~ErCQAEeHrbtd z^B~HQ6azKfT{nGE8o^aisRV!w+_jQ7Y6mw=F^~)CL@!(P2 z0QH`H8w&uqO)CX^0|%uRJ7?eZyf1SkT6EOUl&H8g!_Ze1rtQ+mX&9UHK7UCf z0JL%6fGqkN4r-)8!PY&mq_2a))#M4uI&0h((Bag#s2EP)nDeF~;rU(P0M(E%><*UW zQiGQveGiP{w2OMxe)pyjyI!Cz{8)Ldy^R@bCHsDWs0%6COSsufhT+Dj3IjirW^kYH zF~p~jD+u);#iRT5VQdRd%tv+<;1;h*^RNDJ3*kw&0ivJs1sm=f(iX3R#Ri@yb1-L; ziq?hBz=-KN#ikb^4n69&7t<-AX&0s;-gZ+JY8@F#(^)7IzJ)*YuseKx!&w3xXyr|& zSj^Y!Lonm_1r7e!&}}`S#q|gJd+=u{>H-2ZY-QoF($hE>Nx};o)(Z}tpSjyC;81|h z>rU{s^s45~&dIbtRBj&4XM2i09Q1g^0wEPU)&TRM~wQPjf=9&_fbIk#B zrcdw&R=D%<2X+B0&F8WoMygdm&0S+=8T7qMZ0MsW;XEpX`TvsS{910kU!P6nbntm-n*A=b7T%^xvDo zrFmD08)kn(BM?%K2(;O!#zp(z0*a2&1#u##Pf!yY0a|Kq-hl!V6SOvlG9< zo2i{^aO|)pc_p*@V}j9qz2^Cszu!sm!t&?usL2cOV>gsZU2iZXJg;)&fH~1@-u__w z_9U16NEQY4Y%>(6bliDu;%?Tx!(g)m(ID(l7_UhH9#PSp`?hb?Ufv$yscbSnNL%KB z?((or-&g3QkxH0n5j6Mg$~R3Ot7MSypgdO`UAf{Kn+p5P!eHwJZy6}h0p8BZ!G$Hsa2J5}z6gue;P#{Ou3$R& z+yD9jq(dEW!0t!QQ3Y=Y6mdZ+ zM?`mVe^dDTI5KewfhVH1FLawgZ6x>n>EX1x@>gTDFNNpYA4XQWnnU9giI>lWZ9f4^ z66BD)auh7CN3$-+-xGnm4;j7rbj8Jn?RMz-{4eZC2?F%#%2Kr9wR1@$%$Uw9h>`Gs zOve*yptFGA9fkz)lXNIwz;3VcUf3Sa>PToiC&1epZ(sa^ z0jC#wlA&NZxwl^rI*%?03N~$Pjq9$)-!R`7h&=FMby7B!G)!v4o8s)@#+6+{{k<9! z0Mefep!%1m+I~pXK+mzpA)A^}_y&T~Qr|n7U*8{kP-@Li8C@E@(cZ=|Y(U@=OB+Dm z!5O|_OLh*GlVGBB3ft0mp4MUOJ@$IpqT)RdHr_fdsBs{qCCPx zQx(ay%vm(mr|6!GUaXNMGnv9m&+Q(~ssX_wnzz$BjC4BOd0yH2uIf6}Ge_an3V?@J zs)7sM8z$1Uu`FV8cIH?cigkJ?ZCFH48p7c2Qazw60A9#5x%NaDk9nu4%|tb)qlILrSP? z1gwsM~QkAXe=~`y&-0(YnKOLgjLgi{BdvwMPoArrH}A){QbPej}jzr zGD1TehIlf;gyG-OX~LkntPs)KK9Fk`Smi` zhrWj3dtU9Y)F_m@$AlU7j888RcKm~&o(zxkW#{uIc-E67r9sU61x~92OtmxYSi3HDSJi5K0e!S=7 z-!^l5>`6jNq%@zUK-3Dl(IquWBdZu;&JzvBGV`S3nmv)+>NP43)AR14#fa#OulZW3 z7sAbc?(kpi3?@aw1Y#nMF7q@|dva-P(^>=GaBNq@x z{qq^y*ob3VJ-G?3jg}ek@VSlDwrq5fS%WS994m+r~TzsC?vm)Z%(z!rNYrL#o)fXR6M7&rrg zx*4;~%2jGEa2unr)M&7NADi%vA=WW2c03ee$hCf9vcDc6GRonJJ=>`a!$(S4*O1MxODij8? zFwI6au{Qu!r7+Ze4c_cMk9Rm;kaBADpzqyqOhChNi$IrSlS@!gCpyDjgm)6okh%F| z7(JkIB6ccrN1qyLIkRIVq&!;(@jJnSOOL4xMhXtJ?~`(PBZ_AeJ`?MR!BU!u$7Na{+lFq?&28I;}bg zLeqd)xA^-Ud!O;{u~ep*+ViX_@B;BK`uKV~AYT3;%)~EnLzv{$W4ituecZ9)^#mHvW8l2hHBzILc$lTVMx0&p@(|mBxEaqx#k~AkAwZ!#k%$>3 zcEgabaRT{>b-Qurdjhcv)z8P^tL6SIwcACEVcdbJ@}=LtnI_UzoXEY|D(tk-&x#^j z^%s8va`c@kSKZq}K3(H?w_9%yr_-G6k!dP1>BIt*qQOC?Kk`tWDKMwNLbUsVzls0L*utS=5 zT;W6y2}5eb9I;%AS{(R}@+833XGcQy!PegW+02bAx6@WqN}K09V-MjCRvR_kHr|bJ zL@?11jtt&pi{mszTjrAU`u!dS;021Q=mM6dALJN5qX=n0B&%8kIKc!L+3}B9iv445 z2swhmXX!^=+OG3C>%o6qldiz4m6(BN^03*rq(ff{}@HqhETZZ^{z5x=~*Di1< z(JP=RfGkdNltsX%n)W96XHMitA=@yD9}SayTAcu2_#o@IR$z9onvmE!o2b;|@ zgU-3Oz{#nOA55_=W(S}9YlAzto+j^m$ANB6P2mjBb59KWoP#6=Iz) z-YF7uR@S!adxBd1(9HHelz)Jv(Wfj?(um;u*)hcX2WN$GJ?)=L7Wgw(?~#>>?<8X5 z+6+)jquD+JaNr<4lLc1va_s?*IP+!T%B7MT^RpR-$g@oXo)k8 zl23hM0A#}GJ1Js08fE^b7;n;?nh5}w@2EzxqFAlsYGWSLzjY-~2$EVIeX`5MnKKa) z>)USMGz6Pao&(BSIXO+An)IprU%24ey`iS#Ei%duhuN<`*wX!=9;!dP|Mx{$&n_4b z`>zcwDns!1G47QSug;PoPOi$p33mDuNhY0AHF#^fsT z(;DYJIUw$t;(Vv7x9v)eP?*VAI%JN8JV|98LD};>Z+2*YA&x|Xekh7e##|8E#R@r2 zRijfM+$zsSx*W7j?!F89e{0Ifn;=j}A>2N4gK;F1^jecJ#0q4JfQYhSZC8rIxr6{% zQ317Z{czWx#bE^~!fvYeV#}iV?4X>8s*|0u!LKw~dVT|ah2-w<&bzmX+5muWc>QoV z&QychU$87`7uMFh{d%$SYGYW{-|ZBWXB?>|^=1+t{I7Gq#FVDv zOzWlc*=35tX2_mpiIBi?3I2XWBc}&4CV%Kog9~4zR*9;a^GMBk8^CNlF*Wk0Y3VT* z>(|h%Anv??TIe-NGD)t?c2cApqq>5ai_tLYV5tC7Ni@=@fr34F80e0{_-oD79q|n$ zhxqZLnbogGTF5pJkr{ABwMZNvS}Il(C0kSRjkqJi!g5>h1R9!PAIec2e4IFaApdva+BK@m1 zd7rVMqS&&z*(kyzN7%9zah)~hP`mIhE~jUN4dsPZE=|ID@5UKbc{`fqvLzjlmNQb_ z7=1%huyWb#PUO=2@#M(I;~dFo5u~!nH?qhkE{T(AAq~KV2=1OF5}xtrd)^hi>HW0= zz6~smjymkiz1H2m#C`BuYv)-{=say&c5h(h9dBRXPOs_?V$9&c`39xHahP_YOeI`S zu;~#@42UfzAm}9UUIJLSR-W#3H>m&7c+H%DpL&cO{>Ti8MEav!XNH_TfX9NzJcEnu z@#~#f?Gmw-@g1p}BE#;d`Cs`~;Ge%t%%dylzoD?zG41H&?b zcX!*1QK1b}0A7Ozp34jjTD!tBjL;wre`)Fa#Yy=h`MNKvAnBqIdjXDuI&s*QK5C)y zeQK33HY+V}SAxgwsbv1dA1r#R%R{0J-&_>BiI`tP_ul|vYGfL@y;?_`IYME*lLda_TO61Q^GXZ%dJf$pHFlC)fgnzNJ;EDM+Z-r@VbdYE!3H@N`TM-l9SPpMiXNbNfNhfdNDy()vW zFg6IYOM80TQHp+Sm*Y9uySkt`_??q#2=Je(=<<}3RY7QrWLbj$-F^8-K`+@W3L~q- z7Vr#%V4hY?{^=2AkN(095+29F*YhkLG5sB!rQdr~%D8-xRO&$Uu;ABEG0-1c$q&U9v1!q6)m zRcxlb%OzJAs_@KmvVYaf7?%>l8|>xKKx|13PTzzkX7d2duRcAZ(qnN4O>QQq62OKu zCF6i0_1wkC!DG^a70~PP1E;A{P7kX!EKmGV<#S$$pC0}FX0V3B-dZuKes;tytrgO8 zkpq-nNtiMO$fLn)P8$HJaF?7h>yfJw$Ql71X~hNH=^DHaSN_~>tMK3Tk=AgE8%U+J8|rM7mC#e?PSs6@>4-lu^&IAI$2kZqj%^YljrsaH3F#v<-*w^a1gQ_ zkAa_{r?v`@XIzcDLSUDGd_bSKjKfqIIAT37HC=}YGaHLJa4?|@F&$^X_ItEnaUvI z2}L6mN~I(G;SjkO>rQ{_TRh5Mga-cH%fY|kKgo1HFUul^u~)tSjMsze#OAwbP$|W% z>t`75FJ1P!4C)6CdV}BUKxg7a@X&O^)i`g+_NW&Lk;&pqrszU-j*(UgC^99;jE8oY z{V>ks8iTD2)lqezvQT!^~GFMsV&Z>Y_xE##@QeG>~MSjNvtk$ z?+<14rrVneqiZ$Y>owC)dHg_+(_pf9L$SRE>0c!b8RZNQe|tA7HNa3xLuGWH#!L!Eo6Oz=y^=`q%*s0;zoXJ3tq4wC9vKBg?} z154o4*T6%Z0Lb|wY}Vnp3Ai!K;9k6!zBoH-tS4f!V)7N-i$;4|A(PFk% zfG;o322X?Dsf>y>WT)xfBV?k;!rZ+> z-0q2=#W|X|928!s-+n3nn1&$prb6pPABFYj&D>}`*gO5g*Pqxc8Jbp(og5ezzm?m$ zD=8U2YZkm(mrG~D^X60kg|4U*xn4D;Z`UQB25<3PubQsHL>~esJyCkQ&KQ7*b>%#f zseXMYj%Od-OkSQ0y~^{LX)b7t5jN&Z@l{_95(4;~q{ju=?`X>622e$8XcjO=c7^lKZyzsL$(;_EGRgfe7SJ5rYw^(R~!I`i0LlG;ww{Ogq)h+lzsc zjbOwPUF}U;`jIkZqRl=c9Q0kL(7EM&D`+`}4euWzRu7R-@GbSeoiixk2vfnR@WK754S{b+7z?-q3G z$XZBHj-F_|XDg;XzZh2q_-4675{&I;d4IM3VicP6=-s=$*5R zeZ}<=;~TsnnY78_2$~z_zT16dI$(Ky&!aY}A z2kipID{6W^8FQvDFd34Q0`t*RAGy#m-FJc&%*kRJ6R{!so{!b}@+gXsx;>OF1}O8j zIabCsW)|vXQbHC3M}?9;<@5>Ksxwr-Dn?crYp7t%Lv|=`*Bo4}2y${h8 z$2d63$YX`UOB8rok-FEoLtT5|F2K5o0(~(6_F+qTSEM829omDwZ)T6{RjzHq*#PFq zX9H@Redj|Za8Z2_tvD_8Q-C#0ZT805|E~Wrd}GCN&ywjxnyUVLSY*-sT5 zp6LW&z&4Lnkr7y*Mnr&@Yzbr?p{-ympsdBHSg^ zhD^^l+$DR~?~+KkONR0y&N2$koqfm-L5)z}?n!w#uUI+%V7Fv%fIP_ciB6@(sT}r!J(vPUDk>1hi0p2`#_$N}h9ddyewPUnFy=xt63{!d7;h~lPRsqf;{2b_aC7bb z-XHL2?}pzoWF6_qh96y|E=3${MO0N0AAg&!5$KH(={y@?VO|Nsox=}qNT37jnc-ZZ2}`tDOKkNS00j=*czftq?KNN&VLMph(Ygwy-7PJY(pSK26C@G5Q@MXWo9;)I^OWd!bhwM4J&gO7XxhSV^GHCNg}X4P0nmLzRS@lF4&V!Oceo^06bss)#@S+A>7&Y;G_iAurtXqP_jmdgXnolC;SY$H$!Zhm`Vn6MfXouX-VmDP zo#Uih@3VU7@xnGKf*C-yH$_1vs0#$|__yGVa7C{&gbj&w1mD-!P6KsLB6r`J4MRY9 zlU*JVJnodL)q)m?Zx)*qgfofZNWrGUuJPf|-MgN#jRC*@B8=PQg5cx0QIJ~)TqWC` zYt#M3c7xEvlUDM$Z~fF@n9{6T%KQSS(<=i5_CJ{J;@+fS7bJ4+p(fvEDYC1d0$?m> zoHy;?fYbfe8w^(FA&v|Ezf}Sw0>B=t6iB7)fV%ns<=B;??B5iSj|uefn4}NF)5Pbo zsS4aF!>e)OWdVu{rb1<<(4?2!05U7Tuw=~|O^-M^GCJ z$w#?m9BA##W*ip!y}0ARX)THX6vqeJ!eKp{uu74!rsqG^$}$}mEom-A7+;mQkWCZW z9arFg>`L~St>n9cgo_H_>-;%2&NT7%;ZnLcC&u<9!+u3FDSeFi9OjU`80cI28&hLh z{GcVi02I}V?7XVTP1_|*`B`mOB-lNAlaOWc1ae~nZCzJC6xi;-sd@Nn<}Tb} z`iwZBpsdQ)G+wX-B?khO?$pP}pP01s<@8Er zZsu%kq`ygc*b(R}6OEIp0V};g$;GoE_w^&WnSA>(A4DCo_lV3kGb4;ruoZFvq5IVN zo_64W3X=alfw!P+GG9$HtuI(9|Sq)j$_TNyaGm&jFD5#j}FwAD-Nw^*LG zXhWbN7t$pi>I0>2AyuGB6*p*^P(akS(+|@+!w!XsI~V}~EDltImL-G6kO*gItmkKu zFLdO_wIB#?Y3Wrrd7x504#$Fx6=iPsD&Xd%wl~Y->rE&EGwBuvEI*-pwyf zOKmf?9<%}1eP`_bLY) zyNe>qEFxf|xd3q?TlfA0O;T`mlkKzfm05=HDMJBc#Hj zL3msuV|!(jI~mNSdApl|lsV7X#9u80+m>StIFYz_PiOPTCKvsNX8A5#8E54_o@q69 z{1z;e-#Yj>)-FZioYL zDc_xBtffT}sFibiS;d6(bP<&f)txt>@CzE&UsgMl>KvvFG^@#9l9H`4qyKFLT)D0+whGW=hb^+;3@wYmo zJVZ@BY}%6O6GDW@Bmp~V;k^bb(~yrdDQj^4)ipRDult#*%VhFp#_hxaeLLiDZx{}U z((|9J_E``n_k}Krn>Ezj`}B^xMRec2?=PFZ4J%ED7wtwBBI%b`PQvx@bTV)lvI)zs zDXZ)1X$XSki8-bwQ~~3Dn#}!X!PsK`=<=J?@;;HbskQoyxDb;kL%%*;v>a-<^)1p+ z-)S=U@x^q<(cHtxlrFFzeGOM~>K!38^xH))njS(WZ<EGf<9wV((@dXq8uW>0cII6*?dNbrKi6E7LJP_IIpq+6|f z2B_ceC=WdOx%?a?=%r@#F|3BRKQ>Tlm<)BPA2}Jy83RKj7O{$YDpj8OMsfvl@pecV z+Im3Px_V>_w7;hkD)-aeF?nEHZo-<$)RmN%&si|Z#LNS{3p0_>U0=BPLo-5z>YmW( z-=6qECuGjQIj7HE5OLJiC~?&pBEHqQl;LDxN6l6w0ZLVFxh<6QQ~G1<&aWaygL~ht z2wtnwX%h4^eN>O-;NTcTEQE{?r~)-QBlwZ~{R{t5Fw?y6!Kso`R9@H-T2az7n8(dW zCN>-OGZ7TKJ+_b_xVcY`F8hFpEnhqN?!aY*h{tTHg6;F#Ww)A6)+{Uoc|%|xg$pJG zXE=sk)KRM_n?WQ2+CU)b;QeF@CevF7q6Q(`%0b+zAm3Ea)s*5kSvr&X#gzFfczz{a& zAdd3SRV632q}UH}%k8=3MeOZke2LmR82P&BcTj( z&CB0DkqOQc741_7c)MDgvi@AUADpq+$+OXQq(~eA1$AA&iIV#555<6p-hL0$?bn{| zOnEVrF}pM3D^Khn`mDdn>H z;RprQmie_?x!F!_P)w`P+4Jq`)aA@#O}pU_p4vYvMn{!p^uk`;Xj78kSJmRrv6P>( zxa?mac8If0Vz!vQAl>62AC#*?9v7I#pv22A4xuYJ_cEDC_n%rYG*QP71wLaY6Tg zixgC5mxJ?7wcHN-K*j_u?yltVVduM{uaDJ&yY-55*t>_vKT#^*v$e~g zZD?Cvv9hXuyuDCHC;20ZBhDEPcMb6}dPCQ%3fpXxAD#!~hi3fhC}wx43d@gU*X?pw z76y%M%pfk&{zCp)9S`N>{O_HB1yCfI;nYcnFi*odxLzWrAOX5fC zdA(&A=URApFbHsUWm-%wF7EZl8G43(7cn!mXSPCvPqL5?&f%IMqVFe{*yPY!X!u`ON{{83;*;g1CP zx*+82Fz?faGB5=ia^%Nz`s@i)uygSgw)l)cc|N3lhY5xHvq`B{gJO%P*s*gVjf&;5 zH1<2aS!(AI?E1!s>uz^>uJKNoO6@3MUy9MdzczsDno>NdJttp$Cv8o?$OZ zA-z1PxA}DIasi_}j4H+~cbcQjP^_A8)5U3wd~CaJimq=n_U>oOiny5rHb8hNg3kgk zd^UL{wbTgqFpgqBvMslhQ;zH&>~;LkAB@E*$gFtrBkyj7OVTB;^t+Q>BY!B4%I8Uk zw$q#FQKXd8ER_4s)U_RB#Z>w>QXTOIzTQ(`baO@OWuGSDK^ftAi)ETB`MRQo<=W0t zN5$z7>yesodkqVE?gZTEeqrgDvZ(F13d0Iha6o#FE%TlifucNkzAXxd`xmcY_h&

_W3&@MgLkFD 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 literal 0 HcmV?d00001 diff --git a/docs/images/AsyncApiComponent-SchemaLoaded.png b/docs/images/AsyncApiComponent-SchemaLoaded.png new file mode 100644 index 0000000000000000000000000000000000000000..883b42220ea5e4b91e6345d6e5c0ea67b245a6ed GIT binary patch literal 382136 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

(JBnK>IL^W4gNoy z{^yYY)>Q3(nzAsnv;KS2f7|r`ZmR5HY%gSE1soK@`#%HrXXAh0_-8|IhWm5>w`=i_ z3;oAh;7aqNaWnjD)OgVZlMsi1fqZ2qEUN^31JmsOg>VCWy#2>Fu#D(dozwG`4g}%{ zi3B@Zy?b==PFJF*;eg?s#l6e1zAN)d34+_-4RgjUjg5hktk0*OoMd9J$@6F82 zgkBIB@`Kan# zmX=yV_&Ce|>970a%$jiyZmyTBGCVGKCD-tRKjZ)BXAAQAO13!DXr*Zektz?5jAT!@ zV|xBybO(nR=*_^xBi+^*?mw{p3Gu%e2#^ml<)WmdBpvyAM$3)Xi>Lp^gz?sGj*5wq z*HBP^NBu9l0l}jyG)E;Ss!WrJwI~0_Q|x{a<=|o1AjN|Y`>q?Skd-1edXcW}3`XO) zmLM5(I(b5{xMi>o_Jo(N-(22V(vi?xDRt_L89YgWEoQ2IEgF%jnO}In!#b-~uww?* z4Kz+7t5p!laz&E(jNNI5qq=RV0*sU|?bVCgqe8Q;B_uP9)5eFX8UrA*8+13JrxA&L zSGQElhFK5Zf?m=-42{vRX;cdjFm5LegCq9l>fE3vPf?$rAGBf`FSmc!Ic~$#ePd@= zqH{A4-PPY8+5Vj%U|>BjYAz~w0Ag=%pDrFop=|ASxYTwu=d|GB5%g{eb#tO9N!1kj zFJ=Wi(iSU-!t25&6xOF2ded4J`jnu6xA_B^{1DR{`4H++QIBtOYHvl5zJx|4(coWP z3_~`shF6MzW6!uv)W_%+Ta~Pkdy#W)n@9@Q%f4(Ak%UMEo}ZkL`eG?4&?32rn7bo| zM!p_S?_u=YX4NtXJ;hMU%bG47B|q{wlDe=PnJ`}u!Jc`i^2X4B9L%gBfvYPoA96(V z1iAsK-ZXk|B)^VpZ z^mnUo7kQM{8>X#>bsjs{l@PJjtR&APjNRJp!id*GU!7rJ!N)ge3jrAHwj<3x2*wAC zErrxgx0iYDSG!fIUYQ|VJT5%w1ng3mCpovG>LZyAq*PQhV;xU2wzS@cWM_ZCXIZni znekf1-v!$(H4yo*6Z74IiwaE>UDni%Rj~(E)XAxGBH}$S%_8Uu%Nyi8cww*!-Jaf< zGNX}9>Cm`13wXU+=(ah0brA363$u|-XvVg0sou>cjM=mwlY-x}%|9ablO;9|PT#59 z$p$^CXdvSiZCyccuT;%m?O|q-war{@g;dPZk6-P#HE@E)9i7|{-*V{U$^Gzpj_!wk zM((E}P10sE%dqS6M#yZ4OfmKshf10p!my!z7*U$}!Nm#c7(C3!SVyJMa=aI)}Jp)>SzzVf(#1SFMsDiEJsqUw3?w%)%B3JEvtu($E{AAk0h66 zZ#1KGBtVA6hf{=5RIPqwV1R2jGvgZUwv&Uzh+Nb{LqqEipJ&H;CV1WUCw;0)4vnGL z2KRizG8^t7;%_8^th@!6N7NNr;lTS z)@r5_eFNKlFTuXM%l>rA6y+r4<6pREm1G%sJ!U><&EW-?R`e6WlVQfPR# z95yc8@`w}9NXAr_r&0(Zm|65rkr>%>vRnXLhJfx7Ws*DtUsS%ajl|mUM7l+kaKv}f zVA=0|fs&Xa!9$-{qg{C36N1uaPR=DB2N>~CPpJr(yVqT2OHfyNcFSfk733f&+mekp!pgXBOG*62J5l40IWvbIHK&Fy#$7DKrJ4kO zf!|777+jrQrNG+()K0ux0y$o;3ISt-qe7pbMLd((+M=`fykoM5OkDOU8J_kbJYXIU z@bCtw=uV=>%gV}n#D8TI5b|8@uncF*r`h*7o_%dn00rKvYXi5J{qbW6}GRNdg zjy;X3TBt?Msuv9O!pflyS5-noBi7VmLfb3q_U6hB%2Q_2_p)X+QnR75KY>eJQ1GKF zW}?|lWrCLDR7Oi*#CVeDB|dKYsdDp?=gnpJVvA6EaWOyd%}JT}V)S!5jZPd{sfg^i zFc(!+MQiIqP8sdm9E%D1qpBuCt02RnR1s#w_9s=H;kZcfJjcCd%ogLcMGKuFlwBJ` zX$@eO2R$w-i5`+UE-0*OM^)Tq&CZN~kd7DTlZZh*R6-7x^otpRdkK#7!yuCntCCWN z^1hg}{K<7<5Yc7iARkg*fBn*L8|NJEn>uHp@6T{ua;rVk;S^}fdFmVK-T?mr`3!XG zp}5i35dm_FGJmgluvUkW*N|c0!2lj^cY8s}@OASx8Q5%}QB=`0Vl_u{B?c*2!Y)q1 zFGwXuceGl<2*2?-ux~;H4f`t;Z%y<3n^WVOz)$VQnxNtr!4Q^+V)z$B&iuFI` zYt<-J+APrf`S}g!sTTbx<+q%#S069XEE<<(pV=Ku`2^XURR=rnye%my!3}C*+nX#A zdQPiGGE-?4mY+`>5tG^g*`M#rFG6tnnAHuh2l@J)Tr#rr61JTo8AYEOoCDn+Z^?_w zW6-^=%hxat=G5>QA1pNvee&uZzea_*a-ogY%YRvK>3G|phxRQa$sv7AX4LJT&i|E~dNF85?T3w820tz@N_Z_H!RU*_ zsTXA{b3QbPz%nkKP>PDNDxWw%oQNCHnZ@|XQojMJB(Sb#B9UA7r)lpl)^DAqR*vMm zKKR6aI=QTq6hz3Cy&UuG>Gf&S-L)9+<%VIA?A7V+D&PSQw_HW<;whz~H!3!tFa`6R zX8*M|%jYkE*HcJzQ+P=i%TV&DPdWK3+MwLbsK6_eBRm~eUn|(zkUT-|Cv|~=yf4(> z()cq{2k>pZ%j;=RAZNFIDr)I>Ho3n{y%_8seYcXpo0ANdyis&9?*&sFhz!KMp5kV6 z_3J8JvY9Ycyp!w?devoa|BY;iLxv#-cJec{V|6{AI3wqhB&S?hWNl;d)lE|O^^!x2 zu(@|;;i*b4vc70GayE9;xnaO)^Qa!_Xwy#b6HZ3!Z(6mobAd(UD4oa;D0UwnrNzSz z;wVlB&x0TtlzQ%qm8SYj&nxtBO`Exxsh^t3Ce{rwcJ&6=iV0TzpF9+jZ97xCZdTT7 zgF=`gG)46aZ%9eC!&JADBi0k$WS-M&tyDxLm`#`GXnEb7+pBYEC2`C<3-JQoZXrvG z6n4=-kpm?e8ia$mkKPwa4=6nYr6CA(BS%%^e#IoFH|z+q8}n8O)<$_+pkBtFtgU(? zorJ-)BUiCEi56Tpi}srJGXW@#!{hGeEGId6Z}s$OR8dx3gpXyeBo!2G8+0)&$-v?x zzUrux`8!062m>`7&6MwWeIN>j*u8Tmm)8qg+@mPVLq~pj{FqJoS@rLNr>w{0nl?Rd z`wiD&>ka83PTFGQJ6}Yg@b0$AZtLwJ_M$CnI3>1u4A%QFobJ|l zvC5Vkv$A3|Bw%Dc+>vwlh1uhv1?8xnz{XV@aIFx|<-n1K+QcEB_fB)rsEN#?p7o@= zD%A;=wzf9=ArT;?5%8HHx^{p)XZ-Y_-e}fUBiR8(U-LzFMPBWPo?1=kEC!(BM5hob zg@1LGW5PF4@OcFu6#3$it%t6?wL?MCBGWp_QU(NW3xR(b1^@RR`LhlE3=mxmK!Y|tSxQQX(Gy#U9!pl49ChK zC`Wj_VE(nZuWV%Ya}P*SaTczb%_NAYp2EE@qq8Ku?6epb|G z_A9m+-Vk0Y6@mBa7K$s80$~}Z2D)W|C=ZH}THMZ_o~Ry%Cat66vN1bi;J3yj znSE=QfL#<*^N~B7cPr|aILWKpJzOpdYx#r{7YM$b9hvyiuaM62T=|*aT7gm#*gU@|J;>pGe^046!O`_x{RpIH0iYGFTg!Rv0$g70kB!DuvF zUMJx%B-2y55}eIVv)jSoSUV&4^Po;sVu>;paqvX|+T>u|5Y{U&bE}ntuL?iHuUJrM@Pd6nkUDv{6HnyNOUC2c5VV<+W~@X`%BJW)lRzbX6|X$<8tLTjLtEU@ zVdNRv>zpqy<6Z_3rCrJnY}{Cga!uLgK7BKjJu@cALO-WU{Lyt#Uj$3u+H!-Ehxie(@oJCDWy#OWwLpvz8jkkuf-k~qiS6QiS+@QZFh@#3oNFJ7 z_Dnt^=xNo_L!143s^u$hF1L%K1U_M$#@>gr7fS&Q^|iOd9z{BCF_!dz8-3ilg?;_y zYJm4jO2>86*hZTN2M>=@yUvj<#!O2ucw3I0M$8rzxIL0BPm1&O8Mh-(A)b!&JX8^m z^n%%LNm#wcK4T)2#bBpwV4nI)Bn3@PZ3*f5CPoJ_pCEnxfnbqMH47WMH|Iw3C!@XD z8WX3!ST;5|nW3Sf`90HtM61%Y4P=i%?OF&1Dk3!jNHNZETt!`7y;Q%o-8;!lK_PV7 z#*ig3&bn6o-lfybEP`I_^Y`?Ql7UQ4Hjd%j-4;B;GQ@(3j4Mq{v!va`=3T@*=2wy^ zWE0a%)9Oj`R0`~+*JgJ{vZ~^t9P1N zqqw<19Z8ht$$JycXwbazdEKKoEUCbT zy&sX9I>TgnbKnKh>Y>O_CMVoO=GnB|cA?ZBL^1fTZKp~M zebGRdYWE&{zSh-bYcz+N-8{0*baMA~c29njO%)K0l;(>m;$6z@d;jfY$-Q$_F4w382-g?$p#_ z2W8R+alYf~By^gkzuK!Ss^a5OjJvrP1)pMpTL2z_W=%)IcnR8~rcyc9-2iHnq_1I3 zo&kghEg*g2tZK2Z9fq#DIy-46WH~nYbL#dk>$)Zt^nH`tO9kG^%ge958WW9>zSJ6> zumHp{&9*|CBjJ;XT-C9NZ3TQZA=c>-8QxRSWzPtD7oC{ZAee z@_?_-W(=@J&W4zem4qQ#HcjroL zGMYOmsWb;;I^?A8kw`bEqYhmuU>d%xPH@W4J6s$^n;587lF*2f2tOKGX8EMJtMZE& zG3~6VezaKnM-YCIhSAjqJBx6G61mTz_-C|1Dh1CFO%WpABc!qZ2Xhc|QSe}bj@78( zkR=0X6*=1`1MKc1#I(Z1`MfWx1J@V>xX0Dl#%N{V}R-J0=UY zHE|~$s?>>IfgCzt3mMN=+s)U4y+utMsTB4z>NdX;SpNWkPN&j7KpDLGu?RmfLpJ0l z#=?slFU|R%_C+&A^#D2#e=sXEVv#=pN9LUlef1)|4d8cWqwsXyyYd!Xx9O;De{(T7 zr&u!njHJ^<2yy|$n=#-@;X0K6F$2Rv(bGFwfPe&4;DizGk(^-sRJC2&qf+}h80YC$ zUQx90E6c9ASX8l!FvYC@UVg5Y4KZ_KHhNK7J<) zB_{j^J7`rDHvN**r<7~$oQcrTc)6A5-G_*x5TSj3Jm4_aNPHR#07r_u^NyRpan&I> zzmc2s8xE8a!*=+@?=%-)|0U&oRkZ%{-A1Y1-If0Y7UO4cd8?+b5G&8?i+~)SxvGHC2H@KZL#| z;{c8}y~$-YbL&Pi29LU*rpk&*^jKR-e~k$>z_U#g)Rr0ypdQ_W4C8Y>;h}Dj`u_8~ zwEmU~flT^oQTvComT-yg+`gmXL*g-axqP38bgf(lzis5#PZ;3$#+o%PnqsEz=WB5` z4VM?|NtBd{&Z&S(ZfT*y(}tu3zF>Nj9E?F$vymDw>ej}!kUt)y4*42gs_5z22;dLm zQdgMyPz&c2bx&>o6Gisz&wE8>`6nAgLdJ9#(iA|5XO(I(QFzphaCfjZ23-B-drfCQ zYuACCpNT*jNqaG7Q3r^|RUo2agIN^fXO(7T*S))-OpyO&>}zKgfX850mdOnpRb0(4 z>woeg&x|}Cz+-Gi!|7cns$iVHrdwG0qk8A7U9+RTy8YNw04v4?61B8Y8YAd!Ekz4G z^3Lh=1e689E0s<|y~e|*PIPM_IcOWPiv@X~Bp@VeA|pV?Abn@R4S;ae-dosVhhj-r zu3A7?S{;S;-e&pF=$3jqej*d0xS#J19=gv2o05nz^X_(pj47+e>~32~nbNwhCpdMV zJgvD{i(BzVz(Dg@JU+hd#$oq7(>7$zH{nF4k;4jwZel=kVX*%S^w_j5)Y20nmgt*op#!>s4JP3=%Iylam8 zxr~xLP7lZJSX$uFo#tRpn+r`%>RNJgBt=cPwZKey!k`$SS(G}A)O>x`bQb}T&9QA} zqfR{l`ES>|LV;$C6WUG%Pw<(^^eS=`v%1d~1`emYk()P?5qVByrS1i1ckQtkn|g-U zf-Srr@{<=N0P6mpo}M1P`<=+6FdjhMnN|Rp(3$BBAyxL4*E5MLg=2);^`;;;kDBlS z2S7l<_%UN$R}gRb7TsaJKa5H-(^;F#ap&oesb4^d4&je^{LSCrKN1LSMY>G{hdr`n z@3f59U4}HRCW}dxp7!GEG?d0HZi}6{?N+FggTY|Eh{fcJ5K`IDp)@g+lSdV)e9NwY z|1%oTSBJ}scj%w8KkA}H0mwYCg0yPZK5rtwOtRsqyXSB0ls?XH6K`=MKGEq8VR191 zK>xnM*9_F2t;A`+f3j+MVwXwLO=RG;rzplmqhb)2r)VfwD9s5JD0v)IWF*Uhxlb(% zJb5+wnxw!Ks{xl}Lhj~zS5x(my}f0t#49jFwR>r!|-qg3{bk2 zrkfC1gNiMv_dCb@TNFZwUJZH>K8xt^2uuBGR~V)EKq61ytxesoV;HPWQ_Un(K24PR zv6OX8WCFe(U>E>u#>bYZ34f`goMQ#*6~WVf#aQ|Ivombm(WsfeqAU@}I7zzztgs7E zg%)eA9;lQc(V6;-HO-^jtNpmSElURQvb2c0el9@a0t_+8L7D9L@#&OJlh0QDBz~Yg z&RMLH_ao!FI1Zagi=sLF^o$~M4{2o%=|paI0POBSM|>E-APVPL7So{Vd8MKnr~P># zL_sVf+6wGvKL#R{ZdKhr47Jr>mVqB5GF)`Y1*vHGdejOj=np0|efWKf5%el~xYd^? ziXt{Bq_2rjBhdS81qgCSUsJA?@w4qKV!Z_?x3X^VQUnPhWo1L5Am3Pj`%>~ULp(ER zD`6(lp3oL1PKL;)f}h#+`}E200=_XDUC43KJX`wFH`^vWBxRF)g1Gjn9T`{ID7xvg zXl3@~Z4;^*PiiD>-tKIcT;Qx?!gSM2zGqZ-?x~pOmMkCJsGuxo-^8)sEE302LGgIB zaDk&`=W|i>Q!>yDV`q*KTd z7ZQ?Eni%+Kvh_aB0rJD8=3~?m3CoT)>Nqgon<>*IIoupT^!7!0;Jw zjZ)S_X&zH_D(ti2;o-%d-9ahP2$j;ZrjeTiiM<*uXRC*1?f?-)0)%>pTfckLv$FE| zBRCqA@4>|%Nwo=!TjQqFsQ8MU?e}NAhHoc(sl3UApqNlSv3cIIrA?aumhX zn|P;AXb8v@ltEJ3uN)2rj)SMs>b&dg<5_Ph&biu% z0V3t8+H%qdj5#XFfhra%7l>lH)#(?<4XN35X@*38Dm)v+`)l2H!lSo`C~+H(IKO`H z8!n4ms)lU|i`Yh!V2sI&I2ZvuJ%dzK{Ac!v1&pOr=eAPV+Ff!kl{opJ{IVQzP_#IntCwrJ`JMSjtSsde(=Iz#pm{NmQruqJM_mXXZgN-+owAIj zLv7%WOXSom%m+O%l++f0Pu>2wH1O<>KOc3Vj6zof7);*l>!$#~@XHOLyVv?~q`XA~ zp3~Js6Fp8jV>lf$Rc%HxzoTin%#PkuOPA&E32?;s7)r~&i(F@+zMi}0WVlDE-4=RA zezyXz7aA6}3g~M{UuHcJY-ZRjH0s1*6xZCGa!DNoSOal?uvD~du)59+DEd#g#xygG z31Hr!z?W>@dD}5S-upgVQFRA^b_w@-*P^CSanrgQAiGSNQm5{fA_*8u6)3!1VsWc=^uO z8x2&~m$!eP6k*Vzy}3Gz`urKO=mubBp<=`yqj}qwLO@bcj-QyY`Y71zTIe2I!w7&l z8$W6y+2mwEH@Hf-$#bpU*f?tQG%L|nqVeXmuC&h{P+Hx;eTj(%Rg^_^_b+Rm6sJHm z6QX_(iCphyUG0Cu+cf~*23gJIa9k-P20ZeVhohiY5b`yh^d-^3GfeGPz^%qgxgC)< z8OD0G_310RCcEU!48=XPwH8-1*56VPzu1%6oUMs@88BTrAM)tUPz#0Q9WU;+0p3O} zLFt|af~?YqK#ji7so9Izb7e~71zn+$zVkFgbWWZxUi5=h(;320JZptwq2?(|p5dQP zM+`^5pnYQ!5O9^t)L(xc&6}x?sivL>^~g=aPns58tKGHlX}QO?yX|=WOeGi(1jEHy zXqHo@%0LASo~?5*_fauqWAJsdw5o!l;;KJQ;gb&xahqiCK%!1Nvo&F_9C}NJ^VL~k z#@Anf>|nk(3>Yyz+-id|bE%};nr@Y&)T(-qt5f^?l;y8q!eN|iew2xFaB!0KtFG-x z%^Md$x1jAKKcWz+i;Fb&=p=`?- zU(`Z2Y1iW&g34_c1T-onn1d>&WVHbyC=f*Cp~DXv2X;&c$ld(;oRn?kbHWX18?K=- zkW#=VoJ`$a@N|paw(e#!q>myE<{s|dHuO9h>ga7exp07usdf#f2=y`F)C6E?Xad}@ zs}dsm9^rGCk+XSq|=lBLPhrT_jTLe_#X3H;wVi(Iwx$kGNq_1Oa?r3 zlCvS8J8=05xP_j`-cz^=h$ES&*XYdt;sC<7r*xFKgC)wVyK(+$1dHy^30#Ef~I_#<;_ zL0qeh!nMP7pW<9(UpKf5vB6o)Ms%-Y^L30k%GpLq9w=cpkhaU*HJfY)@BDRElj-+> z^(d(b7f!zSBWs7$Lf?b#hF-I?D+Uoo_JNi$TkV!lf_nmGt8(mO?o!=DBO+g;a1hZ( z?KoI{@A!%KpoNWiTz_|abp*tmE`-ySR(bGjM8{h#EG+``X`0$DN%y>AG~fC>o?L?;$FMu7XTPD6#JK+$}+=R!dF3oV#M0vd)vJ?KM3k05D< zpm%Z$VHCIZmIb=IF9$2tHuhuS+T?$pP$3kYmb(dXybvG?D9ELsF9mX;-3XZ1t$<0* zz0cLgFd4Sz>czU-BrN80DFf3!!rZMFyeN*stIQgK{tL~C4@wAfIPT*>L1fbYGnS1c zxIJ2J%3Ca`>#o=a;UpxGI}h{K`QcDHPZL zhzdypVW%|sIG`V-O&FBU%z318~Hy+Dc`h`iDs0CGz%&#);aD2oGMzBfH8`y%^1Ex?{SC{>aRn>jkkpr1SksU~8-Hbv(y_z-+bo&iwi3F*y zJkRy-y_^fI^p6xM;QMNS8q&-Z0ph^EhmIovBho&szr9qig`todsEbpEqj3W2N{#_( z+htL7LrFp^&5z=>THK1khOgR#xD8hQ_O z5S|cuoM1)#&hk)>)5m|n#{go`i_=E~srf@eK7Nu!chA84j-UjQRHdiBL9gsu2*9C2 zDDfM$iOM(Hivd9^gRfs*mMArpH0ig3#kue9(x;dxqsMDqJJn%+>2%H#wNTkm1*q@4 zq##Y;u&?%f97em_yDO%7ZrFMM7eo;f4Nsd|^P zsvwM5PJl$MWTyokP0t2;?wPUG{emthH<_FSME*G$gh5A#k>t)Z) z@q##jrU6PZ6afB3T7%#Ee+{RJIl;bM2c!%6V!&;4-<~hS`OqwP1V;fGNTidCb-p{Q z1<$L52^D!zFh>0loS?1;EW*gh$khWDh++F~EjrB@$SzXQNHzbYrUnZIV31vIqy?wT z&9Ub0Jj>v1+L)`0y5MBDDJ+{tkpb8F_m?hZma6kYWwR3iviU7~qc)s*FhRZ3@$k;eWj~Yl<`~gzQ>=oZ#J?b|q1uS=* z9!^zXY@};GSg%7GytvUtd6&bBBJXsPtEU0@NA9!PCgt(yidE*OjifoicdnH7&>u55 zRZDO17XlhksPOAlK!mw6zf`1Q4Z#FoO`?GyM|A6q%453w*>Q4^7a{C@+3Lo-ZBt`F34A zY~FP2V)6u;PwOzVzV2FCd}mfPb;+PjRV($Q-e~r-gdk_8*3l`blyp_LIMUkrXw%PY zcyY}pWtn}C#K0Z9N}Y!vR2cL|qDJ!uQrKDeb|xm7=@}W~Kxr8n6I01gh7}ZI4G9VV zm9;g0jA*}rfX6yoRy?GnLihDdE-o(S1O@5Raa$~fN_9g|xi)(7fUFD-;V&F4EVI*s z;5zm&jIU}iAZujT>q-EgkyP$b!n?}p6VP>8RZbm{ z=9q&{EGUD-y;KW|dwY8D2=i0DJi(oLA_2lUA2L6cQpZ6S!!VM80rLgl8PaT z#LEr?y=W*P)V)?^&hjDyiU-Lm)fGeDL-800OHyv97O@FC^#wVl8kCS+R*ZLlKwv(K zKflQjpKL7O2<0XTntlYzcsZ`C-@(F@a4iUFU^kvQZ+aC^%@u z6iVa7M;c@z+vm19%DMw9hVh~LYEy)qlk_Y)QtnJ)PtNchBXcywbBk83S7)SzoB zC5SvPByhtHEk<{1y<9)Lv6g{gAlZ%qr}NEz zs8@HX<2s73QxN7d2pHWr0DWP74({m&#JXi^;q|IrH%JOVE;{aq>nJ+R7F|sRt(7eVi<(ldJ=; z*S-Jsub#CTgx{|}E(8M0sn&PLy(}5Zc`EnZ`IO8DlkZv%02d8HwE)W?qYnaMqL%{o zfk4K?hC2>;#6Ysi^QQhUYfYcNy2v<1;n|KiarRz{$Ymy?*EfB!FbesC8=w5K4P4S|PQ?t|y>uMNpQkDh`? znmtLLp!{py|K?KuKX)dP^9DupW19cP{CSWJ{&NGm6wn9qDT4mH|E3ooc*JHzS2>~o z|L5?p79aG0K3I#1QCt72#O3cM5b84$5XIo9mk(>>zdcQU1RUTl_PODI@esxN=e7H* zuK1HdaEv}gqYnpv|M$m%{(XdBMgx7I@1Xp&{cn1KM?&>}bdvn_LG1ST8wQ&Z-GRv6 z&qNx4yaf%#vIwl^g|C{V2B zuc}ubGz5Qc;1_z9%?errFunD+Wn;ja7ZaeqvipSvW0pva+WHdleJ=%G%hzoKGqQEM z0I?dwDUW!9hy^I-sM}-e_~|p+z#m1gz2%u^9#Ah+gg4G(l6K8IYv>tXH|AqIzpKJm z$YW9rgU;_V@xS`JXA+?#fTblQDSh;ZhAzUqzA(^EW?@6j#a;yGOZXb2?!1I6Y}H=w z)%kN)JpYGzuh1rK-v4v`yM4gQ?!NT71n)ccZA?A>n~PiL%U=Pu#d>T(|%qAQ!=Haop53g5^QG?Nw=(1PuU=>e%dc6pSmYrC=Cqwh zEf?}CLcf4cP;Ti#U$=j37w^QZ_j66OU+52D7796uj>>kq;BEMewGnCg`p`qQm+K!t zgAyS&tKk8jX#jIwegTfL9%C8mI>j=;!*F<2oG&pqz-3xxTqtx)WWO%x5eb}bZGT#0 z;y(PD=->DcpQg$`E-bP8f%O|D^Y+a!Y{f{4&t9{Q8sF~#n1Z3!RLHF`%+l+)-h0;; zULqfo*-KNpZ1c*hW1+-QY-B#mO;s_|bdPbBp^1)V^(Z1wdaB0CLXpB|&bk{w>(Tc6 z^KLPvidU7H`MW|ME~AcGUgMX}h}~Sla=ZsgU}&zo3s7I=Ly(iY2CuiZ1&-(3eq2^% zHB%LH)T!^qV!SZ8HvL6k7C8Sw(FR-p(z->wzH~iyzFD zp92{|Se50JK{o)TK|z5(YIIad5tCzN;99*X1{TL=Zq%(KB=dOEGdn{2 zrv6!B2j-o}^ecrK3?8W|tHmK@qNSfU3rszRZ+4Ca7KHk9OPe$|xX(Q{gtxLF{npzl zx4g8SJg-jm>9n9!p-jlM6)UlTDHD4_tRO+TwOA zEsS-eq9tBn_LGJm(+BpIq5aJ*45OCQFz2&z;Id1~1IoN(Gl6?J#(r}+BU4IToXHpf zU{rHLKuKGS6^Gjg;C}=B<9`86m1a-@Wf&F!jO88-KRi4=uIWBC1%EjJOc2}qJp`$V zf=c3z+TEw1WirS8(#HPaIpsE&&qqF9LgxmAaEvgwOe~P02T<>`aJ(}xUF+89a8;By zfnx1er#bbMyE5JK$I6ZfHtu#<`>=*<`OCL^0SJsJ|lN5DzjSu(8{y#X#LtY z=zpV}b|ied;T0T#l%BvRF!C6HTP9Gsi=gk+^LT-?#tYM}W6X-`G^nCL zV>%Fv_bwsWOSi87B-mzpG(7JbcFSWa>T_<=C*|fSQ%S{PQx-!DuC%b(TIj97QZ*Fy zb@Wv!Q^3W9uF6l*M;2A$Q)Ay?>Ffo4CvT%K3#OBl*cq6Z3js3>+|E{6R$&=iO-}~C zbAy&R`R7}DRag}jbo6n|8+|QyEa2Ju_TJ66$HJz%tz7JC8~d61`gg9MbBDu`{XKJ7 zBQS?uuI)-MPyG-x*OL^l=wZ(Ns=M1v&uy!!T4h1%1hKce=jdji1QN86qiu_XsyL%^ zjJt{gq(?lj2=%&gy{@ghmxFj(pat?5{cfj0HLXGKhVwbDwu_`T-{AWa+bMmoR8==! z---0yDzOdm;N>;iNUBvvQWQk0NKh;^rT3}=A_4-^rHd5l)r1lPA|hR-cj>+Nnjli7MS3R` z>5$MufP^r||9j`1S+i#DoiFf#1xXI){Pt7!es*yYX37eq;fElFYRs#&HpkB$5(%gM z8oD*M$3BGC;T+92UGCJSer!x+xI~RYCKTkhEBnKO%L2`RsV~_}^PE zz#Gbe7Py8!Nmm7=M@?O4a)r5VCveXv6s(~l*3?qX%4!j#CK;{WzhRH}Lq^pYR+!uB zme)G9{Qm`St5BNHp#%l~p&Dn-{P!O~bX) zLiy*1E>2eHME$0$LYp4w2Ar-Y=FjWS&Vt!9WyE8xjsS&O-2vuF8A*Q9@nC;uHH&8I!?)$7RieNDio=I?+P-E<$kuZLYE zzeo;EdzdQiu~eF<>4-C*Xwc-u<6b70GY!ea%wus@A(Z1J?CCY^uM5}bFBG6trQhmp zGkEbkD~fb4s5PJqF{l&|MAeGMwD;nEzS9QXP)=3`n2qhY*&|swxMKV4*t^1YF6t%& zgVWkX3VIT#4^QPWrZB^1M54IkL{dKSd>7xSLyQy@j@rRzT-On{Z9-X5o@K$u)m$) zSW!#pjuShw(tF!r6rk@iy7_r|$p?YtJGi>Bb_9&Z6O=~7-^YTfB ztdX*_98b&onhy${==%-Igd-e)(cny1`1dNGROnNe+4`vImrzQ?*u+XcyNlS0Qz5BP z!+bz0n?)gT)!P;Jz!s%6I2o@V08B9p8ox~e`lg=U0%vc(&heOOIgWS>bjhiysoBbU zGm)&M%`ZO1PU(_c{=m8gblBLC3jO+ZOcM+k!_pV6hXVrJ{3P8zVn^FTQ&4b;teqrU zyFzIarp14u5fjPrPQ-OI6o^51ks_)2t#yQ>`mUmihp77M6euwQKeAUY1_rfkdvBOG zG%Gs2&ok3JUQL^q`R_+3lqPUJZ&IOix@wD)asiUH#ALx_vu2W{dZ-f3&fkxLQCgq-t-ij~%?1=_V8GFER(JekJd@qMe{~Dy`krgm(tamZvGLcnL7J8<0+~=-<(e;zZ4BLV+35;c%>VYo&BbU zD5##8T76q`GH#c^_CmsG&S@)Mrd~2n);;_j+-|l8Cx6ppAn}TiwI;E43oW}i%?P9WTK&&)J$9*w6ILo8*kA*^URl{QVTX(=f3i6yo{lea5#-h z@_m*vSXcvAY)Q}kxrerAtK6sNtHVkiMv4v?RJ0t+=$0Ebjl`{+i*(2B-vM0=(F!Wm zWF)e7k15ajET1*`+P;t8-0$<$O06!O%BZmL-)|~{6T8`ok3Jem#hjfXP!x!*0cIGUA)7)Y8t+rS`L7tnF)> zyW4|i?~KRW(`vSLXSXZA_Yy%Dld3VPn#8Y87Vu2iQCEI|8z;W`PIf|a^Be?tvOvJo z?jCe&wqX|Gk?3v>n3cA@r>CdhGDlNWMm6#*-3mQ!x4@G^^TTFb3Y2&JM#0k{$V(~Tl2Lu3ys$2*%g{_ z=%;k&zGqasWD_)X%jHUw@OlvXBrUW>z^wbz@$PJ@nY3gBYR(i7&gi$?5XsNyo?VIR zU9fMipYFL#YP+IONRmg7LWf3qYi_n@ zF1AzZvc=&8G|V&3LFi)r5{*gM_A1mNvae4Bdq|Ls1EX$GgA8qED}p!slLwu<)=r!UrzEj=8PYZtgLF7$q{k z0ziO8U{l2mA-pdP9ImmAm(1p^cyaq+b?vSo31x7-`o z+!>`fHko$`Ayt(UUnh^5I|Haa80ZCfPaJ0d-*vhFQ;oY~0%)j}o5w$y=5gl7QzS{i zc>X7>r{Df6EENkt=LFHYR5bBY)Lh zjTXV`CSDrPopipt>N^~1o?Xwl;-8z;v^IxId+r>Y!Bcz*wQga?;y+-jn+cC%HK0(B zYTgzvv{RoP%r*%?Cc})JuA&LKwrHV#lY51N;9}nU@`G_|L|Lw9&t^0vnx-Wfkn@{$ zN!ZJ&Fhxnud*FX*)kCCmvpK**OLA9 zjElIQPN#tn>zR^GZI*rfskVw4G_|;x;)h1cmqdO#Y1XXI{+x9cDQW&Jn;5oM)`0Rzr7iLTW%)0GfzdhJ)Rpe( z7N1YmjH(vb1M<`#1levxA| zV1jKusk*W8XPgg_mfvEKI5MUsKfNG4t>>`6m^T05DfWsad8A+a`}NRSSGP?UQ3E>T@i`Nz?@bMIDsRnvU@C5EuR-|>;!|)AB<_`n~zei z|KAwLTs+9tf4?}l|ADmC9*=SRsom-3Eaz&V(s9C%5hq?fB)sV~WTY`S>eejA>D|ar z^PYc^kfnEEPS@TcR__E}6tS1Mkmj~Tp5Lz3a0WG}!>+HUnO)47hc;0(+3Gf&<9&6n zDf}dwpS*2`%KPjP?`qzywWfVHUs) zL`Uhah||Z)qRQsRNjeT0FQIMRrZwgWEdpzV-&LA#?7y{qHaXT=#$wt$sbW$;g_;Bm zZ4onu8_u8Zu~gExn!C+A_t<=JPgaYT8zIh*I zL$O9XbwXn0qo+IgnmhOs6}EBScbW)~o%bzzcZ}JTf~{qt+M)9g9fnK4^2&mYS|+#A zGG6$S&BJepZlppT$q{qj%OX9^=X!?BjDJ!EP_6jSys}>PVB0W^!oZk`SOZ4#Ql=}7 zZQGj!$*8&tPrqyO$gyC2ayK<7tp|OEul%6o@I@0Sy#iy0Llg*F(ECVZamRBq-8D?* zq*`hloh0@?jgw!`xoWa+#LMIJd?p$Tacma1f@9yOZ)^Z89y@daXlHl78Ag@>mXP`L zMM={yOfg5T75e%c1Ae{uVqP0pzA>Z$m%TvOP8Pi&b*jHHXKs0e_yS*leEu6~iI_cN zmvBmg!v?9>cP6N@t)Ay*J}4+Ic^c@B%FOp-YfnRdsdkWEangOW;+966uQH@1IP~mtS{78M@# zG24yUH$ZLk^G4nEK)LepRAz2Boi|~)2h-jmJG&xSQg_XKH}mpo#cycTv045&Cjq?w zLr;1#%TlGnn7;?V?s(HvlE`s)i&8g(ECsC_Br8A3)X6NBiIIGh5(6~JC7Et zy^i6dJO6Of%zMF|cl~SiMF8dV)c2bAL}9U|MwQQwWot9vuK#)7vH|_`JD}%R zTVr6HJRmrKQMyL8&3*Vo9hnSN1=hrlyHX51kQKB-2s%1MA#vpgOkE)pxe%n--7ryl zlf_DuR#_P=>}@gUUVk(#d(N~rwfgn`@wJFkk0fLBoo$D{El@kq+Y=}tjy=IldJdem z$<#^O7}$Q|P3@kQrCBQyblCbezf_;wI5o!3T`ywu%F}QCAfDeK$@g&Wkw$WQtn&-r zs`GgchWYn0wGH5x0jq6vn(%Ew_|$R5sdi$B&NdjrY;IW8y@7pM z3a|3-2cs9vDHGRW>@GkDHA>*m`07)k21-W5n!6lv~Faqpv_t|Rj)FPIu%f3El$eZ z$j8N+1*OITbic4e$=PO?lFfBj(}(am7SN9vSOm_x1Y+vh60Xf%+}5QFND@Bu9387u zH`J|nwZnYe&RADSCsw_~%=a&Jw89kG+1}lB{8u$Nv01tp;8O~nlI>r^i;e-aWzCxU zMno|js;Vquz*eS`A* zMVh~Pbk{HWpk@%N>9d`VOBK00uK-g#=TJG+9$p_KHH#DZD>Z^D!c7T#r=V&Mzr!AV%I0+Lt>_1rTA3Xa- zjEqNPhs$LYz?4@KPqV?U_~yF&WJ}ZT8-QdWZ+fvf(pK&sB#3^=IG8FaX*Ta+*o+O{ zj<0JO5Kc}$#x}LYJ~IP~1}N)opu2Uc8XJ1sD=}*ohuTHS;xTaebeX4TMTw{9?xFUl z3(O`LY_0oMRnc{>oSkj$M727dQt13Dama&>Dd6nXt_F%bv%eShmZp`5OnBnsx3#;RsGk{`vh`&m zv!_^DJXrfeNlOxI<5-{S0gRmj$Fi>ID~Y5t!5X4Gf(?n=U?+n0F ztBns`@(DGZX{t)nn7PwMvREJ+2naK>Eg2#X{4RR8nNa@Q_5&K`Tw5fmRXyoB+I{R( zZftF$W$&;(m^$U_d2yf&%O6&T`PDo-hQ@q7-#Juy6JcQ60;E!j+BC8Oat253^TPG? zZ6Fapy@^%`jmzpElRer|%XbVVy{kE$69vt*byh;6K^~uVcW!DqZ2t z4XI{eYpNh-)*E^d#2sDP@vKc~QV$Z+}``J~{4f zgf;II1lUHanv#RN#fgVCH4d9&0?&R0o0gQ6v`7(q_fXe7gNI-8LcsZ(jQYD+r+29K zCNGyc!|3S?uds-y5__!K%o=ccXxy++z}rwFiEOt7{=WZ=8z~z=TbdhR1FT74F_?sv ze^c&Cpu3&HxJ~1_*|>>*5C@Sxwo!2H2JlN7)1LYH>ww8(gY84MY)6tL9Z1yvTQuMe z^lWLE@t}QX-AD!eoJa<;LT3bDOdhG?2ocB>eSpQ(IZmcDw~XfD$-eTpDGL&l)4@A6 z;AKxR`bO1PTb=7BgU8E%SX#_7FQWH^$u;D;nnQVOMt9ST*}JA>5o@XdZ%BB~{+G>Q z+H1bLmRl5p)F%p(^vyGgZM;3V>@aV)(Ii{wfmY{ji5fy)rev~6-tF$VQ1AM$-Yg)` zFGaA!POW^ow_nNxPX`yiiazK&b{zY;5ag*JZ3crMODu17NiIli&wF**{B<-NLGini zj%e1JLd(>sxtZk}K>C*Heij#>FeQ5?U|gMBt$C@oLajd9eXGC9cWb05mUn$9-L>z= zvs>1ExypXrrn*I4O3w1nGQ7S``&G0#byI;Cw9*ce-eHp7in8lT{(R+UTv*aM1o6Iz zEJ=iT&$^oUCQKiFG;tNm!)GIl^^dQ0V4!;e-YwUR&~jUN8hDm@C}}Xi?ytUTupaa; zv%&6&BC&#XNXhc;BSE60t(NSn#^l=|sYwWI~dAL@N)~AoQ(FE9^s?dQ10V&M#mwMLn(Ah?s zz+^}jG~+#+<$|%}U9Ai3AJ2S8Acul?eqWZeA${uw%jQ!m zD#NP(m+Qkamslo&|B|ZQ_VmRv0`T0no4eLK9KGjSejXR1qMCSFT)I)$j5i$6ejbJT zax@eDUK^u8GB-?hbi%}(XY@wK=Bp;1Uh|hsUI1h6Gr#(4GGmA4U;lDH*NP3sgC=g< zr}vi%i z?Mzo7HF9&5V2);NC)UlPl2hdE=V?86_piJW;o+K_ascAilouHxa_E}wnBPgZO~#E= z+CK0(r`COM@0^J|(coPRqI!DiPL|5p)_#p15J^8Xc^D-SQ^MIFmpEGkx2UBF3=}Xa^fP&G~3XX z+c;*v9&%qICj#Fh(#VLrTmtt(Qmfp5f1dE@b<%G83i5>Ah>itRP182RnK zF58Y>!&;G5z|2}-DX?f88N;+TNAYU49eL}%7|X=Vv&vopZL3=Xk*&6)G%NyQtAIo7 z()WM}xnx)lm<6>!j)J_Pgv*@$7I?v@fHxQ(v(lcqtibJzTF6iZCfbpJQPqT(`yG!y z>?b9^oCGk8{-hTabU@K^=NvGobcxrz2v}mPY0aWQFe+b@SfLgtS(|l*UzHjHP#DPo zOaVVsdSOS2nA^Gd;Em|`s6#cGQ*E|;a_UiIZ%BbigAl50VSq8DYZ4RtveshC1u&N| zFnhR={xnjsasHnM8FYjtaGG_jczUyt9InkCQ#Aob$*7imf0;ucfbNn-#z>MxU(%Q= zT3TD_rPY{->%~yO2P8{q0a=~b>@sUZ`r-)1QS06ad@$P#7|&WdO}s=`^y9A%V=X{p z`$GkPuIM*O3Q`%b!{pi9OUe<>Ocp1k`87)D+ zF%+f4FH0C9VmKfBI>qObOZ8n|n=eV%IzzQoM>?MdiSpIR(0wIlK4ZT@2aPSEky2Gv zEh#M}=PS8w;_Zx5qquyzaQZOw6}u==J9y+%$*&v%L+vqp2mhd+uQGI5B%;1zG}UB= zsq7RL4ETu>qa{RnG3e$>Cjk-V zro~9MoK2#u_=<=g%_1RxvU70YQM~8Ii=gG`!M}ttSqjkwB~)xP?8%{}0${^N)IvaN zb58zKp^FMd0|r-vKnD>AvK>_l0 z7I?$ja!1EF(xKkafS`sKz^4UHzrGPYY9U?KLrRbZlVzZ)b(CxgQYKx~*5LVBNp0BgB=Sjbx(=R%?hirUz1Fh@kBq*7# z7kYfY%s=s%rh3;#A?Z<5IX;#`ruq0S>Csl;+wcklr~UXO-sm+pQ8rY!^j#qK6Ni} zM<^5(#3|(jhQ`wo0ps%_laTXFtrCsL4YDUfC5OK?g~dA*OHZQ9!Mh7;M?ch9ZafkY zcmN38nfAv)53_r&-h6u08S?OoxYrdEvTJk^-}e?RL0X53kVFV1AS`?t^_7f$@lu*j zoW9%~F9L{z$>w3%5_|Yg@OA5#A9i#8{5p`Q?rL)+8X6i8;}4E5sz?kx^#k`CO6bKR zB37`i-Q*gfntDfsJd@9$YZOUqLUd)zywpMlUma4s+RN25UYlrZ7m|^E&~tLC?dzSY zxW>3%=&~zY^5qMComJ=M@phD? zi|77k}pYjj42n2lIK%j#^U!HQvF#YVhb7ODMfYcUfVFeyzk#$1(aXAwzj@Sm~*1O z*zFPgeC%*T*=u{POqnuMGT45*-t?NVLYffW*YQd3%}EO%v(4cgN+yafF9<_ebad9< z&YZk*L_hfYRoW$Q?(cD#iW22#VLxQMrNhcmKN_z}rB603Gk`2qvCHejf{Iq;q`Pk* z98*n$+FzvCZTm9kB;pIlZ|vElaY_S<5VuAkowFz+tlKYXclOjrPBJkw)ho~RoK?#0 zw$2}m8r!S;dy8W~_G*Q#eq5sNp;3;bi(y;y{>I?vPBzrLyxlmvKg+I2?T>*SRa`*@n^vWlaShVSI;N#yk0*!4t_E2nNkye8HJrQxaxdp~TT?ANuL7cxQ#jMC5o_Jt-<;viv*x z=RgOXe~|RV9(<`4i-N{}*@%&_EMMAWQ!4UB)*gYu9A!?Bi-ol8zY#-BebT&{@qDT3 zYio?(zGncEyvw;2)*j%+n5VA!2Pg9r;(lN|=c7}4kLmyCwA)f%1VWRzrsIGN>OA&w zb}{=e;hz^>rMzv0D9%z*dUJP5;j8%6i!Yax$q0{7C_?_4*iClr6Nz}}rhW{=BfcUo z8JK}<_LCrqY@A{bDgixQVjwP9RdS&{Fn6@S}i5CDXS z_`f&?(m5GIq={x~NHv_rQO3efy#VzcO^9R$x zx=C~Or7x}@S|!>WvdnWMMB81n{eO3^kzOW~+#tD0@`TjiO)ng-{Q-QyDr$be4k9LCT#2tWiw;Ln2j_zpb~!hN_nvD97WE-@qca2a#{I-s zVrJ?bVzbHoj$b`FKa=DVDOZs^!Zf?06vhj*IE()rA{DtQ#3yeiJ8t-H7w41<=>!(h z#J{$(r4#ZyuC#e&bP)Xb#-*#4K3Y{zr|*y%rd(l;ccBp~)JYudmY^kPq!F5BGm#ul7}MWu_yyIdEB5?)&~{0OtiXbH6UrE(0@*EfIWufgP} zofIHK^SS+asD&{AU(2g}E`J&x+Tts!AP)?V|Cs)^I`R3}&rG>9hU`=c=X=xMy5m#6EM(zF4)z1msWV@ zU1vAei;ANCPOuO0ZhIDw+cO`7$@^fCrFL|(%q=;^1<1C3cuK&iM)uWR(#tC%5)#pU zt^y!S=AAbYvo)D^F_$+Q+Ija^h4RyH%KI|fxDIm#+3WfS?&onviPOo~sW4i~-5IOh z2MQtjb$V)Q!G~Zaz5awpV?*hFdQW_^wlZc^HZypEeIMl`Bh8K(R_7#-E} zI)f+l>L59t(euEN%UW0jnZKGE)%}n+Y!8Jj%R5AA(X-kb9YiL4{(*--SL>nU|>OrTa3mTb5B+k$aSp>#P&&c26mN|2+{g4uJQ1+Sab(k)eL zlbUJ^>^+8Gw=n7jscQ?4r0&ZDV{JUtaGDXHY(!@`C99UrI1^@mw4bAG&TOLwKyyRD*(^{Jdzg z;T%T%ex4m$u%J1Hy0Lbruc}#ql#Z}4CHYKwkARRvob(ONsOd9?_^Z|$3YxoK82#LK zi(8Y|ROGv=b;YE?jsYViryG?n7kr}0uXyJslaYqlZwRV7;07E{b!FuY*>WHe-h)wz z3;}9mIZzu%fj|o#S0OZlQwo7`K4OVG+XpiBugjl%1;hj;CNLJJ6A6b}&8DqMnK=M} zb6UpZFj|c8l@`oFt*Bk&B~msJF2l;)*Q}8OFf<<*F&zUTutj&*2|fF+NrvJk z`aNTRAvwE8Qp4X5iE$zk-_^^2@jil_=l(QLyXiOQGt8*QcjXG%hrrvn|IN2OIu*;F zXpSu)RZZ{Y{dl>VYV6V@J%EeY^N(7F*F8s{(i#>J1c};B`{C3;PV{U5r5i?N$Ho;4ne|wfr zIM3&cTy2A~FSYm_=ssrBvnBAB#UEqB@Yj%6j-s#B=fI67T4lcR2 zVsBE2*OCqVzSEOh;y@3Q$`LAoKuSog8*08=>hdB?eT8Yvvog_z6_D?8q3IMB=(dj( zlt}3?iq@3Zq-#sKhVNnKI>31~sHBxHho4Z1`*ZC0j3I<%vQx0?_Ks>y+EUTy%Tbg= zJY!pO%4e{f&d=q%SiV?UUFUo7AVm%yC!?-6d2ALZkXGSJ1TLk14v$&!rn}2fZIOa= z9S5kNOoGP#AHI!*hEvc&^#gtW6kp_^vZ??ADjMJgTff6-Y1=Ly6@H{oYCA%es7vfD zBO#ajPGYS;Yz0KOj4j+%AzcHai@LPT1w)>aG8lJ}Z|*N%qhM|Qf(VvmyiUI`MJ;3> zQvopKPLo@Kq1@CItR(=0$7z#1zDRjNx|Y3-*&kC;-%kpCzViq)2)xX)KEa$4&T_UM zMi#T?t0=~g(9_%V>{xmg81ys^{*MR{I_@5N^u3FsWpl)WA}PalPHR;x9-!*>*B&$K`zCP(?h}c9U`Owq<56D7H zzp{ZU2&HAqu6MHX5jk&@X@9r6x>^L}LQVW^1Hiij;E4!4K21gCRm!mb^Vo1`dQcrS z_`?oc#Maz|Q~{g?-P!M3tK?rF?%^G;iFuWGzptL4&Xm;i=}#K3nciN>AtNn9T+Ay9 z+p^`s0i?d)chv-zLrCXNN9kkkFf~z~O!6R3&X!z;=B6)kFj^{{ohU6+(%oDp~ZLH95X}P_A`M@R>ha?%U0#pGrvCEmsPOze@fdwqaqI~ z$nCkx`na?TH>&&2k4@n!7_c&(iS1Cx%TbJ%9r!^YP}y(@GHffsX#1ee&@S?x24%U5Y> zZxj0~;J0P==hT$hw=dn&Zr5*}B-W=?BSbY-C@StsOE*2!(dM;ePD#srxaR$~d$8fv zCAqA}qNBY#;vJCf;b8Hn-cg32H%90QLbTBexR@d$sni?@!TNijHgCj1&~C&vc7aX(^IIVlp-b z9CJRBQ!*|XL2?LdFWISMoCcN5lWd*MS+2~(71gKp^S0*NV@EhAaJ%Y;@_xsKIswDN zKC3+>@i~vi3pn)ieD_D@9)2eSMTraCY$1dpt3J4t9Jg9r5t2h7$ivH0Fn*+$>!gz_ z9@gC;vP(MM_C4JwQbsBUJxY;0iXp$HT@HsRk*?L_d@S^skoa-L?S;_J70o~^AC7Z_ zmjU!tZf?zkpH@F)@cLUcd5%EGeqQMuy)-lXn-OwSOrrbxb>D8}=iAgV+*5Sl+bVC7 zKY`@(^YiE2`z*;1XnE*}=agDJdy#?XLOhI~w|N2@nJgCq@XijtZ|^DgB;&7haA-c! zjuh_ctf6ru6L?NZ{ls4mN5UN!u?JYdy3ALu+=X-dHZoe44s`<4YPzxBCCX={DqPyF z+*hdH&@oyN2B`U*W0uYxUpe{p89K{daPrKl`=33?h*1maVL-`5_t;pe-QQ0_Qn2}b zj){!AGXqRl45(J$XMf`_Wd-6YX@Jx^&n8rVV$FyJK#^Go1h{Z5{xxgYUre5DFl4JJ zdMGy6ZmIbn2i?lP-rYDj-G!9h+hABoV1nP}!1Jb$x(QoJ+Uq=6xpAvwC16o1Ad{XQ z^=-sNo|LXc%IFcxCgG7qLtq{!eQl@;`@kqL(E5td7tbH|^s!?1-uJI@KXGc|V=uMs z5v`dr@t9z3p}&YvXwAe@Zy?Ey1}eAAIO#2}-#5p;31i+k?)&*ZlRE|);{wpjr!Db{#_jo^50(mXU%gF6^4*R`78Z6^2Jm% zZ}DL_atOp*_8XV40HG13Ucs(sEn6WpEL`D*@KZDDlHmQnXYu6ly~Nvpk7u~L^)+&9 zWMig-^x+S1SiZNd^dEMCHO%2k!5+?9Y&8!r?T>d!VE5S)C!!CA`_FmQ@IkIO)r=Lc zoD%Yw4j1&E6h!L>QI(^z_%k4S6wrNACJXH1LngTmDOgFdD9oBre%7!EEI%7H^#^8- zm|AnkTps^LHvU?Z&7n8X1JhmrNpGJqqXl$2JTrjo9|P&dE&82Zm8>L?{4u_bQ3|WO z@kimds~DgRhyTF2_aaRpclu+!F$?L-`|@UzU&=Ujy1|1${%acK@K+8ctA*lR7})^B zkJpTr14_|8fNF3HPz})gO9Hi3m#CFVKS@4(@#Nko80lOfAQ0P-T?$u3cNa+C`VdaZ zTjB)NCpKQkRvv^=XHn5BE9kTH_8rce>S}#Aw?b+vDudi47QHf=dUgHeWW0FC7&&#S z*;v*nhFD#cSwF4UU&!aZ>Q<;e`Epon64A+WtF*SUs-NW_!Jy|3NUDkxG4(UJj0dsT zt_BG8Zy_xLVPv$njJk_=sD;WKA~!Ft$Rn27_=-GTEUgoXeW{{j+g z^dIH#zY4jkx z$LIn{@z;5SoaUSLySlqU-%5qI5q?g-oMOlNq5q5>jQcngzsgMhjfw;Slh8D*rmT?%+Tq2?L;SV_U)vQ-jEb~yOUhQ zO=zX7j%T&hmZmZqKK*7rLf0ajK+N#(>NKsWA&^iwo4Y9thg-V1_Jx&h#((Qgur(~R zywx8*mCf@|%7C&`MJLtjx)IwL^UnkhrR=GiA8Op`%BvM8?)QfUQOy|}g$fH{W_z(X~+fDZm*1j`sD5%ClT>BbcWk?S$Bd0o*y%>?B z?L9{Y_kL^7Rlbwo7ao=~pJ`Y*#bZUfH$SeZYWsV5IA%wAlU?IMQ7`zu25PI2f;NcJ z>ee-Lo&O~*XkY4pNGDYg`905qNIn^N_D*Q z)e7@Z56$SqGSg|THbuC)KsGY&@`+cxZMKA}sTEOQqj|*vw3f}MsO&5+bB)(ICd#yY zGjY%r3~O_R@Uc6Z$fbDGx0(DycqHo@cx+q)=Ll9JB(Z_`UDwx8~sy z;Y}+XoJ#B@4=-MZ7I^HPIeP|5+Ea|mn*Lh~ z9UiFa;J`ONnnjM${amzOYe|ZMEqx`)cxhQgy0q6z8o~;339@5`xF{y$my2W<_ zNDfRCWm0FA02GKE9UB93eHm0>mQ4rT- z86kDH6Y5tK-rM*zn~F_7to~i9ve?RFf#E5k0JMB%CJKHj zW{}fayxUQ2(|YkSlrJvA|E}smfHx3k%{ZQawF1vN*&FI@4P=nTxd3CN$}!Swtc>r% z$n5Ube~=v6^6JVi`8*G|qZwunBQQ+V2lc3&u1hm6h${ryha3kfDZXdk_uo0Q$Z*|# z`66%cv;Eqk=cz*DS%C$Q>GX*_5}^}A&&koVDP6rZgy^Kc7V0^d6$&hL%vX;TgknlK zxg!yt)EMq%E^;2z!_AjtwyhYsjpg|%Fzf!_rOqs0=9RwNpU5pk+|N!-2pOd&S|Ha> z*?3PVGZMk}t86irM%ed3oG^ ziq`a1I;dpEFXa4vCIZn1ZD?8^Je?v_zz(ux$hkV__@>m1gwDdf(jX$2;Xe!gCz4!W zGBdS6_m5nEoq-Fm+s2=UBfEf|JlR0f!IKVP^@<_T1ukobPqh$KHf$dbImWIen7HUP zEco)9ZFB!q=@&k&Ehw}_g|1XipZcNZ3Iq$b%zYE#?1CAi=_i%+#A_ZuLQ+jr4m&*4 z!!R>J@bz@}M=@2$WyZwSkactx#BOX_;PhsMyVF9h)1<|Kw>dPHTH5thu;DoUN_qLS z&4b^r@bmhcKp#4=s%ZF*+Rc&$CB9;A5>W2#3L5F0kC%v`TP!T9O*GUeetVy;vVT@Q zp5pk(IrBfW0Ib8Ff~Y(czc@aL7b>Okx!qe*`noRs+tJo|1W#PBm&Oq}YSlZ&;EXh{ zC0W$iC7H}IUCuXMe3hs^eQ9>mH9OA^ov%rO+ga#78#=(;i9=0TaTjdV&zVh z1k5)1gl_+S>XIj<5FO`Zj~>gFE_kJ_#EZB!8pauT6Oap}a?XiEN<4^xG#EM4G+^m# znGJmyjLHM#jy+3iYX7<6)5CRLM#hJ?StBTQK1u@MX5Jwxo}BLIb4Mn+TvZs#|4@_q zuRO$JF(Bx3`+3Z0iqxiDk5QhQ}NS z1C@8>n$Jh-|0Ejz6%-BVe>0f_O|dW4v}AY1DDFnDwE}V4Izj`b>@Kfwl zuiyY6Rz)GcfPZ@K{j9TBS>`{cn=gBcAO1)J6upuO;5cEsdg_!5KBeO|Zoc0_Qd3`8 zC4M%FHmD{_sspPofPHdXL6jhEzy&H?cxpZ7=n~3Jw8$axTn>BqdzXsdlMvyVQE;0F z0W2lBLHC5iNFanVI`|XSRbi#h8mf=izAiWo|NeC8L5%RD*R|iz7D?A;N(xd^?Zf`A ziZvTC?y^2MglV@U!3UwE3vDtCs1kkFVM#@!mt)s|Fx#8drN0D9Ppwz=qE!HWLCY!m z@mq2_A;ev&FQfpyr|-O>QE5db4F9Nk=Tk`K>a412`xERU_;zWvRi6S!O4*I^;<6cJAxo?w!;!@z8E?^Kb&>V2E&KYE9(~Q z0r%*AzmRc$WSzfz$6UVjlcYc+?uEQmEQS16S6s%t*C}=+?@G0Dkg7FwFH}VnkRxB^ zINl#=quuCf!65JY4qaldtYy!CCA?7YGW&Et%gTvOQF5JRzaSch%DHnZ%1;Wp0rAH_xbGI zH%BV?5FRpavQP~1`~(D0U+~xs(0gtJ7x4YYPn=YcjfFc0hct0!hcfy)=2eWe3A4S z8*_b03B*=k{{Z5ZuzyBL$1}d#Jy7ErQ0n(f&50C-#`}~cENb)9Gt**So6auks2}}UHpRAO79^?owMbS^m6P< zY*XN68S)q)Y=`gqnC`xIV2~=Ak!>Is?XjZv$D-0d(MoqNfh-p{DNe7O8};HncN_;- zx#YJxJg+@e`EIs%#q+Q50$I8Gf&Lu((N2R_(GC$C)^dcnLH4^5nRS66m(tU#v^)UT zj6PN2YHK+dTw35kBptq9YMU?Ec7b8ZnPn}P?)E`IKQU3~TU&LCZfDGx>)tm(?EFz! zo)`N8L&xO&BDk%Q@DU1D3{xK;WZ8hZYL(vZHWKN!GU2vkEXoVjqcst^(;W)!Ey6b`~~^`;7Z@K5uCu-yhzUQn)9U zbn=Bh-%4lqGhOtePZO9s5#NvF=WXpDZWYvGmkRkGl)ZISl>Zv;O^<+d*8rkYBA|r8 z(4`=qN(%@|Ne?xYNP|dF*MR0QbP~jFx0?#`0ahpd)B+od-i_+afwS^&n)!$ ze(&r4T-SB(hhZ*5j=Tbnf<#C6A#s$t)tCEpGL&$V$(plW4`V8-HKa7b?PR7 zI>RjP$`fHI%jD`Zx)vYlvHHb$=F7YNvT^MEt9O5`YsX5%k^Avzh{N9paT_T3k$XHR zYKIkehEDN4_lLl(eID({*xRh8Em515CtAxd>ql31q0l|fpkN;H?zNyuw))@89o}Y zzk0OS+t_v=avnUa7H(hD0r?-mLWxzbwOh2PHC21T)OLwQ(~&Z!AmGU5jy;OWlg(ZHl$u$XBgj z$X`vxnYaWcvDjUm9uAl#gJ@7|F;g@u7oB@0>T74@I(r=2mQnBQ*xyf4x?t&il1lo> z+;=5{%KdbIa+B>8_F`#`Y&_!h(=P!lM#G02iOv+cP~&+^6ARhbdo1V(x#Ogw7l#lK`}WTeDFDS1a2*zzopq55oV_5wQJ#UJTIX)lLOpr0|K zT{6zaZ#coG{k1Lac#!lKnU_@d=Sp66xlGKk{;(dK&DmiY4@gow{S>^_RD=n?o> zWGb&;KO`7p>afnAZ*U*8bQ6lMjA2tGM~og|oNZ=Bhw^eQA=p`?e1l{1qjC=Km-kS zM7`UtQWLizM1YF=5Nb2=%~5BfF^bdnE z`1J_4|0;?n&XVQ`Mzzn1W!rV!xTJAC`5ZbQ&JS770N;W6leLvI#IM-@FI33CiIIaL zSt*)=DctQ-^Y#AkCnkElrw%)%2FEDI`A=+(8~_$lR{t^h;vX!e2FQ;5XTNP^_i=;I z0N+=#d1dmu_6hHHZ|KwSv*FfqFMJ&oo4V775Z{jpF1&i`JD-$;X|288`N@sFXnf&w zv6~rRgB*-h#}lB>!#?u8HPX)65jHHvLfLCgw9cSPg5MWrG+#3nw{jKgr~_~8_Fxjd z?WuA-t$fwe!zArurFz>4&jDBH@&Ex}eOn4lPEnB}2tvAQoCUx>j82SSO{D7skM764 zj$N_1;QE7>BF0<#D%OV5^k$ZOFBEnx5$UVzHZ zLsudx-=v#1+2@otEb+*qaIi@z0T8o62PBKW!)HMTnyC1@GZwz5D`>kBQ--0Xqn^R2 zXOe^E{7hR18uv^5@LjeC4D*Nx-LN-XqjtJE793^*l+DnKx^NUZWfB>cD=$%h_l?Br z2et|pWaLv8l_s81SnmgGQ#k;N7*jiz{_z4)xX;fHJ@cNS0~aji{1C}M&aZ~WD(N=O z&HsLT3~6~?w|<$-)l_#^;A{BJE4(|zi(2D`dj5)n=)MKvcMbuYvA6ZF_s;H(#9lc! zU`N7eqm0IB;OiRR0t|!NtzYt(AWfffoa{BnLDW!eNHh}c){BXR?2C+ znzQtzi;2(mKTk64B>&-#BAlxbPjx~!tvO_wnLWAJ;LL2$*aVyWSgv$R6TS4sa*BBO zP2ga0F9Scn0J0fvU#C}vLBfp%zcUlWi`&fz^tnn6cg%WN*I}_OrK?G(>cOekDRw2k z@kA0cNCccyA$ZyAE$M6q!3^!k)k6c%IU4^xf47%lXua1@8t5?#FW@Ne!j1?OK|W@Xxh9FA8dQ*`y`)q%eGL1P0Jdu>8B#>Uzi+9IjZ~B z**tTQy7M2E%7ZOC3& zUMgc$TN)sWZflc?|Ngzu#l56nS9m>U&rJGu3Ke|`FMGJMhoGj-f-TTxC0x^$Jo~+b zv(Hc-iA?&BET^aBWA+X0DGE}W;{bSZm znjZ)PciH)~d#Jq!AZ2Q=e)9U|;z1w!JH3Uz@RIYx#e+;ONf0aFzt`=;5*tN>_J z4^MyIf%-&%wK|_c0siP7+2!H|JU&k3~d@@Ja0ew?p~^>h;j9LAa0J?dC3vnrD7vWY%nWo6yYWXbmn84 z>)%t^-)7%&S6o)2p7ffub^>d-$0 zr3Cs9<{G9B7#rX7>|23S_`;S6f73KxR(x8L$w~vJ-%W2O_dgDK`{K`&0#wDK54j~; z(hQ0OhdeGZ)p&u+RcmV(#&}%BDcjsM4Gx|nsRQAz-0z+oWmi*V^)BT?lO$YH ziQyB`p}(}5oOmkm=ydKt&5^L6$DgmPa*7eO(v;g0hT)0v$Jaz9%RaJKeM!-FJ==!b zIAa?x8P=i&Co5kBMu#sRoLeu{b}$@jn5FC=twa*3NZnggYd9y&;7Amz)PbpY3h&zWT4gd`vx@gr`PD01*lyXgp{moG5uy zX-GjkXX1;_1!5RpET5nz&L>wLZbZ3@sWu!gfD>XOPL%hb6T(%fC=;vr!fW)>5~&p$ zd)x4RLspobLj2ewZ+)vv?IJLMc=gDAglhj7rRiMHC?ApD*F(*15%I01wX#NY53r-y&7;;$*p z+!jo92=YA{QRJjs#S?Yil55-(QIZ^X`*Q`X=;Pb2P*&pi{-jEk;ij2##JB}0()=0Q znW+lT0@|i!e*=w%a;zX64@M)Hx+DuCtB-6ec<-X9tUcj}O@ygd2|NIh&D;ILup+iw z$Z=`)Aaa-roEmPS-nlkK}Q!2FQx2KFpIxWgG%ru53{I9tZ|f}2Gq zafe(pHPQ4xEPb>}g12Q5mx4k)q7&^2_9dFm2_K9N1z4>BXO^}e%+cB`b!K{8OzX{} zX1N+~-`?-yu-<1nW#~j*>cVefGCDch`!=0B#&}tZ#g4@2(dsyR{U+r@ih^0mMEsGUNZ|ChlFbd&XF?gD#5zN7bA*WatAu;}Y2ORpOuDvOcnVz`vh$$k-c;bt$-oonQ-J9>6q(51AA3?sWO0bv z-e5vTFmwCvm+T~|>~=(%W#75u7ik436ko`&<1;O_90`#X3u>K@PwjjYv&#em^D$>U zt?}vZni|dyd!3IB(wDWJP%GJ_rRz-a9~TA<#j{ieC)JHeEy?xB9u zx?b@USU0R_7t)-d zAd7o`3W|za3AaB^DMyOSYN_SNm3=y~0rq!&kkCu(s~8ENhzN*dAr(pUSx<+bn2zp> z!^e@|MyCB6&uAo_vuJ0-F~)I+q8P`*EXBbK&GpQQn^f3waGcB5Dw&+Gum^xr=LmM< z6rXx1fl^`y|IIZMLw5!XHPcI63#LE)P#V7fqWgnxxvTOt&x81nOjfo}h!#&>U!krw zbv5z`l#Z%y4Rs9D%EP#i1mu&vbqe1sl#MoGPYVorwo12hJ$R@qAN*T8Q0zDyOAXEp zJOpy7qsHTw`3Ln&qtem1kdtD#WQ)J|e z1Yil-{^!cDnSOxo9{B**5J15jzwTdcIJgS!@0%-4kM^=9GOBEH_j$~#y?n{iJTnMI zi?1my>rF$McT%8Khf@)|(tu=e@KQx3H><=G0^I42oEAvhoe9(6pO`@;xU_Ra?QQ3n zxCzW(!6?^*4Q8l*bMT{k&%Xj%n!J-V# zCdJ3ce>t5ceVt6@3CgiLXyzF|_?n#hU4C)2HRMs>)ha0s(KFGPCIu8EGBgCC5} zy5gg6S4gUB0}&!Dep4$%%2rw<)A{*sFCR%b`wETlwLiDj6)iWJFq=_P7dt~9AFE6e zmxhuM3sBBcu6+H`z0bhqTJvEhMyG$D|8B@&eC<(l&%`&YN1-jlOr>Hvd4dFJ3SueBhG=>I-Bx-S!t$PLj@SS@XS= z9vtR_hfa}JR;0HVVXkt*md|b~UKMsE>KyyH0A;=%UjHZpZgZ^ZV)Yvn8kDX(!!S8J zojJ*1{`~_Ow?G8a(wak3G7t}kzxnLho>ko89E~513FeZvz3V5vtU8et`@?IJ5J~qf zVL8B=hk0l9)>yGg%~-@6YLJ(gr}XN{O(gHUq@n3KHm2i!Y4@d@J3{#L6jX+PQurXO zhF4H<_AgmlrnMA#J{5X2&Lq5e;DUzR|%ZMK*5la1fBJZ3d6> zXf2NDuM9fLKFs{T+C=^l1X?7CG0_H%dzsR=2}wyw1wsxBhUNm*ZdU0Y>vXO_yq?Ce zUCn&n9f2_g+yIOeji&xF>($R_i}n9w)@$G)^0DhnSC%*a^!K^kA=6rul_vwFIiq&c z8};0PlSM3X?ah0{)R>@usMl)lF6B|r)V0w~rN=dzubyzqM#=trskdbmfj7!h$;1`4 z!Ua9Q*XMy&nf?kdeo8Y_=WLbR*U+CTrkCn-_SgQ$)YsGc(hk|rd!-7JC)FDuNXtWZ zb_%$U*zH0%4ew*{k+>pLCt{4XCSX76y!q7~R~Zna)-5N=0`m9HPaiy@7j?Ug`QC$A zbKjYk_SUBKg*N~V_o2e+0B3P{ik$~=h~vPVExIa)*+oSH9RHo|6v$%J)CMQ{J1ya) z0yy>e-oKn*A`&OrE?XN`*YFdej9sV1^5^~CGlgb55*C^eUT_OGqM}3=qU)}7bYbQPEKszhfiU@s|6wHR1LZNHdS_BKNb|@!%lfn;PAJ zLcn+Z0Ed8^v=$ifyKtd^Ou-ut*x%I8fz!T=47%7E&CxRMJA3K|kf5*8(E4!T_vu*x zvOrl~{N43M?w=2^^k1Y2;P}^*4&x5eJT-i&QU6*A(QNy(((UcMSU)fPI_tzC;*J5R zie$U|0e2I3HM+W!hPFRy?ehI24eeG7te(aI^J^}rn6{Bq!mkf_5yfrUIxWf$Q}`-U z-i^P4Dy5r5DbC5J)#2M#={|W+>o*?cGJKn`WM)xZF8e^FQ{HeS9t6lPpwImTe8c_z zUr3)^d?>@LeW<^KEeL63T*k*sGnqC`Pngod!1sRrS|EOQ9Bex1vF!X&@s*rG7ABRg zzq)(}naS^H!Q5~4;tJP`61J=Y9DY|+*2BzGRO;S@1K;XkEn~_dW=n$8KW(?4dh0#@ zA=+qjU=SzC6>;c~`_5Wh!$O?>p38&K8muyIWK?DeC)4x;p?l9qR80J&2Dn)Eu;2y=@4)&a)ErGnHNm1QNB_Yv zrG>t(yzdlka?tu|5j^uS#D!QT;bQD4thF?7zg@ko?l-}CShU>pU`CUaLXfd4rL zeo@!e_f!-~E~l>V_;o*g6|f|60Tk(L7z}&})C!6w#XBGU)t?+#Yt3rBz)O#dle>^1 zA`z`jvl>_|E>C&K1-G9Bpq^wM+@zhIC%srCPf70y9RqH(j}zr_uF$BLPgW04lk5Hi>;762DZ3ktRG$ zxx=uSiMuI97VX1+v~m-5^%&CRr+Cw=1Xi0)&obt~5QqmQ-A(h!0dCTVxY{*8vze!n zq}i!Q$H$xGVAJ7f-O{%jFVfomWZi_k4lpD*K!-oSI{vjx)S&E@6;=CP=Lxu=Cd%PQ z&G;)c=yqpy%SS^ETNpwEaJL@i@wIO$@X+d)7KS8@f6O>i8d-TNfnl_8{V;w!8M(RV z(-=)Fazmhm$VBlCB9U~*q@4hWjTya9q?U5P_seXPTie16GdgyV=^Wj5W^}~?c_0vB zZI5YS{ef)og?!hc^XiT50z6n=PQ9MXyjjHV`dw~)-0`DoGe(rfCvo;vN6y@Rmy=Mr zCUMN@btlQsxv63A($X=ngw+#8&o<-*@{%2YQaRqDR^zp5pJ!5x47`CvokW8!`CYfP zvuMkKAlwHxcdqRjHqOu1rh~*;yUQ2uy-(MjW|;d>vsK*9x#z$1%h(0N5Hvu1lp^Kc zCJt~#1kfn&y^WbQl$Q3-NQ6n%b_-ZY=?Hp57u`A|`Ug!U-1WwkMUq5O;pmE8kt(|T z8`ha01>zTOJOk;U3tO{p(%U|F6H*@cBj@Fce27xxT`mJ4>Cf473`Z~sM`itrIAz}U z##jia-+zR)bkUh%zY^(PK!V~t0P;Sny)T>ywh(a1tj4Ssy6=F@KuG;0) zrNxVxve0TzObETr+#9>#9E$&fleBt}!Ck$`Fo8>Bm;rd{MG~U`M~QAESp4ng5zMn5 zC?%@vxcWc4)ACr8imt|`P)H@N}u^qhyssCdzD zn(Ai!zU9o$xV|P#f)ViIxkJetiMLD=(?+^AOYtVYxme6i?RJm{j5KOGnKUK@)zTki z(Ph9`sP(@gk}=&vLfTDWZl~BqKp)GerQHhzQU9r2Y*@R#IOb$pHD-a20uh-6lDogh zLLM*!MslDL*`<&hZxeJsYuO9D8qBV`dPwNOxEcsbW|jS-egl+oQV6CK{{R8`1ZJ32 z8h&)L=0Gq4lna>KJzf>12WNzo2T*YUI{$eWhP2M&J6(M;+$1p0zz&V^V=e+dh$j6< zFqqMOvJ5yM=~Y$Y39w8G5C~WLH37VdpySiqUt!O5^bIr4cBiOJ-HLbG?(1l$l^0=i z>AVDDCnCdiOP6Phgm^>?J||gFF@f_v0?edU)OG>y)gxeuehfScAR92RsGGJzyPKsc zP4(5ON$zw7wvH)Rd;(_RXD_gTYej1>5EAx(I=W?Gz~{06o(&@NndU$LV<5%ZQdk6P zVOfWsdhP_0NEDO-_L!p=6_$O}g0O2Sx#$$!d>iW=DC8E;A@x1l{vzd2w?@sSB|HN? z?4%L4zVI}=T|HyMN`PbD;@~D(D(ft^*LcXaIc^ehxg2G#445l~<6qOcds5YFzKjNo z$Jw8p{F~fM%}qv^PH8@}ClAGnU@#@MJ;T5rVASvW3{2ro68c;M98c)8AW%1aK1dde zPhuZQO32E!knDIqdKOM$x;J~AS>{@ zEfMJqidT(PpU@YneH=FLUbBuQBZzP>RcsWrn;!X`Z9WboAznL)cdLHk+3sA-Irp*Q zy3>4Esybq!>nEu_@bL`Zs}F0bL0(ZNRJ0Q%8oSRs*NB7@l0=GG{~3VY;D!zLz6r<~l02w8 zu}#MKHY_}xin=`|3kX?_i(qcM&=+7Cd=RLa>JGMi2~&%W|nMVWMff z>bVsQ-lxGI;StvvVL5D}3wrZUR#CEe%L}oJ&inc6_BxWi$A91XdVr4)H%YY4BPz#2 z@_t(o(&&6)uXSKgQC%_u-G4B1Q|1*qvm3FJx^KsNBe_yfwmY88vqG`bjt|Yr%hR+k z2AeitZgDF`qgg2pKcy>Zee!Kb6JJ@Xcd&`K4XjDEQXgh;&`_>Pk%7P~3X$|d1)iLc zG?o}0$XBon(EH$mA5Cn{%P}fVhIhrS-y#L!IPk;0uU{|h1(Wt%B(RYHlx@X0Jxb`f zoAYj&U*0tH&U8g!a;4P}IBP?gvRtW`ivv<78f)#eXq?6D+u*R1sdDi{7exhFfMW>>iBfRq1qv=b4%IrfJ;-?t)W;O?a=;b3~ zd-ge1X@_``Gp^!a0KM#AXS`xQiNv{I{j(f4$r_#aN1leZQ2VgR_l)GT`I_|zrCD+! zf^`%gZ)3~Q1f_mAKCd8?TeHJSq$yA`(BQ7Q74QHCr=X%y^nU5&o+XJM7|I3|KH|fJ zbGg^zKyJfBz`VUGJhtOg%(>A$bb;>RTv26fW^u;V2o6kV2n_To5jiZg1CK9mw9KB0P{xTwLtz!5n~6@3kk}!R{*N&*2$t&)gB1WpkRQ zHQA^r^bUhLe{v{gZ=te@!3uPIOm!#E_j?5WSFiOFmJHu9$(4xb%c?w!LpJxtreeyWQEJj#_Gqx_LHl^G`6fA5|8uK3)y*GoG2d^+eMp$G zQ~m9-shP;)aOj8CuUPECA^_w!od5YzC9>hN1=_V9Bcvym5@Aa?M+&G~%PB z&nb<4-P{TI#?q{$af)|=tQ>RD{hTjCfE6O$7hMHoQK@KY?*;k#;%o!btMz+ecl}z| zZ*p>x=J}*o3O9= z6`@6`c>wA^^;TZ7>tio3D_6^MApJigC+_}nU?|`w7)raMC)x!(7}zQN>A*aeOZ6m1 zY-P-*@Xwtu12J}i`}rkZ1Z~b(9HWBOSpCx#=7n7U3NPetITs}vk+}0EM077}a*fF#1a>q!lnXzRyaP{Mwl9qZbauUp~Le1zY#_-i7@B;K9?z@*S}Sq7_vxl zwkN`I;haCyC?qxj#e=za%BMAf!LAOWL1tz)=X)K+QIpBpMbnGk3vP0Gqu&;w&1zQB zVRA}a!z~~{`D#1&W_bkeAjt)Hb#h8Q?QcvKv}A7FhlK^RCl2#XPJ5q^C~`3VpzCP= z^#VE!1nR|)B3F-U`-g_uB!s?Pktk?vx}@1uA4yCPQ{I0DX|NTBte!L{I_^15{*AN0>Lv`m@gQ+n745FXwG3Y3 z?6TJCR{!xVK+>rEG86-DNi9GBgn4H4;J0dgmX)>|n3>QXjI$|Y-`ZT|26Idm zVZB!9lIRUM)78@h5}34K{?4gQ;t(*&+!QrylOsS>S_zM!ubziCUlS10rp|dX93E!6 zWf3OWvw8w%r-BE(YJl;mc%oGnWAYJ4OXH_*I_-{xCR_fC+lBK4XeHKt7<4f=xh8p>{rEZTX^l-oF{XW@vy+dj6jTv3_E z_O_B4r7ex!iETw`^{?D3+@#HPBUueg9%$1SnS!P`)WjJU?B?a4hS<@0C^bS)i$W#@ z;RV_!At0had37Jv1726XFo#)*_zkAxNs1<`2m9>?T|yCyxxoL=pBX>x7!c8Cduu+= zAP(wmKNfL@cmbtMyW!@Sl%%O+0FXPXULZvdLHX4vIZFD!!=p6&U@vElmcI$rZyOnbvC3!MHqg{QJ#?z0l8@wQNfMXG!WAVbEKP+?=72v4B2sVd?MMWmP!QnE zgw-LhWfIgN7vG5Dngb+Jg{YfoxYgO#+glX56_sydI^U^UFEevHqTJYHlXy9GSgkh-(+*l=5ROc@CSK@Rg(bK2sPaHm?Mz{REhmkkPVI&JT_cM};c05Rt zhW2-0F!hUNsl)HzpE%%>JU`&Tj^=-vZuQ3sNq@9+J}6<@g2B~0hU(5kVXzVKoyY>> z{y@G}zdv5?`EaC+Jmwc%bzsSl8wLCz{5Xj@gA_`Ro0N!8uHm;7Gop@FMr*alf#b_+ z3hWQ|zJ3HRO_OE|rU_-doSLQ#;}xCgj%#1ij*pMexnBMx8mDzkkS$;-q$01NqhoWZ zu-KxY0cLvoNc$;Pr@Sb-jpDsTZ> zF*IlC(OpEO)|BYVE*g+Pwq!;9THhiR&na?o=8bAMQS16 z<|j3Y5!h*6nbjsu!dJrL@A9R!jlNXgpo+|al9a56I&KMb{c?NSiF2z;DYN49iSD7_ z;!}aRE{Qg3o9r34>@1ho-Wf#;O2Qe}t(M)gl8~&8pX$}74bHq?wANPo3B>$QrrVB{ z0YCkxC(oYDy?_6+Mcc)aApZFiH^vcF&eV|V5AD=qD?~$7{QUfYc6oPrxZj?oZ#d1j z{RpYH=|jskPK`rMpHTmVX@PU+;s>dL&eAvLcFRo6TF_$M(kJn&ykJG<&V=^{k0y)| zOzsuA!&iG~<|`g!&D#=R3&r3Wx0QUhJ4(?hF{Y{qwuKm>tB zMOgP4(=3Ow>L8{?X=2-hXOLfW-YYzD61>q=1&f>VvEckq2QBys4XiH&t@d_2w`DCf zAFQ}8)Wwo&^PW&zUINtS zASLGjFcWu+k^RGwyMjF@zP}C47w<%k?0P}b3ff4wLzjyk6?Qh@yR{h6TQVq{bDKZ1 z9s=TqZ!DCg2oV%<%fp~V>%4OxZ^afn71R$2l>Fo1Mc+u=3 zHDRF9ADn0Mk-PYK@a`mj^8);-BEHf)7;{0<5Z5Em1 zwRe1#73h#>hEe&XdrdhsAugDF*AWPL&d&1iB_UCVnwYsV0@K>FJ)mHNc#8(ovWUWK zJ|IQ%b;+Bt!t=wTEg?&XaC7!t8u)x?|V+%I6P_8|6Lyi-s3 zXy1!Z5v|ukR|qT%(!Gz4y`L%k&ny6ZszU(2BkhFYBxGNvUcCtF&O3P&HsvSS^c?Fc z!*{8})Yv*n#I?rDYj*}H1eEk_8SNy6u|EzLP48y1JX*rJ+ZkL8KkRw%pQ-=5cj_%4 z&arZc< zN-odg8p>h#vj2X&5R<$&p=Y9V7sXJY9|ym=RE`yFM>Vl!E7p^JKqmniQ5xQg4pUKZ zHehVAwSCgbCcYX9*z8^}t;1xEeXh=SDbv4wlM#6Mc}l`Rki`T2qVb6<- zRV3kShP6=Q(z3Vm0K8f@5H)Og2%I2#5QyUq!6XoPBov?z{F-9&znyjNU{5ZD5s+h4 zE1T!>S$2`I^w9M-&wn#|F#KKj%D)yAH>OgcZna z@yolHO{l-6#9Qx|p<~uJV~6+uX!vD$=~|SgXXM1tmQwL9hGTk?-%t!{Tw0jMTHjmk zD|cYQu6wtLr}hS-0fYpA;N&Vje4`IZRL&Vmn85T`_QIoqI*OLL!{`HO@ ziqz*xmx0WyY&;<0>OkdZ;mopfle#tFFQo7U#_~mc+yoTMG`4Z9XwEmA`=@k|Z@v;I zkdl=Ho;9+irMU7!Ao`7>+aKFD^fdDVq2*Q0WZIeZ?PK+)58<}2mJWNKhq`U|Q%kwp ztX`VEaMSovQ}Jk1yZxEDI%zje+$RrQkN%p{J^2gOmlBcIAA#6ke0*DcvNU5BeZ0PC z&|%K1y&CC;9F_yFA**`D`S(L@Ij4su*PSaH5{eqq6<;A@N7%j7*K&+q>Une&S3!xm`PLVbjO^JH zHqJg6El(uf1@~;Lda|xCkoVJv^R(4A59Asmdir$LJ)uYbkDQ$^;tHYw+gDu8G3iCg zD2=fNA^bMg?YX7DBE`Hj7PEII;kRwjWxHd&J1+Haucb#%k>grW9~tj6OzM}0SF;}p zL=QV+29CpF z8(~kSXD%rz8FM({)(ghJedh@yB=QdSxuXERWS*q-4B3Y2Rv+DxI{W;d*Q`G;8tT^u za;1G&RiK~(O3?^~quS|7_)LCbz5ZbNl*&l6_o^$lKJC>t6?Q%;5663NiRNX=4pitT zQYO)To~%pSVjtW7MW^*AZe{S`;w zXGr1Wm%%iI=G{j(6lrfs9R`s+BoK9bpNk*uHyJae9pxNIvOb+o&vd%rzs8@4|lhC($Ef4Z*lnLc_Q`aF5rD{B2h`876>{jU)>;o4({ zMB?PfPQ|B64rM=pT`wtSb)T5_aq0*eD~3H&;)Fm#(D|6ELpPIp-l0lE5gE4bfgjDAF{1DS(x$%bd6!)rA=bD9xERRT6x6p5!61Tk zRrC2ukqdE^2IX)LqbuSFXQc;2`^2IB?l13WopY-$qKH|$ykrQ*Rcn3ymYeQ%xz`YW z-Kz`Rfs?*lZeWPWfE zAJcFUPh9Ct?+Z~VLva&$6}oD!>TA-<<6-NhEYQPF04a%RxV74sz{uvRghxxVKJ*{< z+GmoJlF}emZw=UfTTz0mPUA{7Mb%KY@m9}qx2!qLPA~CYd$r#$f{+aDO_dz?dxALk zmIg$Gt!|#TzfOAnm^IdWzwCI~4t@UX=CK zfcF0WC!<*}UtXnG#Ep`U;#t+pJk>5Yv{CDM8O?{cG;cPRA zwFMuPk{9bnw|Y`S12zO_cS6KwR3nw{1L_W7r_rA zW-KT!GM>L`Fgk$YIUtj$Oa~=quVh^h0=ns87drbSai|5f-ypEKe{Z+zXM52`&~m@- zlz7%6Z3ds>F-|{oVKAC?_GtvWg39PAr7lLEdn#h{>>ZO|=wv(Tt_=G6g3whv2ERr7 z=;i?7HOyUak}B%@%V@A_pu9Vj{rA)<%>+jOb&y8`W*g+eMW8Rtz9js_$C`bptbw<| zeMBP$&$Ksv7gvzp5MVbdna`^is`lZd1$nX(`A znKD}h7#IXK@$LpDM)Gbrn}M zX58!)-&=O_z>KE!@|)3x{M))OtIkEhJ*7e@8tTJ*V>Vvrd9JABA^gq&V}0*=+VG+L zBMkFFx3Z%viTlJYJ7PbL^z1N`D&HFAv~Y;!6p1cTrKO8!)&;r@ z*~ddNyTNnY3#ppe%M(=MXP>7Q0}T$pR=yA!V-?A~*$<5dp*-!jbH-enpZ|cW5!erB z_!G}YViguH#4?t?dkJ$Ot(M%_Qut+ZbP2Loc0!+^^XtQ^5aOkFr768aXAcz&eEq9L z;<*z_4$^QM%e@WewYwz(tHe=;`&~okc9L)~^L1ZC#b#lC+NjE#N7N1edr_J0TTqW@ zO)k2H9av0m674$P6^GP+E?2XoUB$1Q(l(OQVoQqE7rbQh&{DI_?F~!LBi|m0`sVPi zYpDAk06He{{Q$m+3=z~f^UkUaVoD^1AC>6rp8slOXLXpVQ47`*_1Z7)4QygC9Qf;P z>$Cpr_!h0@Mbdw%F*_qd<=VTdE%(>4MR_hk@>Vl-VVQWpaVB<<=brg&#pxHDfxmf* zTV}_|sw#{KG-DM*dcQDdgJ*zCXsEHxcFhXEa52Uh>h(UbrfT<0b!}}k`Mo>0W?`o$ z)_GiW%2+&59?aCuhOIiTlDe?aaQH|Ni9dt?6bVvDV(Rhvm=uJi;3c{5zAIi}p3if3 z<8wZHb&S0p=F$QQ>%HO|MMu?K^#46;$Up>Fr)JGiQ;~Q`Dq|?XRIT2Foj@e-x8SL7 zf-Bp3|K5%rglqfs5H~{OO_Ulsc5XU$(x;9pd$|tQrv5^fPkqk2)t;j6ML};RBs{87 z`-YJOg2&1fV`~F{b(0aOrPkN`$b$oB@R-ii`DX^R+oGPBiO=7jOe|@NP_a)*ph}1x zQbm+!Ng8f7W}S4J*vSMO7ONPlq3Oa?CC4}O4UIK4zjr2D30pQ~_@VsK*4TX2gl8ho zKn;ZG$HV2$nL7$X<-d9o zT>D%T1SKPX3qAVst4`$H01a z@1*#*3J2A>h_0f-;k$iV1A)yKvu! zSVF(`s!1leIncG~%tN?*D%Yc98y@U=;CS$Eu)6r4*GUz%cf};k*Rp+bZ($96_0wnb zlhJRjMBSN5yG0|(9?QmUdt@G!=>K5ttK*_df2YUyqaKpLc5y1QIpzgeH>zHfcP_kQ2s_ZR%wU9M}->pW+UIp&xduOY4F zk*dkYie(|0%iL|N;TBHq-F{p(nFNLzZ*x4YyC2xO@;!g+HiRWTx4jmlFZVAs?|P2C zzUuFAN32m+Bei@RUA-_PIH4wUU*v98ME(f176duSiiD^7 zBfDXl7v6$5m@>^0AquU8O0?26T_MV+i`yi0JnN{uC!6KV^M#@!3N+l58$_Q*XN3q1 zbXGi)>^ZhX#oO$&Hzx}&KldwLS}PTAdXB*TuipQY)EV35Iyc_dEBnq!0n4o=>vJ4Z zk)hxAMd!!dy;I86l50kud_mOjHY_9c3f>D+bC&8V>ZdOYH8^SyLL+ zPLeMyhaDz$>q(tF>l0kg7+9k?-iT>Kwh#$;?pqM$%aNWs2Y!R6+;L*3XI!s0I zd|~01(+&$K+g|7_39aCJ#>neYQGMHG_o`ZRG5W$~wND41ao32JJkE7+s#fEusXy$B z=4E(lZ%9wzh^LcbeTh`;J}xi5!9?^K1jSy<5!yn1d@`R^9ix5w$B1J%k=4#RGjHzb zJHIJX*{JKECK>276_3!W{-lM=%X+$ZYP*yP?n(y1+UC!Q{~KR%=8g|SF8j!b9I|Y* z-a@<(F0W8pXR^EErC1@0o9AQS>D8qUxy|J23cD-5YMOsy}6g zcORz`q)*SH4)Pbh`%&UEqC$D@lFKqtqS4#ktC!7P6npcTU$UfS_&w5%6t+L6w>EDm zpp?p~~J%(X|Zy_+Wn=dLm8-P|`x3>I~1bH~kYR^dodc}%R4rl#y} z(iDB~-C6VIckhQ*EUa!HH)*iQnp?Gu+43*c6zaKNVm0JgEL*i+P%ydBFeH2d{i*xz zhb^yxtxwa!9Q!E@1>rQAN$GZ9Qu_-_cNP0tr=AtD_4eB&E^F9#hu^EZ;qD*C<(<)u z%PT-ydD-B08A)cre$jYNcXHLvm-SMQX@%j|@jmscWa6&KtSBqn(wW@!?tKO6x&xUl zZ=TQqifRMhR;a2r@OG4OS$TJRz3q)ZH`BO;(>CK zaxC9_R+ONhvv!$uI53BtxPsokF!jN{*x=gZ?SP=Us&%mh6IK_@5|8e<=$Kd6&8*Pt zi{_J#)B~5cIA&h*#1tjWJ9*TZH#1dH8d!>K37O7!X9{x^lRpzpt(j`Iut>1>htsu9 zgQgAX+3erDz54OtU0s~d-4>ai^sV#L1n6CgJ=e}|n)L1~-;!|UR%{u>Ce%6lN*ps4 zzDSR}Tddhf=MRMy3Z-mv)Fv|1cZ_`)=rJub%i7*gaXXcDL2i=7WM-$3%@uiVtBN3J zX2H{R{>j#KhwrnB(kB%nV4QP$&^pl}W9qqmRgEHgG4U@|YpNIZGS{>E$LOpxbMH9{ zR+Mk=7pm+s(9nAQ)RV%uT`T0Nvo0uKYulF8W%r|AA07E{ zBzukTsn7t&+lnPi*Yu5hl!6P}f?LM)7TZf&DNi$^))Na;wuB`I@X$pTBG#|A-7`8S zV`gl^ANH7PvtC|lfFS-1w82SzyRIo2S$^PdKrgvjiatOuZ^BTN`IN;~w^QO?tl zjvXIbA+sVF`>c()|G6pQL$eC|I2WR`;8xH3LKAPY!Uyj*vnlQh+=R#_s?zbTRX;AT zD93?bpnLvIX6DeD+i$KB&?(5sw0Co}mz{Am{$X?!$#u)R%WNBPd1E3JJ1d?#B9hfw zMoNbG@Ob?l&|pHY4@l$j?rvtQ8sS8;(R=GiQHCR$n)>pP)J$LyULTBFD{3{*quZ=T z^BFRp>U&B)XVXC>&+S$<3X$sFiyWmPM~Xf)S{5LxUT7plXu(V8Qf4!_tScq8W5oLr z&x8iH*5?cxCHpJa`kxA0Ts>^iUuZ@>%T3Tk%}GjB?XmIMzw}@nLK8IU_RQ8h;_65# zWp{={vH3>41}#qPe}-Bv^{sA%<;KPfJ&0!kPxEpy`#jsA+|Hr>(Z!GEf?A{^ zVj}cJwY_0CxReZV7-L4XXsk*2hl4qHt_)CI^VhW$qp^;k{1V=&uAZhQqfKKyPug>H z{0~UsOuI;G3{Zkn33dxP2--p0xE|bLv67g;r!K* z!YRx3y6@AWnLYis6qVh>FfpT#9l5xJck|&%!O$??!f}*#N_>ms7y-2f%`BShW11rj zP?M%4oIURw9ls=M=&`J~{CK&M07` zO-XcVxU=5zU~R<+?2Tt+;PrDIdC_@`##gIIks^`>Tu15G^3ZK>nijS#-L||>_3a04 z_#TpxA@`E$Mm*aq55Y`K7w%1C#MYNvv+`V5#G0~!ceV|yV|Tes3`sI>o(x78E#$vz@VCj@K%{`ri_CMG>R zUd;4_=;JBr7Ce#+qnS6cNBIJ`+{0BbY`Nn^J*yCLY~NV;V$ea?ka|ZsRg;tsrCJqI znB(?%vz29JdXY)*LE8r*N)^&cd_R(VE(waH6KWs(3WkV2GpD$XSQMS#jIZxl_{zCS zMnQ3*pui`Hz~VwKX7MFA;|F*Bl&@mSf%5__`jYtA9XxqHo7%pR_~ZAH>*xcEs;u0R z`QDX6c_N3-Jhs7fWKwicLFUMuIWoO_DKXP?Id55J3qftMh_?3<4~vpgu2|wnt_`Pb zB_`U`&AVgLhueAD6^hnf=TcMVWG%YV95=o&oxIz^Z=shZQs%X=?SJ?4vv&1N?P&tK zMK|fRVcEI}h0U!_u?SkR1$C5g?Cicr{=W42MfDBYrqqRd^C9LhI#{OE7V>tZyVp4G z7FdsYlH`mKB~R_ew{_oz9T+WjRo8i}u+imr2oOeo8!?jYZA+m=rXU1!*tDN+>2m73 zuq^fsw9fO{`}@6HH3tXUnOc|Wx^nN`LW(#oywBVh#!U8dXa0C#fobo&Gh+5vMUKe zMKruesw0&SwA`ysd}Y`ptah2Mi(Rz*^y3Twm_>*CA)Yx)PHcOc_NbQ^0U9|!rzcr+ zU5u%Inr&B!3n#KkuH>9TS{3v6w90y7n}adx-93W@#@YfS>&~;Hq*Kaj7|~}Nf=|AC zOj)8e+c5O~PEX7&=jba9(+3(bKhNG7K6;oGf;TZ<3V6~{L?TV@qWg!9`K_Vqh)#97~K@Q^`^ z==PxB2FKbwy?~WYwb(b`Kny|6=2+HPtm}yl;;M2|SBCHUu1-UJf+*7E@1vfk8aHb4 zb)0=sE&*Gko+oF>=NVCD63Xk@2)XsC-Sk1S;;kJTtsEoCYK8GJ*AotihpmPl3ftb} zeXT49q8l2IJ*$KUqFou*JnK;p{47hBa2>&$c?}a-1^qTGfK4G=Sk1>-y%K0|Ww7e~ zw3opFN!xR{Cs3EDqkr=Usq%$F$63eu4N8QjZnK71--+vlv4!}uC5?{ro=&dCRjo3y zo$WS#maY9MON%MbnF>;Pwi@_2C*4i(-5`!~c)Up_9)T;_?C(vAr)wl?+)}7_AUc75 zp-V*2XE#JJ2fKH_oM`a$_5T_Z{^Nz0mcDln8OZXJN%1T z4P`{eX|0t{jC$TV(JH$-!bVhm0>dw-)g>lyVFMHyDd3YmQhE(2K@q`POHplk#F%JBY~q5%=nnk6axndx zc?kz6GSsD;NgRT@5N$q_1^k_DUZ+1S#AXJ|zatA*AAFuac|IPoW z8<9TAYfv3x6RtSX{h$8@89O0vC8Ei5dq{&kIO6V&UoQ7eZ*(>#AsBsk6!E{f zL*McvWIhc~sn*Z_vP6;+aI?n+2^Vnx{`#Lt^Wi~UghtOpE2B03M2?4hPyYI031eK$ zGG<>qF2@^l5W-ch^Sg)lFMCje?>OvEIR)lG-=ANB!;X+!6|bXZ{Pj{lzvo}C5&-+0 zqW?k8FMpQ^p@9ECp+G3|I~4lMM-aFVm?aR&FJAW@`{m*<^x-h>QX0Gd{hjhi13n^T z!hP|gD*6?VJ_-qHqi>tBxg$ScP)Uy9NcD+Mibg}mU!K*^@A=mks`=nE6J*DIgr*8= ze=!a=vG5A*G)48)@t=|nzwD@g+eV|sgs@rODBil&SqW&uVxZi0ecVZx%GctzF)S{#|H?U$k@&s2v%;Ch7Op$YwP{8U3}l3g*AB}OSpyi^Ob*j&%eEJR2z0qEP(;4VoR$C z%Da1@;mGz}dKT5zCVAeX=-$c)tJ(lUluDAU)!xo3pSHD(wz6#ry==ehxXT~=!`Bpc z%ni;uyWcO(&##g#igifaX+;|U^gJxe@bzV`%+p@{`x;KP=O0 zY4DKeI#L4T{=Q@L#XZ4pixYWyo}b-B1yV0&Wlm;g$VMupcA;e|axuEAfa^Uqk&$$G z#DG;&F0{N9tsrrH{v3DD_2YN% zIsdUme9v;i4yuno?R4zlHp(CG`L`F2-Z?Xekh^*FVHgLC>+D-iR-XCi#=~!^d}e_x zjS+E1S@*zby+QqhHR|n-TRgMH!xiop?4R$mbNdF4)A=-{m+ev)6vBg%Y!2VQ`iC`q zk_M~%*6n^T&mRl-$1DH!M#$Jrec$8qLQ4W0m^@`)VA10QV|0Q|88kBPj6r$y^p^;p zB}>D&aIEq5$dV*bdQLQjqTB0 zX=cbQ%Q(|}PE>Sge{a1N1!^vo;fIH%#8FbE28wi1>*VG17_*Lqh;d>^QCcyNUU=*)US$aUNX9G<;`TKj~UA{fG zI@sG);Aq}k_Qu#_``4qSYGpebE_`@MY)>k-^V&K}+MW5NE%Zh#J9Y8CV5%ikT!0yT zj!?j?gIU0B!<0_p)-9qES;93P_r(G?xx(@Q{f8uUbM)SOwveMpebG3{f1wB=XSH;o zz~H$NLc?p|6C-H*HZ1L?-4z%%>SM)!`LcTJK#;)j%&^CL^E)R=Tp3Oclmm?XsYI_e z^57*)*_R*me9+MMoHQ;Q{~Xk5@FYVg?b48AkM0tTYbTziTy$iri4a*XSIr7)b0G%0~b72QQd2fl|1L++T2Q&3Ro!uKiAdW_GN;l9?uHUyL3to}1Z}wFxd+)t*hPa`<6sEHt4OwLYMa%&gUDu39sP^%AbF)AxWCMk<6%Ru_ zE>3P-GVA!5sZ}8Rd=aLxZOI33xh(F*xy_|&T{Z<*RO$GA`xvcY8@AW^!MpsCSFQ7o zOg*(wmFY;Q(k0_3x+XSKWSu~B!T6CojBX01AYmlH7IIfwrK=9f4V zjQ{p%b^WR&x!+^s_}bhj5r}7M!XcxN9_S^mJy8?MX~89e`NUs2IQaE&NkGEa_2e8S z=k2fU;`E1MrE%0f?sDGma;@h*&c{2zp@gDJPVHtYUFF=MMwdM&3rHYf~ zW6bZxXj_#?a;8fg+@0-65*F?74Bf3IFgWX2glt$HwD~}c0(Q#nnM$fusVP8aq2bYW zXILKdon&yfr#nLC#9?&0BOxIn3>hf*rfzo3^F%voRJb|nHp5(;Zxeg6NsN3tl^!Lx zqs`jiKET|ck^0jxKMDbxee!DV>A%0Ck3@Xm?rdyl{23dCXvgUX%{)kBk%4TT|Gv~E0-WPlnGgheK?g%Sgp(L!k$t` z3%2m9iM08E1!ZKPte zTU(1u>holhxq?+skWLEu`%tXWa3mGq%idb|`x8zotpG1_bU2dhFO%^<{U*_VqFw`W zlf(=fI(<)|(_8E>xcoI6N|tFRjbj6Zf=x8k@Oa1Mn4hh!)-jZU!ysrf@(qNf4Y}J3 zvKs&^L|j%3s!NTlyMOq(;tr5A__$(618svH5J{b3yc#K8TDDv{fUWs5(Ji)lV=+*; zsQeV$dC_WPrXAKu#dm5lLcjYS)b@>Kyba2{(anZFJAYEhE-@(heE~wQIO_T2aH0$a z+tt^=s6Wt=yo3|EN1GK_MK9`R>T=E{WovO@8m#oUL|m1`o@W_MMe{dt<$_LM?r6K+ zmwRt0+wj96o%7(Bii(P#Kx5h7` z_ZwZOeQJ~tX;7TSqXN?RcvTz z=wHT!g1~RkzSR-tR&OVW8e?F;&w0VDhZmi-LFbP+V~~;*J`Js_Q%<72UNY~^U}TO$ zKfsb+Q+=9d$94E*N!e0qV^Q#2S9%%r5i%uX70jN9c})N3QT6ozTx!b=$U~-0TbM98 zB{_L&pg=Hd)WxM?H)K(kZG>{|yQf=gyeKyl(+6iQ4)wGXYwk(b4`b;ucf*wry5#+* zx!xPPJ_=B4erW}HYsRV`sWPOilCNja0kmh(h2fy@bSWGEW&mV+jw}rEjMnu%nVd3V zRs8{F7pw?v6nN@%tpf8Kiq^!`E;}n9NaNJVL)ec3Lym zBD@B@j~kuXUN=MX^Ud|c0@lOjKD*b6r5$4lh^PXhPdGu`V>C%${^lQ+(5A;9<0bPc z_R~{pkrH}8fAe-df!u?vssk;~PnNx-59*C$)yPA?h*h|4hF%r^YvE2}7Y+sd%6B?h z)1;%H4>Nd>-JSeaP&z&~$?z2_lO93?LCtt2o{9|>faD{)uUuDZ4iB}xx$gO4%nemC zb$UPEsB^k0>RlHnvX~cm@dt03`2TWNzxnNT;?a-i5llV@jFE52z4{VtC0ZAQFY!E5 z=4el!$hGgWqN}pY)F??d!^^^zi#m~|_4ta+oze^E&h_6uzf3$YaZK<0BgV1768q_! z<)4*&1EJwzhpt1rZc_b7~RPxr0p{Op7Ms!*;h+%oEW1Ka$dm#UpL9h^~q&J*hrn{ zyPE+oHVX)e_kel8Re*M%$ze};sZb#)=WnqmJIr?Q({TNHNF|=(%eo=%gDFFSt>xzA zyd^n#aT;1@U0$GL`esxRJw7?f;PW_HMFymqV9CGJT`US?BK3ca>8> z0uA>w`v2vsUP3TEvZL_0e?J+3vsVZ&7a?G;s%LZ}x6`dN?&Q>}zgMa;@xFq~tD)-{ zP6GyR=>x=@x?!yH9_YKGYbU-v7yDkXj?(E%N=oW8MNZCEDvIqUZed`{qQJxAbgo}i zf)hWFDr>3O9(Knm;}DpVIl>|;s+*w3MX8q9*t$y3iC`)OV{R`MOlxbWm-y|e<8FzS zC0)0ylG$jruN&Q$;;hQ=UpD7^T3I{)qFO#mzfL@C5brhzv%&IO51EQV48H^o&5xX{ z^I@|oFW2+jRL6qlp~v9Ogj#WuMiI|4q&aHq@tA8J$(yR+Ztz$sdFu%X@H=6AbrUtRv;&8J@clTpAH2ywypnjy zaZ5P4T8?!^?F;lJeG4#LvqyQk5{<$}4c2yED4G%3J-5B*OkZ8MW5V_RG70PivUZ4@ z9D3M*rn2?x&E9-7Re`&ok5Q*DA1fSou^#W^R6|TDdVddd2OIt&{#9O!aAR}SMK%Lr zoJa)8q2C<&pB{>DF*OiW$8dR}vqt-hzfKT2cZe))jDU4F2gil;UE+yhF}22em=@d< z-YRZU4NQ}Yd3XFPcP__46O-rEW*;|j2^r8HMu zvcr5r9aOrel4GpwFo1O(cfgw1Q|r0B`56|GiTH-n`kWH5ip^`qthu@YHKlNkzQYq7 z%xOXKR~wLi9egYKbg;j`Lf6hNH%zJ6L+S-)5AV|2DJ_l|S-`QIK4u34^Yj%}{s>3(+X z>Gir-V`RR8N@OQ(BHCsY?L}`xmjT3>-fvj z8#Zijf}kUodX*}HV%XT83&C;~zUW8o%EmivBkdDqt=Jxjz9cj}$dxtn`qo<}I45^W z?j*@l5=YmsK>_aL`Ju9H<@E0ZBL`CxHALjsLYJAGbg|+3isY2%Qpt3zn#|_%L|G?z zrFkoeSKb9TOobty(iY(>pZ8(uOuL;qHz7=(VuKS2-&HjWCrZCosU|LC;F|K951t4~ z3{NPylkrOQQfDB=&T;~N#JgLK@{(A7Y5CB_k|=4b+ivK^qRRnHXl4PzK8i4Z z4R%GHS26Vytd}va6QAQ?_OI!Y@tit(BE9oHV|Pje`(Nzbs-A&j;7#@6keG^zLmWcX z9XvSk(9w0Iq1o<0_fnk&P9!!KPj5bU>cYnc3ja*l-f`%js)MASsGvOleh6*U?NobX zh3p4E2hkuM-S9?;1qMg4J|kQ4;#RX9>0dZV4R@8whp^IDeDG?5`%=jm>+B9O4ZrE9 z0*MzPJBA61UG2eTt<`$@R z9YVYUbMEbH6PZh&(G_EBynZ-wos^?qC~Vn6#Cd5$|7#CVLeC`H*PCr@?G|^*N11Ta zdFGX~U8Wh=9zBD&1pkI#*`C|(G6s5}r5bvrKcXn-;(PHr*n7HaFNY(1hsR`piUYt> z=ODBL5tg|oYlqqsAw1f!ttB)C2V2X3cMXA<^@F(cMyMmY>1x$ZhV#A^bF~n7xv8ax!lFL&%7NY{f<=EA2c{JjdUf3S?HinrQS5JNeAEm zz|-_PsDwqtwElF#zcqDd$bIh)(VS=ywv0ET@zKmT3Zox?`M|wkNWZ^~aI!I>dv4`3 z*RZO0nbZ5s52_{^J>7aO!b$O4P8JhG)nBu7w_grlEW2Ew`9z14@p#FstkqQLsQ;kH z-ME1JB=lF_3mj@_)_l;_Kx|GP8xrF_L0D*aSL;&TU?l5&s%}|f7;o?ut`c@C(P(*Sy=_AvEb)`KDtW zYVU0_n)&|9YM)`iWx0%C>e7z)`fe5;_PRn%H)Q!Vxd*iDz}I1RIX>7BgaIzR+vmEG z(c9Z0LbHis4uwF^TAaM*M+F;cgNwuP$gTp*n?t)KObLsN>xIo5(0HeWTesA7bgY($ z$6>jAJy`zek?P)h7;)09>$N+nbyfKqEfxO@r2sXG)n$6uiQ{ZtEJ1d~_4Mtd)IK?~d>8Vr zs9kN*ggO{U%~je<@L;8zXp}vHXs9nNz0TbqHFCc88i#GP*cFxq+WES^t{9 zgpdW2VF*ofJl^Bkyua|fA9EzG95UETzZdW>f@brBBe?;V4TP~gaX>J~9uiLsS4ayx z2ILAlN%-4DLs-EGMv^1z5^_$oUg8=l1VEb!P{e@CK>q#(w_5RM@x-&fPxUI?cDpHQ z&xCwohTtvNx>RlM#oP-!OY&$8FfksT%x&C;rwB)+*(j-!zTHjK^{OxyIY9H&Fc7*) ztDnFqq$zqqFe*HU1%b;I+ws=9n6+Kv>L$o5Y%Y)JrytZGVs>FtSID4QuztxWSE)R8_Xj+Oy+ee&2uKAL&85923sCh( zkDJG~oFm@~G3%HtELYpekx(^+z(2YfC<{l-wFk))-y^nt9q1&}hl>x+9 zOcuwYRy_&GZu5a^?NG0{WpB36(ep3}u;=JW@0||}I_Bo)_00@o9(U4xEeDI0Qxu~v ze1fE(0$TiF=Wb@`S-jjOEG85l);mk+BmExBB1jP!(7VkrZueVc&8F4TJx8*s(GX=x zZ|QS1e@#&M}1C5DlO3qF_|_Ch0_dvu*=nF-G}?7nEJ>Ti3>Q#pgptkW^<*_Gq+9`ppM z35OoNexM7y0!$=`4W8>vc^;;8{O{6|WVn!KB)r2#X@DzujdXAE0guDAitb@z*^B() z?PKTGD~|G{-n%txGi7MK3$S~uKIHtO*>H84?Q|{4aG29}#yUsc-mVr$wTnvm&uC1- zkmzMTqG_r*rojBcV0pre7q2PB{F>Pm;}^Vk#tzfzLPFwsgA+h0djj*HGTxxlzrvBM7B_b zbTO98!`5V=ma#!RL__Y?rS>$B!Zn!DJZM98%S3N@5MqJS5fPKu9BXh+Mwws}g;sfJRT%a`jor0zF}8=bf^#xAjHPJ~Orv_jvoJ(ahgd+&X~;(Gy2zstY`CX~VObkFe& z6Cio8X&HrAnYS~ewew9w0E>?36j=>9P+@!mxR{X4I4|HEUiCjzl5@9iZZ0t`P>u0% z{?mV~*Vp&TOhwQ>ITMj*_~8)po=0M1WBHp>2tTp;J*=x1c8}oJja4&0eqBhwZV>O# zu{JZH1Y-$5L6dmbTKPwY zFOOuaErrZobNHS6`!j>#BXJcgbCXoJatg5m*WCX_)g&oqFRVvFE9&(J!Y(ZkF=(hG zDO5SkXqJ+UT(ijKf+mK9Z#|!@GIN);uoiOd$aDY(`|EA1=(oR0C621RW+pJ0D2oqJ zWDW?8jRl%_JoY)jZHS|R=95IfCkFWhlUL8V7 zDXz1O5$9BsXLf+_QjEa1By`*Xp2P7?THOtD1R=GL>-X7|I5oi#1-~ogGmjIWCc*AZ z2niWW^b2+%4~T*!p0xmz=CFYMBYL8k`rXLO7Oz?u)qVO4k@FKex7gIR65m2e*^}G* zscH>q6g@X$edgWsQt1Ax9I;8-G;^einy`EjI!XxN)S732G-Z}wn?+W|6smkpwkqi$ zOF$ea5}QE>$;<4Qz4ZRxetY|U^ay5YLVPyfb4!zrQ$`N>nSixIyRBNNbNq! zVi%HCK6-+?a>q#2o1Fhe+tp$#a6AgQc-{Mu0xP*){bH9{$#&RvdKZ_9+~dWlq>TXR z4V^pX1!iaBMcqsFy>>r=Wo^8S?El&v$@k%b+sSKIR|&MeLA%73;PK6>eD!8rCS-d~ zpU<%g4A#n2hVJ4UB3Eoex#~u>lV9AtxQM56&Rh|M@cwzVUZRPa|@SK{h=u|_W$wm0VqP1^rvW}@yo zr0(gzlF|t$+Aj~5s1D@kUqYs|Xr(T0unh0WyO+l(Z5g`?#3nMkQR+miiDaxhnycsy z4C~HWa0<}Nm>?n5M)Fgt4+|hqyz&{^vlf`7?sj@N)B@GngA09mj;n|1UCt<`p8`Zn zBjS|7y$=4qN9JC{U@1hI`ssP~SIC)N7INx5^1urUo_SR9OC_B1GL>z~%P48yMP{STY6vEe|x4zBfTk25G3gi`O2bC`|~7&s}Ouh`qh zKnLPZN3`{=?}s6YRk`zxh)&e#;}QKkGBA@nc+n@f{@n($dH zG$N|B1^WU-q!Tccw&W@yX?!X<$&hlaoJ^ETBbHgYQL9YJp=NW@q{RU^p*Gjb{Vi?h z-N^_GZ`gYUMlaL@!b4yTc8@``9|4gAy(=L}we%g6wTTAdeSlH+cEoqKNBv1ly#Xuo zzeh7JGhny{G=xx45Hssle_<`}TW%xwx_+$J-wOv{D*Pb`Q)X!!q3S+tYNPK@*QTP^&RU4{(KoobSSR(Di#(aIK?Fu=1<5IQd z7iR(;$yZ*?u^{{NZP&676Z-u~{x4d4+d~}G^;$Bc+&BjC`v)vDN+ay>-s)B%255fa z)Znvmu?ax2mV#7oHoJU>hoKRO80~B4IW^o!i^;r&T9a-?yprjEKvZ4-5k7sjIkC!i z{IlCJwm64SJyMuk(m8Je@{bFecxvQ{xe95mvPm(!>(le>ntF1~>`at_V&7+&L`nIp z^1&fv=A~OA)Tly7pQyDSXCs`d-(=U-X}Pq0}VJTVGZ zIUDz_1>5aG`{ylnzl25qoeUzgz`^Csp}Ob!i^q|mJ^Jz`Ac(uC_$?#j-#|0_+9A6} zuDUDQr%s*HO1%d|2!xlxu1<3okK%%+am{CrkNlOioZJQhvGM&>d?v$Cn;{66zF~9Q zBgUx{s{riL5B=Q%CQbl7yVwf2Qm!H;^ZbalM03`phDJ8lhyd)wkdLVa{sT$G&O zfZ|UfHZ$yXJ8VG)tY(rXDHF4nLsAWr7m*(ZYB3gcF_mp$ixO5qhD7Lq;Zoo@s>#;l z7vQ{Lc>01~8ezjOF=~&aOB*cy7X+U6^L#rxdBCs@n`d=x5cdHAVP%at10ARG^qHmC zK@g?=;pPSIXvDMg+uK!`A#57{y6A=Taj^oa=1dqF=YF%468K&!XxBewbpMgy{S%)X zfmoHb`)$TAN>#E)*L_3DeL`ONsND&9auUl>)aXC?5GRZ|N<;1yLe^A>92f+aaR$(0 zN|!<6_ot2p=3RE+MYFJJk=wpGt8cUjiO*~1-e8k?@CtUogJ}7>AwY##kwCw={ghl! zzFFtHsqimM(C5>R{H!LRO6AUb0r)z`BbnbGH#1X;CaygVpi3l|IbUH+bAUsYdh#p| z4Pnq7pKI5c$lXFXctH}7JG531LR)1$MJ5Vv(wTxy!2#58_MnD8!Y8$(tkNZwmLtt} z^`(-!C-aTskk(;v8O6z@I>B3GErEJRV_mMC#X`f?sB722vV^sd;6NN< z8b!BKP=)Dv%>htXZU{|u#Q zMfFC+3m2qHJwc7lVjT@(rb&4*`QJBY-+h2QSl27+pG_RQ5H1S~LRHB`tNX)?c*x&FoLp_wHF@CR-MT~P-w04F_5|Oix8H~vS@!R`LVI# znNbP!rmY~smbTTrypnmQHY({`(84>NBJ!8!z1fCu^oouzvF80P7c0R>0cou!1yifQ z>j+i>y5yferId@6&?l^8z=xYj68Dv=?H2EE4LolRKGAXeI)TAavrfxHKU?rW7WhB> z?Mw?+G_p(B)VQQQ83CAK-e^m0j7chA={eK_L0`^%j8-8CIYy(rb3Z?rKTq7h-OlSs(D$Fa&vvQk10y0V zhNSbScd++iML?K6FdaQh(H5w7Vts6G9%2LTy*Ty>E^?o9#y0$ce?jiw{dR&0Z0V;N zV}lDC@;JKl)qQa=CsD5Do)CLk0nUOGU z!vXn=QStr8gk6W$doZplPW1gKHdzPR*7HB^YuKSv-l{2*ue1w5aw#Bisx|s-p})5t z2wxXU2(YqDxIcP9656+x{pZg;k_PN`Lyj-*94BXEA083tYVMXUy)C^Uq$gxGEBl3y zy34-C>!U$KJLfr*I; zA3Q;anHMBkdS!Y8pE%2(a5vNRd>wNus3?RJEgTyjo`eKiq7X~wIe|jAAA|y3|9`$A zMV(2J;2{HMW2Tz8fPer&v5R%iJ<#^nP{6PjUn5n8MF6HNj+b5J8~hGAvw0}TS%Rji z3)mYtiHcJH>v@9o{v-k$2KF_#0rYYj zvTqfwG_xCOaO}u4QN-#uMqJ$f`u0X}99j8;Gk)bQ|I?EE`M0B3335#_)tuHiA0jL~ zd=fjdocNltu`z9@#m7g-m%h(uiBEYnjSj9Jt^S&+-P2IOUK1|)w7gCI{W_oXl1>lM zpK;7@qF^H3;U+5X8FDL+>e`<)&Nr~=!d#f@*P6M%?)l$;^SuU-m9r1WVlm=VN+kWh2PRm`Z$ms5lLQQ}3 ze%VQqSq0%)W+ce2QjvQ4So$S#tq$Ass=cER?Kq!VR0?{-ViG!GLBfw2Iwc+Qpd`f- z09M20uE7Yoi7%`4K0nMmL?8JbPj#8>HlRwi>QE%bA8zCkcJVHmpZEXSp!{;Q|Luhb zEU+9$%?M3jf@x8_bu&*ck>*hmq6y?;qgWA`XgRjP1xWT1U?D^o#$;DmL0%zAQ%qR) z%}AJW7{r?jL^zQ)7oPp8xc$FAb$Z>T3!ebS=|JGF3sOBMEjNg}AbN5{0bE9b800ut z*nk{)a>x>By*r%1$M?s(PDS;zva*_^m+Hh#wX;wfsYwdWU!YXyt$=6amZ)&KqvAPa zr_=I!Kg7d5StIWkGc~q50NUmDE5z{24`5TM?qANOn9|6wn=TJmpw!cEw_Fo}EIVfK zlu7KHMyd6)UB*y7;qf#%C8aFE`=AfYDO|SfRjO;e(y`l`!nCL7*K;?_uMWc9pDQ1P zQuQcg*cuxg<wP;?gdKrY};ty?oPs74Ah?t+n3sTs@)B<@g3$3w`ezBRDl$fC?XG zVPj*kj~ToF{vUNb@51J5Q4LD#pls=Jock)nMocIC6(IKB`#!&+dk>{?dD{h-f#=wV zV_^j<5d~aLJ1Y=DI(!x5!~J7hurFcl4f@p7&cAQ&AMf$qIgyPP`)0q~H~)>}#ek>u zr_D$q?w<_W6F)HfSK=QmS7C;WZv5v8i`mE1h$hIEO&;vjiO+>>%yl*Hx*uYg&UvVK zW%Y)D_kl-GnX~ma=!#2l@D3F}reG6Zb^Z33Z4i(2%IkEP!0rfm(pg~G<()f-pPp+W zVHW8iAekXhk1S)E_YnuoCN{xVx(A0Q7N0dSth!a#d1#W}b3<7p?IrcuHLloBCc{*0 z46N{~Xq`1|B1pivo@^VE+n2wQ1z}2Avi~U2D9*?@AEySr!$g;Wbt{3wERj zc{ul>Prnlkh|P=WI%H*l>Rxc@_#bF16UvLlRP9 z8~XZ`H8shNI3=>_@Uj`O{wbF7H3Em892uuXa`=zu@u#u-$K!ZpkAoS#ReT^Qe#1#T z7=I6sXYBjYRZ7jW`7#E<){MAU;it%LX_p|Ea8I4H27`D(YhZ9C69yiy(PfC(*yC}`dWA~qe+F%3deHC8Px1O?Irg|ty=$Jf## zsS*&lP8%l(EPFHvhlPe-`Z!(%{Q614=K7p3Yet=gNNr*>O?7%g_P*xl2lFDgy`fc! zlO6>3v&>C*b&FTqg|RTz3dZ`Cx~)c>d07t9y@8am#0WjN27dXce;CG>M{v-`daJxK z#e#Z-DWEIX-tMYhw#^w|VE%82M*@XQ2CKls+=4(Qm>^gS8`!o-}Rn&`ZJJ{2!K<2 zHefA*E0j!*d3`7ABG3LRtxpMvko}b4DeJgBzsdYg1$*cm-(%AP zG;cDRwG$}BiG#gq@iHurC5(o8y=km$Q+p#42^_}IbMb@sbwH1?v(<6MsXZu}O^(Sw z8hk7es8X*ukF^FXNFbixiR3l(v*^!H74g`~E}ML%oqtUMa{St*4yg(en>YG35jVAj zhHc^k(pFo2B z94wCPm#8VhKgvD-X~?Kw1Zv(hHvWk5wZZ>~=lhuIGZ?6h(ka31b0^AQ7>-%;(%g$V zq`$RrtEXzZv4U7rQ!4mqMehZI-0Ki)DFjtiZP(7a0G^- zs~yXixI=~k#C!U4(vFcJgl08HeDwrT~S%>$01;lk`MEPnf8B;$9T& zv%TkRJS}$3KoTfBZ~n7(#7564#`TZI@-;dKcJNO8ZIYwE*gr$E zJixp5Bd~q_f?#39sHFAGt2hEpFWriEu6<<1K)$2YR>ip}H=aj>6k)Nk8KgzeCiyj~ zaYK$8-@9i`lyQh^`gQybbY#~ z(9LHzQSW0`cRCyTHFe0e$QLW5O-YAS&aTlw>uF6dvu6GQUSY$?AKawmRf79u&E$})Ln~$4*{4)Egng?MQ<&7Q5LZ)!3#4vM?4#;?$ zTTmJVGrN4CCic>+>q#3|rz%;#oz-7gGNe7T0~HnKW$sn{R&(Em`Y$>+971~U9MB*~ zyuOk4v(gG>WU70GbmVr(7+fobpvNp`;8vDi#o$DP-h(I`91`sV5M|n66P_fp1z|+o z#nr54AdVYdk*SvJ!vnR+M4=bahIARsC>=>gZ_ZC204AKH?tk{|nCH>Q)UJ7q&`WDpSDa;~xbwqwOUm z+K8K|MhMLw#5pewmS9T>ghi`B<1Hu-bTrNs2(6r92w3|WIU8Q~g&JO*KaLIiO)Q*i zZ-2%Dg5g>%4>DT7fi13WP@SE6AMf_~ zp;vT4G`^zftui4Z@2)e?0t^y4&L6hupS}W1=~PVzi~fjQ*u`)Ojzht6!wnQfQiIZUa%j~Jo(wchx%~Aso;-t7b~5fLhD`42 zLw#ds@SExGqChbtHBdUKnd$*p^E<}*u>38u?`T&(()*e=^6;j(?tnT?#f4byZCA>> zUraD-5~V>g{1)hjKx+&17?Iw}4US-GERIITT>gKYy#-K~Yu7&tNF(qN5=w_kNK1DJ z0@B?A0wPFDOG-(If*>WJASI}@w1^-L(%s!10%tw@-S7A5|IC~@^Pge%?Aar1yr1h{ z*IK_?kFwWUKBQ#YAMebUcC63Cvws4M-Re4>fdQ=qv#QwI+BU*J_S1KO6#yz49|LUL zr`Z`4=^{9~3U_}wUNNgZUbyBC+c{QwfTMKRz@OJk)v|gc?)z2eEcSzZ9IN(9j@%y} z8kgMMToqOn{r>cKI>b$3vqb*k&x+Bl!Hsjza!-FRxY^21)`W#AY=~F%9!ud;1s=w@eXJbRT(z^Mw}ZdQ_lHZui&1UFwHBQggT*Q~Gfx>#hC=a=&SX zEWyJ#^NxQWY{20G>da0|(J)b(ZsBBtj}t+ zz5gDMBVzakqnDSU;!xuJVl5TRLrd=P2jTl0aVQyw6Qok8pZ#$&88U~|E{3+>1>HOe z$TXMwd|$4IunG5O*p;RbGbzN2>op`^4tEvM0xo>5Qy)AjPG0}Hu^`sf*m+CSkN0qb z*?YqKDH%1!!W!>Y#kTCSgb^NG94h?RcA zNPLA2`vy#GMd+;C+uKi`BE1}Au*llhZ>++p7ralWLUtYz-I=^HpDsD685yP2=Mtj5 zfR6EwiPtjoT~*b=;jugZQX$a#w8FrgKl1$?RORnMS*mEJQTNmrkjbbZNld@@0Tl~i z&Co(4k5r9e77)-4*K)kf?{nlxDdtr&a3!5LyCtiZS zgN+{XBkZOm1nm+Phz!9gVi`1Yi5gkJ`tRdF!6C&$BdsS5)nA~v>yNJR=NH`$@=+bT zv=II0@yUt@nBkgjRb8n1vB%yTb-(N56If#3ugoF%L4QtW2HWR47gX$hG=0+Qla+jC zplTO|Bfiw9)akbVZeoMKt-S4E4nr!ZO|FTe5~{L#C+_HVRARdSeudqEUqrT{U}NaB zOwm^;UhBzol`N;b^I8TOnfLY(4svt>)I$$Qf<$-g_igL$ zo~^L4dBxAwAmm1|$xT*l;kc~iuS#45tD-k|*PEx>YK!mB;p<~ia4yPC&wtwu^7GA3RiwO|j> zDf;kZ+v0UiSn$X>wC=^T>uanGd}KR%N6gSu&()0BJTixmQ0n6Mw5aciD>Id}XSG;1 z@LIMV%bo!q%kT-RyF`id{qIw|Nq~OSpM{{fo%`kgobmtsi{uW{d82}fK=={380Ee;@SufXJ|0E)5xHl^qJ zpQc-48PUknF8h=alI&PnS}Is&cZA|JryftseSCF8Rj2>k+Z@m_q$OeJ?~XoMkLRp? z`_4qzkfStmuVP0!Ks9<-urcq~+U5T}a&Vkv=}>Xa7#w?3s;I)zC?e@aL=2G`B3I&( z7)xiP#wjf5MS>-HJ_zQ-5D8YuVv%r$34@I&+_Q76v#sqFc&J-|JI;`$5e&V_3X-}P zpygAwmpSTzUBCfc(#e$fv*AkNvFWC3pmiz%HIlL%9$53^#p5`i4WY+AqEnFSBeSpA zqHCq(HV>9On$4%*X=98LHNR*?2^O5<0%qj)0J2^~Y7J+0Sc}~(G{HQ81|T^)85-HC zhcNULha%SlS`o#J0#1OC&3QOcUCC}*J7#|l(s1HiKD5Y9r*o4=G+8|Hlp8s zDoW|81JA@y=nx;kMR9PzO^$Rl1JG*#z5+9ePW=DdkCzNmnCIEsF6focRQyi&Q<<4r zGFs@7Hk@9-Bk!t~*C-EE%6L?+f^+Ddk7`Pn-03-p)Hy(}`%bqpcoO%wu32{d17Puc zVXz7nZr_c)>HkyoH6yLc>D}XLrW-eYt`9zWkMiSwNTm!KljQ$?HPB07)ZxA>kSadv>u=eG;D!WkmXEU;lcEP zo(9NqPPz4x+w3E;=@*leoQ}IVjl$P(r{6CAN zKl*PvNz_Q%ZoS}tt7o7xT_PIAk+{!M6X(l#H)Q|=Z`L?e_7daAVLQjv6mdY=M{1xw zL2k9qsW12N$a8A`Jro#s!KcuB{e(X4M(xoHkICe%_T}d&n2+S@{QF+jH~l)^dhhgA zH_U3U?k8`bl2IuNrnqV(ic1nv`QK%m0xALyW)njp<5hGnxybGZyM^dn9K1Vpf4_mK z@CIg@0q6O@r|mz5;-)kj^m{L%0Or$x4^!?XEKKZ8R>Lt{=z7Zu6s(pnXle7~gYr2q zVV6{M+GB`p!kxzMsB%mH%X?6mFb?$>*Ge;?+}HtiXA8g#mSB|(Bqx|zKS?lh4(|id z8R7jc8-8hqDF33a&uZ9a2vlS@)LU*n$j~$h^x7M~hc8zyr9}ap9t`NZ5}4ldqNzb? zo~`k;e z%nkhoptO0u)Su;O2VbpkbfAGFPGcS#wD%gazxqainkMP@19))VIFj zn_B@vrV8-K37N#2&Y|qk=@t%~bAp{JrbuyX!~UWjJiyn$8;Z~_JjKSAT|L1?%?ta; z1HlsK#yIBqrf(akg&j@bTJ*5`A4BP#2X~6vFLdrrC{nCQ!- zz2WBxc>To_!aXqHZYd~-k;1JoPYd*mWY|67CL z0n;-&f--$%vNe+Y{_@Q|`bS*f*f?-avb!xo|Bh_L-rhtCSa}`|uotz0=(6EFlTUR$ zX|Yiqr5J41x!U=!uO344ci;VSKOLG|#pROf4SDtVO?OddA5xQIT$q*Od{_m-%|oC+)zx2Tq6P~U!X$xYQt_yC z_@IUA9Rf00ck2u{#Cs7O3VL){vLKwyPS&Cs^B(+Ycmr|sQIMG;UIIP)Kp=~3Dl)^Z z4`zKi1s3hRIF1?qXB3o&d%#>PLE6E4cmp0YZd5)ZH~$GWQVE*Vsbf>f3o2i~;`+@L zHL~jIa+!~QXzf<_KKUI*ROS0>R@eSKi%qF07+mTlXh;d@?Ie)p=Ip_3rJH+B$ahYH z=R)qa2UM8OA`#lP5X3N7^)#AJwlZb>3_e*?1Cowvpk*P-djblhru!{ajDM6EN$%_L z8F8oi5TyRqSDrKb*M*nc_A9ESiRMPrN&k?z_{|8!{B=fh^oR)EbZHV(bS}qFaEn%7 zt@-doEY&@ryGZ8z&Ofg6J+MUKcp)+Zh|E-GIaSaoR9C0?;#)?)IaG#i1$!TWBo3)D z7snQKTb+zt$EqZ9MSdcI1Z;t9dreXjFGH4BD*|u%A5ZPR(XmWrcOzUKEw=H|phH00 z`7Ws}I2e7nQ@;X>!fk&>fNS7E`u>d9m5^S>) zWDgfldD}M5Y;@S!+1V0|5<44Jn&;XI}?IN zUuWLOU>KMTYLY&5BChu^z>;f_ps@c&L=8I^kf|J?I235edF^(jKxZ(R5JQ1Z#67iD z2l_Wpuvd(WTl;(zFxr_N27*SppBkH36o=_s)@0hr^r{Q{RSYgKF3F6QiJB@% zHz7~^l)H6kXoauw*-SYrpWu@;F@Jlmge|J@S0!qSgSV>5 zbw^D5{OtLBZ-mmGahm zn%%#_uK5hWLng$TS3F zA1j3FsdMF98=D})7WU_xwy3|YKtKAEO?`u ze01IuufUcCzojy!Tr zYQAda>)boz#o+TeEqS_oTNYn@0E*+lgkqQ^6gowBmG6RJy3fsxM&hyU2SchO zuxwy-Ug(u?WKR1)>*%~*I+#});2H8Rr}#~DX5oZF+N)QLdb6J({lB!l5a$hvsJ=($dB8^w2JtJ!X@yjDT`TB$-sBF(Iy5;(b zc!2jeuua5Y;y#HwjVxd25awF_c1918I^%;#<;O@KKw?ug>fL7zZ;$aUtCy}71}JgX zXt`Z{T`hbCGvsin258Yv%PNVMeEbO)evR*w+ng=sOYE+1Rv-78zIr!t;O6W3ize-n zhl$tMvKLsM_Z@TGOT}v*s>U=;?uV7e2zdkeD0lJE37EUqWg54}?a5&&xpGQ{l~v!K z@uMx}Ku6TUBOozSH^qx!cWAZvCP)8n`0j#lhmb_=#gq_MV=-nIRbtf>Cslb%!7*LK zQroPZBwCn?H5a)Bkox8~SjWDe(e!ms$*P{S28vEl6zUhG5{kcNdGkhpMSr5)TGt^0 zQ!FNWCOCpVm=c0jbnTHK4catb0cd*;Hj9P?Drd%k*5-gH03wy)kGe%BJTPpQ#&{nA zblt~ad(GTrJM!60%o&Pbh=&Ux9?%Lk@m{};L=w+RhB*je1MGNUnB2$~HQFTgrwKqP zZrQYv!$5=-vmKA)`d%E(#!%oVa;SYk^YHd|Z2Mb-E3f-nNJoM#$w!pycpmXJ|4tZ#R*o?b)R9j`9NGRmi@ z=1;2eL!emi8^Sl2rsv1}eotan-)oi;6q$tKi^u$Xm`^75;*O*6UeoV?Ue0T%5OfK$ zx559sukz+9wSWTRr1z_-PIh26iW&K+shdV=cjG7SuvypXR6+*imZbMcpL9bKrB zAR%KQDwWZFNbq_M*z%FHYqmBg8MUH8{09dVEG>0(yDl12F6mB9f*xz z>edxBeuVeKXX?M{dpyC@YBQsJDlf@mMJQ^ zwa~hiLJejGVT@)^!R|-9Sz^XN;01O|_a$&Ow!+Pr1YLi-466O9x2Y=)ZLQLjSM&aR z{H|%hO>k=c%trYZcM#5A76<~Qp!7j1M7%{zOy`Y(x9|R28QJrCcdA5}s?l->-NOOc zKQx*j@B($x0VJ&jvcU-XsnfXQ_5d@|u1jHAu!Ka&Y9Zzh>Sc7J*5lCVel6SZDb+o9CiGi zEaZ|+Txat^qWbPr@U}i~qC;>@z2z6|nU0!wY!BwGE=E}ZUQ8D_La_DJ^tBo2263!@!~LU|=pf)=~pI&h+eJ`vn)JSGgJ zp-3T2r53FJGQ&u}#vavGAAq%$Z%8*$!wf8&V~u+ay-Hx-1%u zK1Fatm0|!pk?~sy8J{Ey+O(?FLOu%SZn%Q1W1j$Zc$^VNxG3nQ|kN$OYrZ{f<_BE#mg${Rh<( z*k)Xz6`YNM+_Z?b=?6?n7%Tl~iDrG9ZAU%)?USCn<#lB`s(xNowLbQnfVh=Cr`@Xd zSjq@h5wNwRH^ABWSn*+IIG=jc*Ire3d2=7@KIw+Q2Kx{iMe*C(G4c-QqUxOp;`XoJ z1TtH~AUzJHe=~0^v?XH6|77cOpdk6cJ9$E81um6QfznSXlYWSGC3z>F(P!z1F2(|1 zYZ*)Sf>2~IImhECoxC6uY&hZRD40xknw|)}y|^)9H(=b&Uq~z3_KhB`9s0qK=pU9G zq$Vj-ns=dkj51Pd=W573*%*7+HG{7!O6W8mcxiwqtq74X`TPCiawKo3BVsrmwZIU& z!3@EV3_Z8KMmter*c@St>13RaMuClD>`RM*XYEw{;pr7uaRkj1u4kX5P?hN=tw{dt z+nUn+cPG~`oz>;y#1WY(UmYVbMC&j7T=Rh0PNXF|R+55vXj}U^*V>gT+5g@^2y7U4 z&@!68{P}a35X0z*8VrIZF2O*C6FDY-kip!+DFJ?MptlE z+f%6=x~&eB)}>x;p5}s>7ngY-LZ=RpWA5VI133~CC}ea929U%_HE4!z=CzX=ELkAa zsGYAj85Yx5^z=MJlwQh2`Gt(Q_Jp>qk6y4$MlxuL%!5SuJ2&FAew(B-*HPT9OwuER zWAXeQz91F@u?i4y=$*fju`V_Gg0J6#=I_9_*oO(n43T?j<_5)t83C480j2Dvis_JR zafz2){L5!$n5H{ZFt|*8_v4AR%pcuJ5kXb5Le1}aFufjkp)JH~hR5%~Wj(w01B{OHl8OM=G6jE+IH z+V2%|Q#skiQ_#CHoB|V5Rct>l$=%38*U0IabM?J@_q16C>iA!M5Fdabl1hl+?WdZ# zcQmq09(aYiL2=Pdr3T)tnW?Lx)93y<2uD(R+G!gCZkh$0GpV`5JxIVx&a6EF|=H1H1)JB2Rh0ho79_=|HE*`A?@fYP#3O=P;O1v@Yd}!F{PP zAJU!jtzQjulo4IQ=~ALdY24or@iiTlp-ik>B{~ZhygV3nZpgUdmZ(HQ^*fbXs}Dy) z;&%s06QZXs=%-em4#5mJFExr?+r`WH;rrE@m)1^|gbkrjOx&3Zx#d_9RCKH%{F*3% z7T{8f1H8fbEt%}qT+_PR2o7}^mGnU`c}7L0ME^Qqmt_q^9y)<&-k5~f0(PYLtuD4@ z#zDc9gN|?Y%hCK9FZ1Qjr^v9xvl4xAHPp-B?-t53I@bCEs<3Wv-l$oHkt!cY9;OCp zOk5&XCe5$ws%h-N5UGVi?iAw}5f`%hinb3iG9J9Z<}i=w0XZw4!s#~e`0$RYe~=KB z!K+uVcH^5+b?4pgV1IS=HTxa5hDPJ@sP>_wYY~`~yjDea(u?%!(k`PhU~8D!$UL|C zM0g)B#gINFAO|~^KBY+xQCSLf!}uk&AEciOOzTYg!z~;KChX+w1Adh}bX*FN#Otv! zv+|q^l_Z$`@w+j6jIUr78CXvp*n+)klKhjT8Od2neZOR1aX1yVUva$w-~Ni_M8PHO z_l`xs4za@Q=ny-W4T+PI&3Mxk44w^$ebmD%)_4m(Q|H0r$z<&(zHc1-7H_>cPn!Kv zCa~HzdC(q48m2r)Rf>nE;#(KuPclf=K6#+V-@R`WfejHA}+vNKQNHuOy#pqKF*D^D{|V?h>pS^BLu{jOh1w4#xsDR*>3=xLJu3+oX8maVF+*|O7n-N&%Q3I~ zy#dUrux{l2_uCPxBcQ5UA4uBD>ls zmjcLT)oe`hz8dwfuicEuVfVNjOr|GUJ7>d7`izf}>RS#j7v}2$HrYBK z4f0q8*P-)$b%W{$QEbDp@SsCmsEfb`ImR1-RTKuaFu2+JCG`TruB5S3>|R^)s3EFH zeBO8t76C#m{vKb z@b4d#BQta(=^C;);4A{pXrvI3#zXsg@A|7}0@YQ>e`% z>+Ormyquh>kXA<@CXO03gqDd%k>WdDKqxbgR6dUk&|=`+a-|8goif^F_xGHOm7jxz zOReFtDEYx@R(woOhm)8|@u@LF6$DAZt0(7&+12^As}>6>3>v}FQ}4PMpUrOFDjzea z*|}NGl4E+^U2y)}=Rv+O4#YCa6TtbP*U)VLMKD^6ZKfR11hCL<&Gcl!kSpmkM|72J zM}?+q!$fWwAdIm(@ENu8v~Irti<0W%0+US_jDmtyE^L{p((H4sbSr_9_^W8&$mirt zfjE5ZUN0v^9gj8&G3*I2YhxuJx2O7J5L6@MNm@5mkD*~Tox;8xl!G7pOu4aoRY46B zFw~=`Pkf|A-Dn)B-J#X6@=JY&`SqUeL#_pZ?rkqdf9_`Th+}NGvyFvOyTJrc-nQe` zMkB2A0#4Hr8T2gJppqM=0-C^;ud2$*TE>#W#Mp~wVJAV}U&|zakS}@h72&uOnbC1^ z%b|Up+~|eYa3af0Yw_@)HthFABw^Qm?5RB$K@pMBbE<>v>Wu`Kh!eU`L0cr40oQ8@ z8xZ*TZjJDd9y8_LzCxCfN{FOhBeH831~(d0A_)Zs*Y!8QMnM2fhMji*NIajBJ+*VX z;(y?oBI8Mayzvq`O5Q;I0)T^e# zzr-n$FR<4pY7FJZ{Yiu;xX!y}2nbH@H70L^ z8#yL)qROMHcmxk)D0%OsO7}g3h@?CArf&V(ijD|!@*7At5?~@>QceY%4BoFK^^$$t zpyJ7~^LV}o8Ur_?n1`P{Jb(GQ-jV;@z&{~bDCA*CGjH^U<)2Wwb$|xq2StHn4eU%F z>ku}!XC!WiT;!FNIN^ooD0lD_)nJQ(7{;CJJk%T=KafxiGZS}ANx_fDS@6wb`)Q*kLeWcoK;^{iDpz##IjD zt_z4ByoMSnREvgXnYw2!E^S;_b<97y|6rosxps$Z_q4dSeW$Q2^_Y-?tDa*bSYZYd zrgWMRxoAXebdkfbm8fx7=*2e1R~jh9bi`v15{wsYk2qqcX(G7aEOhx2&DT)U?kwNb z9GWP7lrYj50?7NHQ>RLy`CEm6{gl<&3K+jl6}hh+6>|02BRZb0>XdR>&5 z9$7qJgqsVzdx>mug+5Y|{__VVxsiW@+Z2UL{Eu&x{LJLvav3?Os9Mm1phu~>3bszHeMTN1G2Z9wZL7Nr8!!Pe{<_Yqc@AQdRcnGk%Nnx4~I(F#p z8@?w<#V8yjvMYyjDFY|?nj@MUnT^n(gK)&RTp!TNvnoM?m6zdDkWi#P7hFr8Po=)c zy#PJ8^gO3RSfFSNUXYE#bKOr4cPs*2_+;6Tu{0%*#|;qsGY~Ow%ut`$nH%;g$X9nk z1;s*m4jR3L%qF2uw+gmNzzp7i@2{00^z8aQqq+hD%B=yPNEyRF3*~f5bc^tW-v4Kz zBu5s?(PRm~TCo$HV4I2}DLUK+Iy*?nCx{(#WdH9Go2tyFKJPJAeF9=%CE!=7z8t%l z%3?r)JVv0dfyiv-`1wu46QMPG&%WtaxCCy7y$;=!0K2wgbuc!+aBpHUipJnH@~H9U z*8c*V15WL(ZIBwyJgDG#;Y+xYv9BYWHk(YTtxt$G&}U zNDv6D%<2PFhi6kvQJ9NZS zYFv{PU1sfKO{3?Bd&e}(c25bY)EBSC3#n%5maS%JEE3-Fce?(~mv~FrAC00bGBN1i ziHso%eo`#I#Tw@y2Nwkg{SJysf}=qwHZ#!6kN~w&_6-b8;ZJw>kVpWP!?;zMO8qfm zEQwBmUdETE@87XgVC%!jxWtZ$$dgNt_G{J;#wnacuz$tI+cDC#)HeQW zZSSvN{bF(=9h{KG0nJoKRaUR$2%f7Lv<*&61+*gP6XZQ{0<%F=Ab8c^zdUJ5XV9~7 z&ogzTRP6XCr!vybTf29Ep+Q@aBH?q z`dxfnp$67P(qq~#j3DEkc)b&$N_Ci}dXb5kJ_NQn^SE-%MxlI9MZt7P4t>SI4mlY@ z>$CWqY3zyB)ys9m6R_4`ZR@p9j z^6@|Zx_lieg%?IHWm1AmzMr1~xv+!K_L>854)>Ep0AHX&VAX@CeQ`&)3oa^$j8F;! zD_p&;ax`DxZ}jevS-=`|%nkaAPz4q%&qxdlKv1r!j87OqC8eGa+&K9{AbvbYa>WyC z-y*ePn)(n&m2ByE=DB3^Y81-#zFne~lktx7x?M5_zx|}G2fi31G_tM;!v?y?0Y^wZ z?84%#2{ zBjVQ}qDR}BK13h#EUAQD734znL222xDUmi3<%-%KYWkajlJZTUf}^kZ6E~ScN5a{W zKo62h)qC4GUI8~l!)&meO3zi+^V}DzrI-llxeD=a83ovocIk;88izNzr7q!Rih<Sz7N-$8jN(fc3e)eAfgo;6!1I=i>?V5x z@}#AOA7-K)$mEA0GpgAF8kdBE@NZiq>*bS{7`DwE?`s9 zTC7<60o}`b!}|Nk;Nc*PEPa|-x2t?MW@P&n#-wNzvUib-TI?okjrR#JuxbDs7Cq?K z#&iHwRycqfUH0VGDXfKPR>smk%XTeL!hSM!go|`1N9YBIadj@_Rd*JH0Ow&}PVD?p zGCi!BYaP~-KkD(MEAzL(B={V*fo9zgpJwhay)J}cJzdK~NZK0tfwdBHiGzaCpaJO9 zwL!+hb+)2v4d`O=W&`!^Tw@Sv;5LpSY`%wzm-3muOvqy^ofWOwAk21VW@Zl98lnPI z+1K3b5U72yiZd(Mhf6JmOE5V#7j@;kW`g^TuQ6zVo1Ir*8WJX!mZEbh z)s&CyADAH6>p$J?f%^p7a*+YuKq%)bTlazEMF9x*rmphhqiNn+?@dV%GgC2qcc1iMMbB5bzDSB|8RrMcL?+o=I6|HTet)w5={;L_ccem7gqjqOAk- z_8yCO#F8ZlkhL?(Po*ARlD;9^;~JK*{1C z{#~v~{7=eH79Hv@gLzVf`wbRJiXQHjIY z(ZWJtQHga6u*LC>ViR}Pe@^`l7cgt=?d`RMV3AfFnx6YpW`v8K;4r#*!w=j1>B;hq zW#IWGr_er#3Leu3hOl`<40*ho)Y~AJvz_@i42O459!y|Mj^UW8(PqXVBQ8w#VMMqN zV7A5#rr>Wz+YS(e=24wZSJNt+*z~PQ9BlvC00@dT17)N+xnbIsFo@2)Get<_i{;(Y z7{X$o_t<9Ln{cW-&&#}J9|XL>-Bkmb;yg+OHn?8T!Gtp|e341x0OCKDXBOMgnZ+y2 zLe_+Q4_Zfj5GyW(%qk%vAgQ@46cfGTAR24S<(6AtC3K(P_pGKr&j_W_s6xa~-P;T+ z2wt5Bk05ziT8ZQm+#ySIbJU!8}ZN4ILq5fpy; ztAtqH8(;xofTTv9Ra~^&ivqRDXcTcy(OWMQ6LWsl`dvIt(HXq=_;KM32`z0=p{Lu- zBq8?tSNF}r1FlWI)ry3vrzp*)j!h%}j*FlVEGFOoPC_}oSM{KcEPxK)CEtTDUX5?v z{2$S(e=d>w9qLWG@dkl59kq*Gh5A)x`gg&t7sqnc|BQB*M{wqSg1?>zE{p<$n1JT6yZCQQV4@_8b#Yn~0wlvbi(Wcu0%ARdUo*8TsMK zySpgAR&^ZLAMO1LBpmIY+uHvOe8wuaI(D5^EY3+QtJ!%+Yow(5mfs=4@nlXW&+pR) zY_9A0k6-z_Lo>1+P2%z|?;y#9lw!ZMdhYu-09KDpceM=~M{Q=LdID(pE{kU#RXhxg z^>?X5atOny0&ZSGpxXomiDWiN9%bUknoTLMbRv9bAWQl4+mPbl!8jyqr=8c}fa4O^ zr;A7WL0Cp>z;NZ$8bT*22%lq0tX3-@_QS@cqw$y0L+Ko$<4b~!GRZBoBz^Ih=v)++ zChQ2Euw-dRxE_abY!PB^|3EHfTlUEnK%;Q%S#^d1kyTo;HX?<9bS^z&iJjcYF@U%+ zog$^1C4u+C9bz1G5d}RU)ylOIM^sAb zz1t+R5|8s;$^AgJAO`ZaD8nxAPy%YC+Ow2=7Y-&KvFuc}#45@>!WVV5&$C+a!#XJW z7qp@btrQY8bR)*p@D4_^#8 zPfj~a{}m#!4u}F#Jl3~ZND=UMKn&xWBf|Cq?*{;lz5S-^{#Zi0H*;`B#o+2<_(r+D zI0E(ZM%4l@O&4}p<=C4KPZ;%4f)+=cO*_hDKT#_7d4P>2OUpS^gp|l_>{qp1pV^Rp z4EmQZE^|R$Pc^<7QKMo`?nk)9(ZqBo2K*&A`mZnJy(557nt~~eHK6n(9*7BwmZ*?D zNyJ^b$d|EIsIkTQ;_CZabf+#A;{pD%5GXMs65{_Y%aXB(Zi&~kQK7MB(9G7@ET#Yp zB}n|WUHor6YY5^0PKcp^iHWHNXk%?zd)Rs~?e+Pf)SZWgWxhNE1P|nQW{%IuR*hNO^l=>Wn&gFpZ6@3Ov(RHw0_9X;ZR+OH5F4hcTd2Vmq2v5B2Jx>sbWO6N zlKZtDnn$eL>lx|{J*CSTNskbos0?5KC}5vdu6dd!E-L4r`;v@}aKb#_`&XwO<*EKT zVkK=PEM)gt$8>Enn_^T1&X*^KWz}cT7bfTtIh$9F#V%)t2W_P z*nGk>pFe3QAue~xeUbb3ju+!Y4L0=!j;iaOHDAMA%lvb=Gih+2yOG!i!gqAs(Ql} znTOdZcjO(V=E$+7r%-Uo5J9q4^bEKa78CR-InZqC?rub(U=q|jqSHY3bHp4`G&}uJ z{SiIzRIsnrYwddB6(b8uN=h)_vxV|F(hWq9p@STkCUA&F?Wmod5`<$SnBNP&){5YOXJDD3|hLC2>5MJJRR!feLAfM7mCAf zv%_Egi9{?|nZiDV0ZYVz<7(rC#-+4NpUv>hp8odzY&Trn7GX)oNnR$VG*W6yY(w6d z`5UPwM?7jU!m(@2e6=Rqjs3gSGU_+CU+zBfAXTn$O@z@v?G<3Q-nB*iHK|SUK`)?E zJf)LJgbljpU<$$s4eg$vA}r1-Me$!2>%+O;T{+nx<;QZDj``rN8(;NR$5mvi=@D<% zYS6W@w3t1TjSA9(3h=es&Dh2KThyghLFwJiYlZjMrz?q8h=WXgW@W(c1W)`dYwNSs zlpd$Pc$DkHcXR~bZ87-=yu1CKk4u)F+;Vcr=C9^;tVsCMvestGAXE;i;Q{KCn!r1E)v4kw{SdH!4cmgEpOb4g+q}tX~%=%2`>hahea!4ayW(bxO~| zdg%JeCMtI;$NQWdByb~8ENWbp7GfM&`+H~B`lHT0LaW95xf#OGEaM)NVuU)F=5XFy zVKR(WiEjOa5@vQD2p_*lM!jlmV6 zW+MTZ&@Iyem49_sa#HZ{Gt)cy|DwkI(YLbqk(PHDuC%{LfY4IOz`#H&CyU6UjwaL7bp47^+75CaF>8;H!>1NkXO)f&&~J|wfNApP(40oMk(Gwba}O76aV z^{NpKdr(SGS*Gtv;40gf5ByZ*qNw zDh(gLUH$9tMaPGP#PD?ouA&4u64x6!tFXK|(i02qu^UchTs+jbI3xNo?WnaGj2G%e zI1u-UgZ)Ocvx;K!MZwEUp}RXysw%83`pxWDl;f^4*2^w`ch>v&%px$6KRD>F8Tp?d zzd||%@e%OUb4a{~5rP@3oJ(S!TqdnY=Wk3y=jsyOjYI-cy|upHU^CJ(i~3w53em?r z&T|SP;ou(p32x{$yV2(>jtm?eDqHT)KuGc{ttdyJf*`^RGqcLKu&5<%(h*UQjM)g> z6#E22U<=G{SDn;?ZuvJ9KRBrNvpjpf?mQ!#MvQLkCB^no?SsMh&-X*0(+2D(ySH?` z_J0Jw*6SnTJ6HP(ImpXJH093j?D56uL&P33(VjS(l)v)c^2|l36i@!{kNcokiZ= zsl>{dq!sP*5mpkmM`e~GB`#m%e;M91t&}e4%T1z_FZjGZ@N;6JK;X{?-KI z@gE}vk25VFyp1be78;<%Ha?Ugtgn;^$6kn8$ z-e-I5%<|IzRXhG;NRE}Af<3!&knEht;Rgs3EcXgkSgAGjT?cm=^4^X|Zies6Up!*q zsAIi#=b0#uSp-ppH025aFc>`?Iz=WQQ-nM25E(DRUb#5fXQK$YAsw1y$a^&46En*6 z`uA}Dw?UwZybHrV__u*Uj|HKLN$K-VDQb}??0e$qBW7UA1ORY`4!1qBq^%lE~y*JidstrR&?PwjQRxpQvF*4zD=p zAZjD4^CQOkas$8rpkO6uJ4}AN8LLjarZHdg0<}lkK+il{S%&HzTcNs;%DGon?iFI~ zxw_f1pUsoBFW#Ek-|Sdn`kCSvtr#OO@bgl+mWI8y(sRwGXhZW*^6Q&%pWm+k>L2>m z%fh`glp3Gq9qRn@C544VbX38b=rWhh$F(7svFVCBs`jT7+k0f5pZ(mHJya-JEcQ`f zr+O<+9Ql-2@BO4nkR~hs9Tj7z@j%=!JFVoAiK6}F_TKg5hv(|0#@+HUD!I;@%{!2t z%W^wGcoRp-XLtJWbZ#4`$_Q7s{lI~yQlF--D#F#lRE0GzN?RL_*Db~$n=dBGtQ9K1 zaPRD-U+q0F;CX2oZe})mxS%-6y}WbCn*2hExufr6uw!hV()kQK8C!YKxYRr) zvZg3IeOPxsnG3bPt z!BJ1zN_uk1M4@z3+jqL`*c0tzgIcDhD7zIYsa34!G=B3ifDfcc?OQ3zkIsb;t- z#aWYkA^YE!l?m{a{kW#sPNIPZSu1(xjPiEoA+W$L|7;zrEO#%nY+d`S6!iIeUd1zS<+{Ph{dxPNq4~+NWr)Jn-ns%lrBq>tk%H4the?rhw)*e=4>wSPUHL0DiagpblG`IgbDzDnU76XIL#RI-a_$D3ECGKMWYKNqPcC! z(lO_QAAT~Hk0w$Vqw^8g)o5q8i_U2bWvuq@&*|4OGi2g?mvzfaId2@wA#`s^{(q`342=WQ49Twu$#3*G#Cx}Ma}8?_Gho+UnlSLy%WTA zY-wrC;vk0_SYcy-!kw!H`9^vdW{A_vwB<7P$+TZ3@IHD5daP9Q+MzMdWuW|EYO??L z8VP%f41u|zatZ!F+B_x%KHQz*A^LL^|G7IEQYAlOa802SDVvz2v71)O@n>(w*^3;q zDkB=SiVS{6plj;q=@!yGXp8&un}4QY^8CV=&GLPtSCZZLfJ&pQsA8LD!yiV>fi2o(m`k;u>L zi`%c0;)&-rZ@=kXue(O-EZbbM{c^|F`}@)Q&V*~So_v@5um<-R+ss?vPxmAU@79r* z8~CLQWyzA4-XdzhtArK%7{}b~N?TKFCQcbPFG9wMw|yX_kd41AnBA*9_q~2#{KI0x z*7O8>BI^<}sYS!8+oQw-Yp*6>)074aJeb?A%FEZB>=a|V_{`u{&z0tohHN$!)lU&! zd%oPp2ULO?2W^H#%2x+f;_7s*?-tSzY$aS`b=z1Ja3R3?&cP;NZAhf}az0DycKp$g zlWPI4)$UOR!{#K?xdfE+_fVAsuf)&g_v~lEWtDnw!N9`vd&KuIwwh&UiIv;EQ&+!O z8oyRP-G3q0s`5PKF3;?E!*OY76_@ zRau-Q;Z^_Y)Agsr?nlAZ!WG#@j@kDVdhL(ALT_?)?qdewEi8|cuPC*JuzY!F9X-b9 z{LXIFcg*WuSPQRj-v7hicZXx$_kW*684VfHkX4dh$}TEEt->z|A)criy@A>mNp8L4&^NbjNcA1gU#q&mc$`0D<- zpFfOegZ+l6Qm3(%HZ0O*RZ_Y8lDL?d+;Lq-l{D(6Ch?b*G4aHd!OXhb3_F=44mPLo zar{uOs(F$8`hIG!40*J4u6--enhlSPWLa>KkdO#A3Hiw2-kueL^ zES$jUt-9}{#H&~TgONosB~K!Au0t~++V!$<0*hKiN(ZO8TI!YCmXcOvSc$h%6_%Pt zSCsgEynV^4n9e|#)&0_Hbf*1C=PHJ!A^xL|=m<`1T8ndfHt+6WZRFB4>A-36PAqb& zc>x7=R#Qdg$l{n`lfJwf`hY604D#Th#ohF{R?Y1X&Ze3g|+C3Ol&h0&+p2Jvl>55cxlT!VJmbJ&+pT^b09yLap0Neg5a}Sy?KVy zO-}D6#p|>Ajcva_aXoLl$-Ox0U9%KD(J|NZx>Nj_wpRXoj@F9x^|L2es#wh!OW)|J zI?a9RHz^$sV_E95^x3^ea*9>6m5FZtXl7i0(PrQKrR_nw)m4e4+Qyt?uf=a_;5)5< z)LineYrJ9;!7)zx+=aP4c-`j=M`p1!bm8w0{N>yz5fc;O^mR{mhL{`begrH($I-I* zM`2nB+Y9(m*jHa%Fu!wO)8*K^cXm_Cc~9M*2faFvjG=2yIt{v?y>oIaE=VvLzfwSa zm&v&N@s&?c1W8YyW=c?ao}LUVAiBomzSjs>jjeRow$>`h>lXI9inv0dZss-P|+`=5=8n+guj-J0cUIc$ndt+%^@+z$M%~ z8u_gGQAUX7rkT8k?Lke8(EzjJtmyPXl5)&DkBp4u9R9U&&R1(SSdrzGo!Uo}m41-4 z8)UdR>b%f^4c@_3NFN4t7T;Xf8YDsMv|KkeOzlZkM%ich!5#aAEau zeZ9?gYLj_rQqv+yQvB-5E`_04c**YP;i*q{-BcfCc1M_7iC>tlx6n7)NwAUx6Vuhyc=3=YV`;uZm#}sHTgm(4^yl~Hnp?=p+OZ+EyEd5LOuxjS+Hu0e z9cKqw6kd-(`1P&b~T&hKFXfqK|3*_RX*s=7!00*)P}h z+DoO+zc;b@;WY}S8FV+5wa~P(UntM$>txQePKKpYYX%kl^*$$o9IqQ_a6PpcP&ERFKDU`a-{^(bIA@wFtA}a3=F_s&gO6EZ>E)kkQpx zqyv{lkij-hm9lGS-Qx2brejw1#>eq+m_pU>#1%*@#@}1#PElf2KGh?k^yQ>1Hib&W zCCjOgX4n)hbBzx6yvy6nk|>Uv`>1+!c?q$0u`7R0fGz)~tr= zmfU=#YYsl}>q?IPe_^P?p|%oq&13eT3>rU&T1d%Zt4TwFSNo3*seUDxjLYsk3uQTK zTOQZWC)j#((fr23?mVw9I4NV=QjWMk6U4(al9%)!8&!%u_ki_0vqvn&MRndjR!1+? zBauB>+BrE#FeVrIyUnIx^qbXl%0crrzq9DoE_GizDH`0PFC_wkY8}J-X*u|0TT5(0 z?o!&27HGKIUvx5-lTNwwm?e+qj%4NpSF<;n>c%q((Ls6PgBmL0=DWirr}bB34?E3f zFm@EWoNwZBmw+_2jy(PEjy(WpmS9w0poNsAqX>f!kZ0tx=QLNjZ~wjB!@8g zT3lRT^KD;U{x0`+3yKNvSR$L7JWZKYkBge!4BPgR6>Bb4R@HSjx1_y6!_nUiaavPM zXyLmrKVCClYB0<_+W1+efTwd#JnORr>if4_`SFsaN@&@M&7OBpj^K&{-_{}7Z6U** z^{iJ)45yh0(;LsJ9HMyjbwl#qyO~=ish3){LuiJ4EQ2LmFP^8mt{{6St%8SHJ^K7; z(tHSRYR);g9&4uzkE_LVOL%^!$}?A!xW_V5jpPq698^@2GTn{JnKh;;F4e!#sR}_E^rnZ5eLBsQ z%1ia9h3RvBJEvo{(An0Zyd2U+60T08D|~%-CFZcJaq2Ar{t$;ovpLW2{Y{3+HKu7| z7ea3b$>c2@YIo>g(VQbnxuAi|zGLOIu*=xw#)X#Gt1#(xR?X|Te$SnI`G?zBTC>8x zsHwo>)Ol5Qrw3Fpk@{S+@&9YFSaARodXiOBS74uehJQXe2~Olm-vjbGD-{4*zTSqp zUZo9~KS<4k87D?*7!{a;N?dBk&h}#A&C(>HUqamr25q&ba!EI;aGIUCHFxx3=)S6pMebS=-(IfAw8$WF767}w_Z_m^|5u4R<&`{M9 z`H}J_;E1b}pX>F_tQsdx_isywi`{EQ?2Zn~7UNqeq?(kqxTHRQmxOD3UX121E`Y0k zX=1$ScMVM@l0+ZdiEG1FpPZMNZqF`@$eT{JsS#L@O)N6e4h?+DLNoQTRjCwlF?7Ry zDY7ZcX(B(90TY)$oc2e(k1GdX`0-TOsN8Kla)Qkv;ta3J+~iJJMCA9P{v=dA8QIxC zNsGK15$dSBZB#C@dyVQp82SF(qF-KVM@mRW(Ie~>+5k9FXs&I1{^PZH*?EhwWl(?D znO()68XAa;Jv^g|9&?&$zP9w$rS$78ebc=Lvazums-um=sb=!r#3T}pHrtryr=h_r zPL@>p;_h0XDOBlsQsSB2DpKOl)%OnAlBd-DT>FC|Ch~*@G#Mw?mXuZBj)W0QD2e-p znDWKH3;Z6~xI^cJWg~dHB)V5Ck5loR3sA%iyuPnlH#I6cBW99vyDyJJwEu_p3t8&8 z=J4vncxrE>9d6UV=Vxf{p;ENFLHaRP_c?!G>gzn?JA~PTy9q2yW0^ks^f66ma8HMwY9~+O+HVIZHsx{`Xe)h>~s#=ZKDRgxuL<1!=B7^TSG4N#Inw2 zs=(2AzPoeJpj4g3bbBD3StKEyfk%7SU5N4{74B2T3F{E3*E}Hz{0oC|7pdyzOazu+ z_$!_Io3r)*@P(HV0=>^`vpODNIVz&w831&)7_Bt*LYV~6u2-6Zkxiuyz|5uEHa??a zH1DWAQFm*OwAv>C^*!2@v5^GK2aCOvRV1^fDaq}knVVw-**Oc52E>XAUn_%1kU$s; zU!+KF9{p9!Aj<4h2;C9Wa}o;PAx$|>%C-S#1I^!&o8wGGQOQYLlrtX*e{QoC9HB29 z!}DC1ggyEGuDc^K#5R>m%;Zcjs4|(L7}%HE+|sI8{i36ZbL9Q|K+E9zd}8czt1q<| z4`KORSj|M8;c>qiuXR=ZYlI%pg|Prb&L%3!%XTMRrcEMFCq-R+y!i4<-Q@+%ifif^ zW#7V`y1r&N&Kb|c?)u^V6{YI9C+z~wWvo9Jb!Bo(e#TMH9}ByZZm#E*%*`g<$1*QH zoY^{pY}wr`9QKm8g2gdseKqK>DT}Ic=Ha^&^%?l(?@$wA6zl3;s-~ri4SEj_rAZK; zO1dSIL`k3%;b|56r$LYPgs?}R{qY&>J+0pV@F4G<>;32JLYI)>*zum9vr!Pe=lWF0 zqmD9*=V^nkQmo}Y^xccK3-?7$B`3P|(FFrh{pY4iZN`H5QpNn7n-q$-jOFVemnkkS z25ycO2RbzClE*U%r*$)=1x9jioY| z>fe0`hh6IH2{3R=ef8nSdpMjCY-|%2^V{ zn+J!1tU3cTS;^Z&yaV^0Wq8-_cD>Z6xZKpd7;E0Uw*64`!pC#?GZmmFK<1=yUo_JE zb0hxM*Mg+T?R;{fFxh9d=|VJy)pck6N(e%C$tW!gToMsH9++jXLys_dP^wui*;C!o)iX^^`PETHSvd)J;^pUXcx-E*oXTYpl{wjWO7*xUwUKIglpc9&Q8KNO z&&|5J;`<@*8YH$);dc+74VC5#kc>KCO^_&$B9VHX=J)3Tuf7ileB{!xS=|5e0e|Lc z3ejoNcy-(jYPmsN_P4a1$Bnwxf_PcaPEr)t^^{c8R4}~}A3~eijO`LgM+m z!@Jj$J3!GqwhM)49-YWvwbG((4N2ii4A){M-H^XyccTCbgFnOD0g zdU?q;^IVIBklzQo-rI2x331u0v`(h|)u4Y81v?@vaA+3m|6)h}n#Fb}UR$UMRBBSq zb(c2=T)t9&h9+N#7ATG|N<$saSl)xw4ks)ujCjd)cUmF#LE}4?hOd#Cv;rH1^0GF)c~r;-;)kEF3;6Ro34TEC+Lhom-(O;12!H?g|54*0n~&A` zMe96FM!4ZxZPj_fhpy9o$s_V}1H8V7K=kp2bM(yKk)3~Ym4!}#-K8~sOB-7VB_z3R z4Uj#R04U-#xTqA zW8@o#+}N@G`7ZOzVE=VY|Ju-aVz7V;h5_4q_>lhoa9&@8E4L#1hU^zJ6W{1C-mo&%gw^4Rh&&MTR13%B{h<5AbC!%7nb7RKvDj9i#HcMLl^b+^~Ggm z0tC-k1AYCa$jMv72MUN7vDIepB!+35Z*Z@^H+PFNUL&@8E3)`p@{FXER4~HZC&_Mi zHuBNDQ7^~-!qiV(U(`2A_I509U&?JM7tcQ4H`WGH@IzW#tUJ3D)t^Z`4} zKTF`krb8wEjk83}>xs0tV1mu_qH!mPo;!Ly7Je9cLI3@YpI+i6i2b{#)3KgtXh0Rd0Y-cBD^tl`$TN+PkmNGMc!GomfgtKKI`K{ek7c zLpb%aeybGNL!#>l&u>^Bd?fb0_~_Fc|jF6ao7+gU}^ ztp4S5_Soynb5@@#v5plZ}-XyK(BpXPbD}V-43aDV) z9tnuU_pOBC4}BO}eGa;J-G^|kutx6c{^kvR8Q?<;b=qdY~ZgC zfOp*shS3;C2x;#Nt|@3l42LqS(oRiH5g36S!+9u;ty$G1iwLdr-23W##k^k$pRzjH z6w6K@*l#7uyd)4_2AI{v>QXsFXsEA`&wUf6n67qp(=CQO=X2O^E_zH6vTa50xf}Mf zmBUlBg0~sPCOEd=0{n5&&wBx(;{R=mA3*c-bCb8{XY91RO^OfxpVOaNt#Q;4sfa#C5CLPn80R@#>8BZhtH9 z3^VX?sXV-Hm#yPMSZVgDtPhY-=AhQ&lD@>ab_KXcU0~un4gOdCmNaJrBt|U}PSb~W zP0ZXA5jL|A$+fJ)Wk9If`Ny}&7WRQ{PK3^rFzF&H&O|O{&9c%ykl-(A)xX6}jj07u z^ha2UeSG(PtFr*4rut79xc;Sf_4g+d3lY>jq_fqK{`ox&BHe*U^6{{al(G!O3IlqN zcHBS{LT*xmV!4l?uV{f`j79lpSOYhJIba%<)zqe|$)EsPF$5%h7kT`T(~0zkTfUvD zS0FNgj?%@G4lbvKbn}7#jsh!eZtk7U+dpJO|9;wmQh2Pn?UR-3|B%Ikz0n0#JpLnl z^q-I&q1MESJ;09n5cFg`6J^uPQg}O*RZ|1+3s4B=gY?5~aq-6k(miQHD2=w*!u@V7i_;4?XCjsxe{p!5OE+3gJ z2Oa7Kv52Bk3QSVt=qS`QG3Pq1z5Rpn^C4^@VIeOIz5b8r<`=gws0SD5>cnHUOw1r$Qqk^o0y>6YTsPVEuDC-=ZJO|OiN zeBQI3UM0std7Z0u_HW(SzmK{JYZePOJMVP)YJW2#d@u7E68$`ogYJ^H94u-_6SYeL zPFzzzOpf7hwA<<{psQ$G9dgh%1#;(^nQcZUCJr?DE1+jk@66N|K$rl~D(~r)Q6gj} zfTf+UH-%wPGE!2<($s|_e&X`-2z1!o;qIp*-31&l1IS9Qi#}snH(T1QRYeOaTuw7xC;E+YH&z3 z^`8U%jJkz|g-$63n;qm4vJnney81wV5{ zRYx7(^!PZUsmayPG#DE`-^E(=8QW$2mEmBX#XApR)Sm^`<~$HJDA5OhUkG&jMaH<= zpl5WpP^${tqq(iE5OnoEK!}DmCQ2+p`PcJ~hv}Jtprb`2NS5>>qI^`Jq?yivK6Oto z46D(0N$1gCxX_SMvE$4KICmzq7me%a-lBtq)3m73V{vC}KipXTeE%3dX*>fPTcIeG zTPMu82Z*gTdc4C(EWsG1I#^*kzwJ#|&;W=i&v@+3d`ec@D*#3!8-T`ru+e@8U$fz~ zMNt)LZHLV}(~|7w%betvk=#{ zq;24Gx#iOjbk1j;c3e)UN_4}r0X51V+@EbfZ$gKJNo7#*RFdipTI6>N?3*; zss*j0`EwkPPs8a9n6g&ZD3kM;#H9v-olC^L9d;jNK@v=3jO3xVQoAS?10w@k} zH{|r~`R(5;2?H2VapvD zVdk8%7QV`3H?7p8-4HYJawi>Qe40g(eYWzzv1QAb%U7_%;-`9v5WDz~h4#t=FZ`lA zH1PgU(a^uYr9cNR?P`F(_a2XiY-v85Tqsr;*u;KtU0*B)RjA_tL=1E}SICJMT05zT z+H-&}ly9k#PMS=Z6nhfz%7hGqwjZT4HvBf0=LUMdmH*H}NHY!QKo8iqiX`)tPc^{? zvf5i%VZb=i4Km%kMHvL-Tj0_$dEWjQH^*qKlpJ41Z-%f1a6831tsvE-k?vZf93-4?54JTWDDFd7wnl4@mD!0a3{uT(a&QeMuJ} zH8J1WT4(Le+1=S304kGt^Xao>Ssg3Nj{1SuR}AfYO;=_m{MIIJ|J5Ap!r6&@Zl zgT=Xg^iLPzVitc0_2#YEp0lLeJ-9VM&moPXKY6v_#y@uPr?cC}1@E+b_3Poi8+?k; zkxSq()%CJ^y{YGf$M?1+2-m3BkNy|Q<>^w8MR7)b;i*SIvOmX(dG&;Vo&}K=U z-70&V;+p1%^2ZiMxJR#nIV`Xmx!K&*WbKYoUh>o4s@_>GtazmnHvr_3dSIrDrqbMmkmNWAZ*8l4!txW9P*Yo*gI5qRi#w&JCnq;5y%ByB4B_ekG;c{% zlb&_Z_?)=|)N`EIMA7S_4QUh25F`&y=p)=w;UFn7qnXt-&|9HR8CR`P`mH3ju>aZx zbd~T#hE71Wdc#?lv?+=%Qb0=9pB}Oiqe+JGT-+#AXBkGRghZ3e1SC^oP?*=p*v5e` z7Er8Ex`NG~B6s)j-n)o}(;-W}k;~&I^BnVX5!`7>N$bWlX(XRbITdcbXIrsw6d2%! zJ`6kj@Yfs4C`XPJ_D)97>kwLc3P$dA@&%~xfkzPWKDQ%-xGK1KgDkw@JEYM3jHVuN z;moTa;9GP-jP1a;F&RfUw6!VkTbX()PRE3D`y?X!0X`r@<`R->cGa{skqeFUGeo_yHbXF0m9QdPV;3!xHW1smj zenrOgzll~6Wlo*i9%J*c)=dC^9wc$SWxUw@?Y$HAK zEg#O*#{#pyFO2W&q{ts~@c+2HUj1ZXwEQs0WH% zXcO{29CXB$1VbEWa><0?T5^tW#l@^Q3qG$IyAXw)pst;5Wjptv){7Cy6C71}b0iXA z#t@WuBdky4H|5uaLll;iB^WRVN3TlHIK?D>_G2ty*dmtwen@_2IZ2>+qT|DxTXf+V ziME&<_ca_7v$8%YCDfY|6b?dj%Ax?GZ#^K$XO#ouTD$;r@R2}2yK^Gz6{IW)pbOe2`=GY#F!>UIb+I! zMzG87ahhUXAf!CPIK4IK>TXGOXttcl)gdbs4?ok0s)=wTN zmYI_&s8+a_hokjFA?K}8*9XxXpmC`>B-(BK1!B4Yr86Bi>SVgM-*)UPu?`7U>*N}? zaiX0U)l^kq!MJz(HX_gjfnE`?{(P*UL;FA0BA*PaJd72FlQsEd|2;SWA@@g5R{Es9 zF~m7U*jkmR;MPB`z|Ww>tK>xT49efZeTR{efCY&dEYSQ|L7@Nf>g|VHa{{~TfpZnR zI~Kefp&QAW{qycW_z-<-I`B2?U77CsNDQbR8Xav3a`i=U`DKFMwv!-sK{}GRi$z%{ z&af@2U6b~^`9MKFi3~T*<@sUDTSqG=A8=U=8X-i}2+ddl2u-St3Dbl@46}(;2S7-` zj&+Cn9q>@h!RX#o$GX=Ghvb#akzAXMQ~v5nv`q>tD()QzWU@!hQlB+}-qX8DNjc5R3uowVbWqT7 zhq0%(MV-4<4PV_vnFR7L`5vKQr_O2u{<7I%MH%a6BtsXA8G~3qP)SO@i)d(pYG`M@ z&7&WLw?3cHhV==OINiRjWLHDjJ?TiQvH03U0CA8*)(w=2j1(pWCz3Iupldedy3B@V zC7o`P9>)(v{meGTXIphW!}C)`cxi`s;?M^tYgp~To0o|AB9+ z_FGD0vm-nqn$~q>iEXXRTe~$>J4DH6ZJ^drDk#r*fW3tC;lqdBDT)_<45PLSJs<5m zuqbRhrq6DiNl%)f%=C?;wEsFbHhVrx%i5l06+DHcD?7APfj`2zEbSw0ZJs*ZmtIlN zKCv&d#=L4Zl z7BB+#;jxm+E0_jIpb5SZ?b?x1G7UyDNc8MU{9+t?qNw7@SU+0bQ)sf2oMyM>aT#qWKmv-x-XSAg#R(iR5U%a2oZKgDH$Z#p1|a6{xNW zY?Eo_wG1nr6eGJ`cEYscDt_gp(;5<^qWq%_K|{e_060-{AsgsL0xA%uk~PMqKuel* z#6KpiblhcGXblnl<%B2mVWH!@LK~g6&kYn=kE$K1h9xdFZI0R#@_0ETqVUs_ap9Dt zp6yf}D{+aa!$*Eu^@69BAO|GyLv&fGLRJ8Dd*@)n{oVzj=#j<2X5VoA45c8BhdP}l z_H!nnmX;IVedH$}%SQ+^?<8P_K|bG)b?A%^#^iZ;_zdPrp7}tx`RKM9P}fsBe)dvU zRvu?mH*$T*RHoeLPRhs)fvGu=!)2%gt=t^Y%Q@UQV99q4k~qbYv(@+kHJ@<=fBzZVKbT<5tZm6UcK55nC(Gv=BSdj8vc~ zBtyJJ0?%rWaa+ViyVnuKCaa^dDCT|ydThm|gR8dXc#J`%5KHm1bi11pd&-L$1Ec6S zcBM;`5Mx=hs>Mv~0LPh0U0q!UV+-W_Wb6JcQKK1{Kx{4y>SM8uA(s}$+X_7wIJW1Y z|Fj?Sf+OTt=jEeKr$nPYrgHuIjiA(aE9BB%w|WIa8^v|p@6~J@%Bq;RN*1*W`}cTS zEru1FJyg^FRVwqFwu3L3RqtRp-<DK>1NLx6GtWB=FCiAV%-zRJQIPk3!@e@+O1uh^?^2He-_UEw=lnm zBn;E7vNsM5b!MWx)ylAryLHEWZUF)~;*(l8NFQQLNJ`Q*E8&Wa5Lmie3fpbUPmYA? z1z2}+c4~J?EIY|AQ#gEbN+Oh-4CgNI23hHk()gb)qi5tQt4+J+dS(<)2MP-d7npQ0 zk~60~UA&qYK}x;!IztqY50Ds3+aAVf-1~6jP~S4tQc6pdCn23uMeozF7OlgsokAn{4MIGjkp;;RzgN zHm$N=^B)jEmQc4K(a-hrwoKc@&Tqd#K4!nY(j!{%G+!HSC4Zj$Dy}<-V!vrD`1Igq z+bfQS_rOq>#L66hl7}C()iO%_ytN2M8*?B~%Xk;S*fj_Ox&?RY2owbok@s)C<<>8p zIxDW?>L7*a)sQE<2hZ7@F}weZA1A|AN>J7=h-Ew8POcZ91LepBdcD1sUt>myLLEnJ z@87q``A{h5$aM_Ih27_ucN&n0DZpm8bGt6EwQ!$MezM*TSC*7GxjC^-Kq*8ITwQm9 zBsuxHWLX+-NEDKJ5rZw&cJZM(a9B)MpC+)HG9+Z0~FB)3wSxv@)$E$uGh;$3teuIU=p1yG_K3 zE2Ox_ThbviN>~PM*M8WBNR-)Smao1hJZtP;>w7%pU^Kl{m=5M^9I6R|^>XP0fdsD+ z))>~JxYH74i4vS8$AvV&-B(PUghD^Ui?%ioElxDHwjRyUIl9N#AgOIZv8TmWkIO1_ zEydP^J;ai(GGjq=BGRDJ6D#DAkb+%7$;n$I$8c{e)d{zq$7NCy7ryb-G2EL&S!xi za1bP@a^z}v30#>G<9YoWFE}{3NbU)v>!i;k&kHdaKA;)SC)`SY=dW_)oq8MHp2LRp za5|4+xmo+X{VJq=;yFeHMUQ^&zt<4NXG4PYx$a}3JEuvfFG}j!L!MuPl7|T4?+{fh zy1a|>ZvlTNWfvE>P}a77!RlY~T)GWyN-0MOwr@!zFlt z403NlHs++g)j=~;@LW|$0zO%FX8)3|NDIynH8(f2@bQH+vaig2iJx?|z5k$E<}|07 z)r};mFr62sqKq#-eMOX^#?g9M_=h=YIfRdcn5AH z=L4I_6W{q4dn@QhvH*+m^=r}T&m0^aLp07I)MX7D_Je0+x3CGgr;_61Ytdfvy}AvQ z4*nh}XHIS}pcU$eO49_U0{m$e+GBBNj;rX!*n>Tr02j&#g=|ly@K@43-|^Z&s;G|W z|FS&A77$6p(I$h4xy!$qtzZE8ZJwq<@_b42az&cBV|s%(gvm zr{!2$zCI!4>6JQr`Ws*P_?GAofi z`n7B_bskPfc?P+t-=6*W3D@|XK#L+-{*6!Da}EDMms z&wjtJ|Mk6z0R-~G_k`P?OOJ)~1v;@L@&A9h_U=3u&i`Mo-&u|Sr%o3JfI^UQRt5ax z?)F=?|5zA7p%@5}q)9*yh~4WyFC$+)lR$1b)Pw&gH{4egt}?&G^1i;hm>P1!SO| zx4Y`=QtaAiC*oJu65qMD&oMj&%Zsyaa>{ejn^|iC9$@>fp`rSX8(w1*6Y5%8S{=i| z$NAO%_2)j7Be>>*R{XS#n~{*9ZU!+zf%T}!kB1oq)sqc`)kaB=mAz?DFP0?hJokMB zci27mBe}0}bjl=HojVWVIxA)#!|pFIH-$zP!8hMuJm`PD3yjBokCr>044WJaF;kn1 zT`*_P*j^@@QrFP93w;sxq3^M5_Fd%V(^2H}7dkH0<6wnR2&V0G-N~;YtccOhfn6Dc z)+@wxUoquKjlJl=zg`QXn*W_FuxVzt85r9mi9m ziCOR?H@iqE%dnO+>GMo_Gq%%!?MPqX>6^-G%60YDtgWq=O;y8m`RrP=ZaK6RoK3&1 zK}63K;kk%?*;%8^F&k!aRDmNb6+4cAeNoAa21PRQFy{2WBYqEgSc|5Eu=E#MSn{DT zd>g>vLx)gRL9g~FXa6;7)7S+B#@t{w?}uYS{hK3sh^-)SrZ4l;|$TOqX0>bG!X z!(&a^)n!&h^!%CB{!q_2&x-RgUYtY)m!5;;1*%2)l>6QQ8_!G7l*eU`tJB5Yp|-J(OsXEa15mN`!_2 z$`9KKpzGL;L8pF>`PUCgE%(?HoBc^i@WUE5_3HCF^>5E+Y%K{pCW3?{pFw}L`wKmu z5n^^#frm(u{*XFI*^r$$0bSE-Ho(&^#AY$=jSjq?AUjGA$4_Y`0SsmN)O<&R-&N3- z{V(R)>l8j7Nf+1R&R04F8BZeA>C9eVSO_WxFVRxC zFCP8+h+M)<1Up10r}|Ck89>XJ ze~7tJh4s-aBk{)b+XD@1(ab8C22C)S$Q(z=_pVDR!SgVXY34&|FSbh5_iOR-x4VUh z$AD5ivC~Jqlb>B{wpNr*ri2}d37hJtuleRrP?5%V6qm6oV#z9-MeF3J8xiImubh;h znZA4xqC2wN2kq)R=KXnKqLZkG_PxD{D#SoU+G>0?@-)O-@b@GaX&TlaxdPw1^mC9dbAbTUzqx-#V%R&V zmJQn6<}#xpBlDIcdc(mqyfbP1OxlxIX~h`VepoDBc#pl(4$4 zuI@sm$7{skU-WXq@v!GL$Ky?Ng(TwvI+iUm*O#frui|1#u(9&q7HncgZ}`7{cp zEi=#_Dga67A1t)I^H7Q}rfRF5No~NaZURQ67tqAx5{o<2Dit{alzbapskR%So|uc+ z-}H~8&;gWwLy?cnJRvY(F3Ooue;5+G1E95hGA89BH)P65^H!fq*YhEnh9YPqPSD3; z9XJ?vlh2t|smo-;HD%hl{$5WurVV;F=AS(7FP~=wkx4tB*Dqe^wGR&}bn#@J*=tyS z8&!DOk}Y7fpHHAsr)qucPeIOy;`kP?G1Id;;exfpIXAK3HxWbBa;;%UgGPiV?8UCS znLrxUsdl&*rEpDK?&WeYGil5|L`jXwFz>5R^on4AdOuO)b8J{d^jWV(l5DgEhheMj zX-%iGkjLg{MCZ*xE^*`miP_fL;y1C0wrEQP=BNn+35lpDJ)}l!&DuM6xCX6mJ+!I; z9``#4#%cybEo`gEohTo-pknu602m2BE_V0j^_8iQ z7qYY(_yKRPLMAlwWO5aBfcwNRM3R;l-Gn$I7Fw1cRf9tGWv1q-)-5I!_kGG=2NygyizdV3D<+#y7U|<>!JpgEOg3|MGzSc-60to*!Rm8|C{rXBabj^5u9I@FE zNFo5MoeIF(G;;4e22CIP7kU>4=qkTunnjz0Oq4z`qQwK{Q^b;{gU# ztWE>q3`SY*pTkKeu+rg#I2T?pV;K!eXX|+@0@i+c(blG2m|VD90N-K2)~e`ZgDB>)P?*DBs1^>hL$B{S$- z6P(p?v;Ygo>A0X%SO#qAtKdY0H{$roW)jisb(@86a0yx(dE;fHs^`EX z=0O*)PTHjcF0P?rq}|JKbfZYs3H0U1KV6&y%(j(`#0Bp41Z`2{#~dsNP%SSeh&`=kZ(*|!j8uroocyN|=(t%~ z+7wN|uFj?ccUI{Hb-O%9;juRvB=W3hVyA&Mm@dTY(cRVgW3fsFZfPqBc5Db{bAmkh zpox?Z8sx(=JY%Fx3=F=^fl@f#=N$LIX{t- zuDb6DybilOa#-~DRKxaFWq$Y1UKwO+R@8hH)uM=_LtmV97G`e0YEvgY{^!aWUqHH# zO&v6-IJ#BLD*3_rp9tBPGadbsj;(p8EkVBVl`cWXkRUpn4yy0eJ|86l%> z-Xh7aM-NYXQ@}W;Lzf{Sv{>lqY5*X_ySreq0e3VToZx$DF7y7*JZX1#_xRx~-5N7s z*s$0Ejd;$7PG5|hEPj*@Z?{Idt*RFKr6?weV0wh+72P^jq;C`gi}%Ez?lT;IfI-i6U#|%mwO@_|XO~`m1Xa>45}L;xxnKD-UgzUe%k@ ziTG!UzbJ4&?u$vQ<pFwCF0ZEJq%}2Erg+8RdYp7%FOgnNX|Y~4LPJ<@~DPwcmBbk*s$I=wt~80 z6{;|&@hyJSjz(rSzM7os(y(hTFY}E**28Q)Gr)%3QjF|EQ;HmC7DGcqRORJ^@&V{q z@(n-Tv^`chW*5L#2fkl@)r2?9{`GFzX#u>-&Id2d_eA?%{Up#;%9HkiK`J(_u^?pR zDOT8z_QG+d4+xq7u8-9=e0W)8wvBGUgf@y=+-@^4A1<8Nef+kv_3>~d0YP%MY2~S! z;Pvkl2+;L_=IF^n4D};yu5#ygfqTRehPR`%*N~(9NHY@La%&$iwt!Y8*gL$CM40{`US8k zF8+$G`!$FzP{Hy*8Mp=Y&42Ty^n7J&kzr>Xbdsjjz@&~yst1Z++HV*9c&Y3ig3_M^ zoqXkrg+*~ly-S+nxE=kTg9lg}q{K??!i%G$<-V@Zw@`Ut$ZH119<==<9teDZ8}vx5 zSD2D?S&n@aaOs&d(PpT`lI;e9*jhCzp5wzp#>OciwO9MeW7n-viA+kVsdo6w&!yUR zmEoN_=Q8=mXY1CXM6$P2J(=2f`#|6P_$v<>+n{Smu%wh{Pl4)6&|9?hxzZtUraDQH z_ODMP&a?orUmcofY+5dHT7MBL{05NlY-Ea|Ba=0X4P87#4a1WFY3&BA*a;ra{hw;z zhy3H8Mw3WL8-L~QOf^;*-50>GMe$_wh~U z9uY|;Lzyx~GK5SG<}oCdsVFkfnMvxY44LPl2q9#iwxP*P2$_|6&ae%eZU5HI^Sqx& zpU?Xq@Ao)Vv?r*Vel@>Cu4mw@o7h0&G=B9^B0D=L5<%;5c_F#NU3)BNSy6cO;ur zY;vSLa{2-A5%_N8)j)R4Fdf!7schPFOCqyTe-^0OjBgbjKwj4;y|YBcm-f$d|DVDB z?E-o@M&;=g)U^mX3J&y%-^wgZt8{ zXec*hlcigC=Kkp7$-CmL9v?LnJS!O#GElUa1G@fsH9j>WG!P{otBartV216j_jj%; zLH3akB*cD1_6&ot1<-cY3+1zOK@tnLq&P%<2{OF9F<>}gW(SJ*J`k6Wc2k`Ysz)^P zS~ZtsW1tGD^JMwq`JI{v71oTLWtq2fXSfl5d)Bq{FxILcR3rMfqrm-k(NT6Bz_N^k z+eLAXenq*%s+W#vPEUG1%aa_vbhQMP9`!^-6W4=ol-K#H`I)W=5f}h{kr%}BE$Wco z2T88o0QMw+SkX8TtQ153Trr!@EkY%|orfe13$bpDVS@{4an|`fIi(*cJ5%JTwEUw6 zo%>r>Wjhf2j3BML^t9w4LW!M7*jz#A_Fx$FpL*kF4V{6QOq|%cGiv%<0r$Vd5WH8u zPuNDNYAng_%OAqIdk`Eu?l^erBh#_B&-rduM?1_}`gz5O{wSCT$wo96z; z)w^mHr6F_^#2`@-Jq>V@=PNFVd+ooyw8cmxip3L}KbffW5N$_%$Xhr4PGWy011&1> zE0nkWm97pZLY}3+fH>O=l1nDNv}Zt&DyI%2WNcTZlSy=)INlGn`atFlf@7WspI-d- zbFdn}!E^A6c8LLw4uoESYj6Gfba2jW69#h5d|)+TUVL9}hn9+fZq=2tx%{Tv^g7I% zbfGs?dq5=YoCh-S@*MSxOOM}j2logie&9IesibpN>zFw}#bnv4_au5V9<>1bh~c>M zaOrD}aJ-o9ScrTdls2rgjJXa_I7aB(%%=;w*x)Jdb3H5snx{=jmUc?bSGZ0_z5g-= z*OVza8vfK9c%hd!j)r{P(X=$ZNqzstq1p{mWufiRums~a99J8KLkS7Ax5{EcCG^Qt zETigJIE8?h{_oZQUk3o>q?J%9o}GJTdl_Q7gobBy^4AyKo{oz{k`I4Lw@AWpwlt+| zgNIjTPx$L=^O*oGuNY+HWwu{lp1OQHf*Q|a@G=$1OpuYzeNi;Qb0$7~Eg=$E29N`y ze)oQuWsL)TcK-E?v-tpT#bnlIJb%`6HzAY%?^w0)GLfD&BSR*qM>2#&+e-0gAKia`(S_ z+DSM^h>et*T0|lr&wcl%>!-5#NmWDk$=^t=xnM$C=TUn;kIts)MBBQ)nO=5x+SMn4 z(vocy_UCy4vL}cZbC4=R=+XQGY$#ggmzaG)39JSX?xaGz3M#F#azLm5YcY`Q-fEb# zmOh=CtVBI`bEOm3wlje;Fb($ygdVU0$YN%zyxxCCBbkDMg7#BEAc>BE36P~1PFDJ; z3T_3v`kWI7N*~uY-|3`SCc2+r-)EdwDHoRHbYwizcU-{8N7$m9H%CjsSwdf0(ngy= zPDeXd)P|{NC)Bg*lkmfn2}hi-89hK0`me7Z1aXt$KwIyHC+P?GmCXNFS_ogmTmv=O zXZ<5Sy_M`HJ?cE~b*0JM*uIy~y)?#)nOl%eG~TDBsy1`k`lGqf!Yj@q(4m;b=+ciZ zZIC796oEO#p!{q1!`xdP*YK~7LQ$(XNUEW&ePo?J1Y4K!;O08*MnB|(xB}tWRF|A zg5!Ju`Tl;}KMS~h;mMbTJ()THKupt9ab<-AXFXCs6=t8kwc##lHCKO|VL+_Yz5wn= z#Ae83w=RE=usr!k*-%#(kyWQx+u2#)~^K&Q_&ZW!W4(=L;~IBkA3Z zC20hF7KUmmzo3A;<{MG;{!AJa_lPIPR5bKIb&Oye3(dpa=LRcWY`+ps0B6nTs_uWc zRxB;VM|?DEqw;Mh-ed@wWQqFEeR#&ch7sg@hwFZK`3Y_%`nE+#l5t@E#~)ED1-3h% zkDk3f@`xWSlom9*3^Pz#TRnb~zu`LC$hG|$W`>fx#e>qie*GShF4N}ee9Qs%v>mxH ziI}7y;NUEJFaGGp-|G0C<-c$7{!!GjFcKem#6^V&csdNee&`1w?UKS&J#n&@NyS9 z)%ErxbaZ9&gO84EKY&ukC>%_?NGB`=!wy&ds5_?~E7TBp{=v75*nqm?-(v!}gK?1E z3WF!LGWS+VtB&vHXMV54Coi;$`I|R3l|;VpdP*wv-|Yk(*8IuI$}yJ&ei&YTbB{s! z(%N*sz57C^;FgDZeYee5Np@j}`c@H(Yd}13Zq744P+)0Pr@~XOGfrPHmu-uQvfa2^ z8;u;Xnf$=uboxP0C?M=`-(vrd_dSAigfDT>`m~c#yo1KswQF~4 z35Y`Jkpfa#1U0H-jgTgw4DUyjPoxAu{yw^GO0C6KWC9>F(qmqyQjP%{{vVA zN8H-6GavYOUeP_))S;K;9{CBIA@6S>`0>@T+?f}b1YgkeiwsJ1LS|zzQ2HL|9lw;H zko=hfT$BUP&i?jnG#rF=?qg^0X+J|zn?Vsk{|KS{GTe?Z(x!?0-@Mh|{`cR1l>u?Z z?MiNbx79Q!o9FZ%nn^cWl5S}}{(Lb1%-m~cVaXiB>Q)`E_R0mjr4RhTr4F$wJbRrL z4zNFeKfr{Mw0bN{5hcgEd07C#9ogm}lDz|$1Q-K8o%vyGa`I`lENfLqUTwiYif07s6j zQ)rhEDy6;gBjz3~J^QiT69FFtut-qLqDhg;JeuP5U??RH9_YW9<=>Sue;;>TG{3m3 zr!;GidfH_%Vc2shDyQnQu%QVF^O;p_E8{uf>E>8_jAVb1Nw!C5FHzb=MnbO%`F38u zpnuYy5;V(4|Q4 zzX6#`NM(BaEk(`4l+4B#vGji~eK>1?`f_VheCfaaaVRjR`t|f?<;>ZeY34QwnIFET z9`TAU{;%{`#?hjbDSM|q! z+XNj1P44)19mP>f|KCRsvm0>lC%Q3Xmiu0DU$;HjV{U5290H^;Sr1^b!@Xtm43FKeWgz9Dp%Tn#Vj{|guWA+(e}rCeeDEu5z! zT=ePxAD62f=&yj)TII3+_najb>chuioOaw<9-e~NuTNWmZK;XADkqHnIehF6W~R$` zGq%~}vCT0Gb037~Vu!fUg)M=f+P<5CHwW&+nEd}zC;j7T-2b0g{?pbY_k#F1%+}Li zBtri$$C>pNv$_GJSN8pDhjxwo0VUMESzRtQ;*_KJxy-Tr_64+nrI;Sf%q$mq3E^lw+8@NRE4ulG1o)p!8F ze%-*p8fNeoLx1!O#ze2!GR6~t=SXmE0g&lW3kLDsQowSUaM&ASeZ>in2adkI$k%0(Z~9L4$S&@%5(;$XzyGaKot*a9BCu;6_96GbR1EoY z=UpA7wF1B(t=_vGiX6we@9l{1ToY}~*EL80tiwQg`yEp3<2@6)Fu^Ynnsv~C9}kk~ zmfKme0IMmW+`Vp81t`E0k^rPUr_Xzv&&snKq&k#Xum|QF4-MhnG<)6nlzVzUBFP!7 zP^S1hr6|z{-|E4u;^wsY(cSYUHN9qS$1Njk!W*qCPz=bywClOii!&y}E_GrT2jLTa z3u!VMW|O7xb6;QixvNKC=bV@LuI-UH%a9`%_ROp5R!YMAbI8`p$Ru;*KHc%{z&Lb_ zH%0YBn}v6%O$yx3EO@|+eP;0$MB+0&I%X{=b=GK7@3g3 z=y}1~;8kpH6}Ay-fg=#;%#}OD{seE)pcn2J^IaR;mrOyX2cXmoOSX+Mra| zcDYH{{h2}NUEZmKyGuFqZg*`Cj(Ve+VQw65THQOdq=$!&G;(fhL3=Ll9I`xE4vo$p zS)CNAxx9}EX~eNBd$xa5$K@hs9>db!=8`2L+P(V}vLWAi89&squ8VzZlUw~hs3a5ftSZ?0%%pw`T|N4J$dJkjvz@z6$&N~K=qNc>0!=5R#(o%TKdR~D2jBO-m6*npQQO~4 zC(NMC{te%);^xN2#`t9JJJA1;$l*Vd$v*}w23Ufp>pk0(fN4uouwmW4f0g3Ifk&w& zG+AAu47?qr0AkPdI57Z*fk-E*tU3;w+TR4vpU;}R)%zT~hP~B$?n?o0`+ED^i;FWu zi(ee(b~PBU|FvLOl+W!~`mwyc_SdtP{q|7JC-(zi;r*L>B=A>Y;cyBJ!=Z%QrC(yD zqq}@Fv&(iA21{&)De6>-qbb-xa7{pT;_=?fh2t@=PgOC=C9MD(Y#yFkmlwkTQP(qj zrEKl})UUQg4<#+536AMFcHx6}Ify@B@E^Kp9OgO9cA4Om-GKUjwK6ox8(o-BJS{^N@Duxgjr9^-4n(4+3YW z2ig0NGU|-?e?{L$D>|QNlb3R!UiLir?h-r1EIN^A>wbn28a*Z5NZ&j#WQth<$K32j zdd{St+8vtSKxq7UYmDhGFuf;kGe1X^u*7CGo5ktSw2N)MIvhzi`26|vIl#`}LsJnE zh^zv^k+((`XlPIPtcpqGQ=1~)Jp}1KIReclZrq1TXnDqE-ple_ zZs3F_r;O-4?)l`RzYdyttZp(LW$?w95EQYLeaPm$D@4-!PbD1B!=>{gvx>7@Qq+pI`kFJy4d^ zccI(=ApH}>oK|BaIMkQ9jVtj*>4UCJjSb1_EpqRdj1FM{u4sUn%B3GvjF;7=Hck9@ zfS+{`F)n>&Tly(5CMk(od^}w1(hq4GQtX41Hr3D>u{BD#2Q7gZjg61v^%vgVETTZ1 z7|D?aigUmJM{c^}x0b&6ZQw>G)k`6U%oKy};0@mm@C;Y}*=+(RGia>CB})2#@Qtcp z`@!-;BJme#bx2k0pKGpgs$Yg*hG(FkVa2fX@}dw>`btzc{4ig^8H$F&dt|QL-{vue zf3>WjK%yvZZdOmyt}~Qx67h%OZiWtZrxv_hJGCKIN}GP})uCD2QbLv02cmey=N&!t zl;^W{c~xpE+qZOe<{o)`k~|;Q$#!|H;nlAat|uRiZc$xq3r}0FukBxeIKKEk$WB3f6IMBB*yBTKp4BB43w!YKBAc{SQ^|USh`CtmX z(5QfN=(K>jzNm~&>oGv{uN$;ss;;eI%jS#wZl0@5dex8 ztk6%vAH@+rh!~e1n5~R?Xvkl=(~cipm%?YyRd4liY!i!z;Jcsllt27s8xR{_hF+2CNM%yO~ ze=wlYKki6zV5P*dc*6}B>cyo`D_%X)XFHK~sw8aB^&9dO9>R%~ugl@zDUG8g+v_45 z-vbS3R&akf{-y=d*o=GlNcY4IN@0{%FKMw`;}q3L1BENh6!;0zYI1*`*ix!za3T!X z6mVnZPU0J(wZbo`26o|>fm=t3C=vok=OtoL%`h$NGWe=Ej80K?V_)_Tb04hP2tI%N z6?^ImnRox)u^UGgmP+t#L!LFts@cJK=2)`lWRK1~BBOXt3{&3Mp5Fm4k39M#hjRuk z@LXOPgTr*=jaT#NsdH~1sdz1P`0y1C&2Q4&$v*7(iw+C4`C<*$p)J0H4pOdYBNwgv zLt%qrG0o?fa=pQp>Vn0)qDXz+14e8(`}13H@lI@i%1J4YyqHin0KV4zu<7ZZc*@OP z0K|y+5oMn-uetTuv`q<~ByFzZ$m~a>#8IM}KaL61bgSF@IRe+KR{z4npLNbn4bXC6l#@6jArtY$}9oi%RTBlv%2_gAb$1E z{=wU0Q;Uj@2$A-Vb=}=_4PipX*^i|J0ym{MXOB0?hGIV&@)NIzr42Q6o;k3i5IdNj zAO>^>`PNLDsr+_1hTido&O4Q+JFDzy!>Km)KJ0Cp&`(<3J-!6vQe!~4vpJwYj{f7u z5tqjN!Hd>zKW{I7QI(!W(l0MxBgqV0FqzL1&(iOrGY0}R>Rn@U1n;`OHGu%)qR4tv zVKi$ePSV|3O$^KM5Jy?OFnT9JxckOO5wco{YZJ@Z4nw`&t}Af&I;;vudbj;Dr2e`h*5$!=s8k*;m(+ z6y>=R9$`j~-m?6Gn2ff9ULziI!wdT5j_;jb5j8i4eRX_YrA2Ol#Gp*tWGNLUR9K-G zMYo@QpvNM5T^!*$u=ad$Yw>_F2NOqD!Q>WgpUn#P*tB8V zqAVm_PpoUHOPb~mkDX9UkBE?#WXgr-4@IcM`La+dJ7+!>Ms}<&^fb`wYp_CVpw$K-mV=k7`eOM>amfB^xB#xezI)X!TGsk5#EeV5U7S%F& zOy73oiE1_?9_|lBEHBG^41De#PrVkg#a)6rR@Q!ety>&X+H5*iEw?iN}H+P}EbWZSowRBphV{4T?34sM}2H=^w}M zOg4BM69^1_sEGqE&e#5@;CVXMrVGsttNVuf94QK*I{R+TS<4S{lg_JayF(*-e>`Pg zXi=Y;v8rc4GH(KP*ztM3U+ASC`kV4ZhMrmdy=c2I`p2zx<^Fr|T&=iE z)yjR?i*M73iXN2t<8U;bHu*u-gBM$!9JR&L6oVr*zxz3ZJCV;8x`1V2P=4TH|za7d4TevqX;Qu(b-Ki!8 zCr_@6+Ld`kI8!X^3~l?hZcKIAOlH>H@*P5>RDu-1%bcZ`xl=eAj&P#nf>W-RT^S=^@>j6~cR%y9CExzrOQ2sBL#Njqe5BhMW{kSGkFr)e-PnSHXy}{eBYxq|M@DKaHd$)wjEvHd(&Kvct!QV#} z#Hl1#HQWO-P{&+pTHrPp>(2!D-I!}L)J6qJ8^)4T`h<88r6UJnPOaziF7vp?4mqR2 zm8xDDTY=7>LC$BA8eXVI&B6IgZID;=k<$>^F~$|lW^8ZhhN@Lx3&u)payYFl2Cwf% zvL&JnsxZ zl{M;lStkL6Y`S&Bz~FFRLyT}Ga)E-_3KUL9okignTmI&=E2)_GY*?58;RyZz$#Jbm zo;g+62lv5t-5`+y-Hdvl6q1XB{6?9_`0(4~06E(+Xv}wb;jmY;BfN^;B`pRt-Bl9Ao$Q^L z5!z9kU5?G*VHXuJubabKUoI~D_2Hny8r}9tkl7ex8+zJ84cs{^lq#I(k#o*?AY`Nk zf+W*GvsdKkDj1E&I7K2rc< zu~8}e{v6o)Xb86O0~@3Cr*?X(Jl#h{to!c{g7LI?e-#sWy?&X0X*s}I6Ak^eUROnZ z2j_ay-6+m8A~oGqg?Myc`($XSU56EjUV@uxFZGRbUIQ7;-P!UHacnOmC4A-Vn$4kg z4j&{h2<#_s7Bc%<^XI#6-+ZrEZW`Ua;Mv^**oE04@hO%SuxV=Kz3h4a_y!g7CSN0% zxqLUYdtGrh{Sqd*Kc;WM8;>gy78gd|p59RYGAT6h z94oEHRQp!P<{neQ(iW5NA4T-*g{btm4aLOsppe_Pyq3TB13|D0%Pu&N!!@CJ* zG+F;}UKr?INC&gYS6dCD%U0h>c0!&FprYe-sDoYo4HIbps0@~THbAK*3gm#O^xlH@Sg)LqgP$rO}m~} zW%rfXC81b(Dn!}Q;%)PVvp^#o^m6vo@vCrpy*z5zPI)E2-w^1oLvyLtLr-?kbm~9( zWIUs{;nR@^z~~#T5j-uTw?wT=2AyAxbE%(tX`$}=+RV05^t5%~Dp7FleYo#raWcr) z22scO`|)63o^Z41LGSRLGA1m@gRd?`CUIme z=#x!UnYz!?QFbSc$k^^UC?8I0%dcxkH-9DWs2tKP#|7CqDR)ysQ$|!l{&G~_AqihEJkCX)gebgtuv1-H(lSD6CI5kFZsA=Q zxmUZ#c|Y@icbvZ^tun(txQ1#5mgSg2N}fSHcc?zT#@smVmla&P4SOsK9pGx5c` zV|YHpjdd1ldsU5Rh@H}hoFu@ysOx&IeqY#VvS2c|+z zanSLvobKmA4Q381A4R10twmEi_xJIFOYUCh-6gZ4W==NEBVRZgp+Z`uP@&2|2 zDW~W28sHqyfD`z|`*y!YWRe3$V{U1nWmP<2R3Bj{yP;sl>wCo#lx%}gcPcLX)pPw-A2wQX$RqNA3I`?E0yYJx@l#0glz06}b{n-62 zhGL31gCsf}f+vMf$fL+QQ&G$BUqxtgi~Am^1v5#Wbd7C*_KD?WL+35W=QDq@u9OV9 zS>(RblQUR$A?lD1xKD>-o!*2~t@5tIff8xd#A8~uUmd5_--J|t%hYKSah%Q2xMlg? zA0dOs6=issSA|It$Q3L9%&hydTU8kO%jC(re-5Qv%r6h&bXQrfVAQcO(Pz%7H~(Cb zN+4kGr!#x^Ee}+KlW7 z3p>W=kM06c_4cjnk=7`1=w9Ess4?`9cQhJxtO4HD%ehwDJz6@0YFNmoT%EE`;vxU0 zC~8~wGLD5>X%fIl)0M7lz4P~>FXlA1lWE}4==2M+qRT7C*hEF zYCvWli9UKc2YFkc^W!V{48_g00z?rHEvMxm)~%^;Z^Kq*vU0@{iKeQ}(?g8hj1rbl zq`fxQZMTtlAxgbYR;8N`JaQc7owSsqu8R4!+i4hwSqj z32U78l$!=bnD9f5#+}dzO7J~EDh_#BsRIH7b{w7s?X-iMG|sVN5PY1ko1Z_9lfH0g z2~arm9v%qOhraBF=>X!;Za=Dvzhum;*%hwM27}Or=YB#dfNkNqIIYB!e05|DC^K*@ z2>L@X)%?cYK;ih5An`_$(K!&oI#*rP>6gCRMXI@i>&Fh?kEl+auhj3<7GDTWH@Kj)n05oBBGDsE@|rYv4=Va5ek(*|fh>2yrt;jv)lARv-z+VCJ7_lG zq&KH^1m1q+^$(}7jfzaffHtu24Zvy)A1Q>kNF9 z2>=n#Szk`?1x0UQzn%zZpq&(Aj;|6U_!*h1lnwF1PULOA6OwO@lAw=?Qr8Iqh$0cx zuV6KxR`bQ`i0HzfYeU2L*jfI?MH-h>xzV5iGpN$(Zzb74i2veAp)%!M8>3fByxy>zF{MFR zKk7}AoryIE7yk3eBp5LeHManb|I+!NLp7rIgEK)35ZH9TV9d=fMI#E%@Qj+qY|^lA z^u|5z9YKg!a@1L2pq=tf2#EEIK;}JJAaU$c>*O6NYLr&M?{qXCO+ZP=ecsCO zj{~Ip@TTpVy)=250+5Q8oaPT2zVMXym$H)dnJ!ns$@*%xfl`ICxeFEjl`dviwwl)g zu~S#v_4R>9pMxF8xh_yLOAVZa86%(?(bg`2f|x}2$6itJhp&Am=|SR}PxWWBc7q%X zHMfQu#@LKxcl{uA9{v|FK*SxldtC2*9|A@lIr{aW2B8smHkl8XM{C|L9*!bJP|T}0 zy3}cTCPOd${FAjABFbFYSD*|WiJ>DjI&BWt!h~em_K<7o7!bMAeg&Qda)7dm4nU*9 z0va(?D-bhcpe=Z;&Q1l6ux98EE-(1`@1A$mAAl_XUlQU|`@iQNP+BbIZ zor&5<$-4depwk-Nc)fYQ&k1$C#$Suej^g+j_CkM`KcIcf*T~PgsKt!VbnXRzmB4&| ziRkjwx~v~b%n;gLp6MAXTH(Y| zaRT|gC8EZ+Ol&9)gP8oIND!B?hc%`On+)RH%be@^sk2FofZ8LlIe6o@X-pca0F2V0 zv?rwKBh=OtK4z z{hi(W>YPeOP<=f*>`B^xRcc7hmLW^%MxcaJx%!G0rRAsQmH*p4Ae;L?kH|m%q*3Uz z2E?m0GbQKWzUQU--nM9*MsW=Heh}Py;{U#seLwvlWg}dSJ#itjkY#5*ejC?Te`D_x zePE+UX#)m#H~Jsf^4kUc>#y1t1oPgIW)+>iC%AviK(-s4!0f2B*SxSOm`OIS{a5nu zFZK-c-bZeRALrUnyK20)cadkRARQj|SW(rB6n*xaMDySO6qbX&z&+|4G(*tVd<|3P z-&Q?jZ<~lUp;lJV*nNI~`;PznuNrv6Ri@4qoOH135~9Q)~nw? zUgke+Q=^W|F0`1#u28=JDHA-r7eOcjP|<>7c8UlX_pi1l01-k3%F`A(1}hUaAQvF> ziXU$Ms(#jI_{{@fEIf?^kBSz^{tUwMRrc`j-HXeNsR5Cu3M2|ydO7vKXP(hMLzC^M zplr%t{{hzIsRc^QI-QJ_($_$7#UBA^*?-ESzdyQrTs6{GC zQl9pqjzG7H2A$_*GfxlIZdkVGlkEuH7bL=;?S(x}BVl3G1kBVE0r9^8=+TSyN^OlB z648j`PKaQmsN&@`qIZDJu?#y@ikA0k;` z*tB+nnzlJXqNmCLri~5#%)ni3Sr^GButA3QI)K4PpZ!aRd|>h2D`*iZc!G?s5rgAL z`MNO-GKJRkh6E(4+4%E*$Rg5GaTD zphF=7I`FyRDRh&47}$@DI(BeuD?(g-lu)W@J-|pZwKoEhC?vQ)&ux4Yr_!xEm10P z+_rGUS>C~0!Qh+XW?0Lx&!;S!rA$WT$umP0d4cISb0Ta#vwrIP`@1b*f)iF?K`wPt z+|jJH(jJ$LV~2CUhlXu%-#aT4LpDWxhCqOhSPrFPPFhoF+1sJOnSUuPJZ0dFg2Ywf zU-B)G_2mW%MFQBGR9rg)Vr2oq2t*LqDn`927zUzzM1$5TzHpPPWd74E;DNy^#YEPX z09J)G>0%z~=zG~!b9Q{iZ;S@_$C+pKWpf87Ik|3l=E4-Vt+DisRT$u$gA893T)*o@LZ}zzK%#hue)n>PZ_9|2LYtLo0yto~Y^T(RPD;8t7U3nbuYHNxZ&dt^ zn!qaeBJksyK?nc9f$xA;SB`#v)q2VKry=#8FYhP1eyMlkap-V_1M!tXM*MX{PbUYs zxBgoG>-WUy#IHkPz6tP2GjJ2Ek`k9dGfVgS95hC#4@A;wH|oohut425JJ&4kG!u>3 zZBUxw2pdl*(=NbIc>0O#aD{qR9UCPaz*Kg1mLj3@l=< zf7aY&{%5cOI4YHh%%_3x5Cm&0R6sxgFQrt+!|n=~#eolY(&m>PfO*sc7DqSC%UVkz z+{|Z4Va28`v=4Yguu$MbT$83j?$vqSK{K1u>&oQ@m>Lml1xz=yjvJX~eBx?msUCAziK(@SF$?@L_kB z#%~v>s)00VUe(tkr|e6`QgMDqS$Dcq~^D&fJTtOyS%86ef<+QpVnf^2$=6+3p$3cnup@=OO@psQ_ zYlH?N_J=>Jjz=5^5ThgTsFGmyUWCA+`yzAf5w{Yg1)2D>;ai4?IRc}}6^hFXy$WK; zY|AvQbhUdR)Vv4k*WJno8Ip`9RYe87pR}pkS{iybUlmfzEZS$rx&ppJt_3h-+Rfdj zJ+3xR!}r2u^&i)G*1wSZkh2HGLrTa-xyPUV`$+MP1v#OLwH__1;K2bS=#TS58)&=E znK16$T{-I?rAdXa%3v^Nap#RUbb_&myK0z)z3X3|nm~+dyR1v-8TI)8PZ|AAM$ zXXHom&Bo1)l%V_rnf0t=Z#2sxFh=CF`JU`Be#vz^`Rn>v9kX{K!95t;SB+-;I-Aw#TFtZI% zQKVDU^Ixh>GFayMp3Pa-RTYI$^UY0~<%Zhww-CtRzXKp6>HHb-3?QM?b|v_HQRXdd zAZFPA;}gpBobk4gbVBk&w+v{uX@nKOUV~Hb@}i`il@{Y9Cl~$kjU~X8nvKnX3?3tF z5&0H6SFIjWV-%n4I8YotybGLw&M3WS+83`i0*R3qZ2;QRCgI1uF9!$wd72fgbU8L) zhoM`n&wF)bP4GdUW2SXaPC_qG25?z@>-qRLY5af(uuescQsIY0bd$#|!RX~^P=D4V z6}Pj5qQk2v8j5i$JKMzTj4IyWm%($SR|s4&z9ZEKe{`HFVl7smGg-=hfl3WG-gz%?)51 zOqM;c_34OSopi&LoM3)Pz(qc5d#Q=IvG+~(UfJ)zoVb_uu9$m+Eg{cC6%-u`Fa5_Z z2hAp#;5^28&5<$7R--G>_zT;3%l0{K7>@?W(<0UK>XSIv_VrNCnC)5rvMKB`chia| z^Y(1x7Tf0YElGry*9<;t##HR0U&p2e?3w&k6}@d9ZAP`}C8X1!*n@SG;M5FBmqiXI zIWMhc)!Nmma^sbigzEeR?2ObH22f2Q*uIsv{6!#er8cO)IS?`Ohil`@0aS>a6D+Oh zHF@GD#chZlX2p-j$MA{R*}4%o&HkqCOXJ!7jaeS}v2A?_o^y*CUOnRv1*h+C`QrCp zE?eR;ta{?|>6AdVSfRI}&xqQTsnJB9%JV?t-`wBoRaO? z&DGnj9`5D%EC&hDZDB$vxuAE9ug7svz#@h0*gH|;+3Jk7YlAF`TUBWi+$at;Tzuh< zYHU*KmhMxbb$N`Ji~ve*jmv5a!K%^21#mF*aekb7KPGHm6&fCfzhJ&hmwwW3dYxHo zC2CPB%91%9CtW&Rn)KPbQ&m*ho?ny0weJbhY4(`sc4XKqo>Zeb>C;&m@Z^?yP}Jf@a_cxp9NREMZ;8t0!gRg3 zanr|%`#-X)*Dn%qJmeU|pR`oghtzC`GL+ZJ#!`H_jqykQj>Ewu^52diBI4C@)!b1f z90s`6Q4YPPQN7+eA=gXVzt~Bzh*{Uo#Cy*i(Rpm0>{A$h!TMwDsECS~wal|o=hdPW zlO0G^7giUChwT`QFS+~}-T|o376conB_URWL0w|~rNOc;17E0Z%CcGU0|!0t!k>p2%TI|Abp{Tn&07!1 z=k>2BP=0EsoU$EyI7%t0(mD(ISUdn@Vw2l9tctqgvvSJ0yIp64oX1NEP(l3-gUae) z;1thbU0N%l7H{t?e{Z?i8w_5C?>HgkjSF#5SWX)*!f#dMSD5>%)K}a`+q@$ur$=i27&p~m;BK9ALFypoSx4Zt zUqpBb5gq*Jx2KnKN0OK)x4W#mbiEc=*S}HnIt)Cq*8l7tv8r@J9lVlk5`l-tJXob| z=#8D`+=}BLe?1vlWdQ!R2Kl4gO!bXB_7q!*Gly`q)0HD@ij8{3PJSQaf%@Y*&b#@t zT)&E^?xaINOA^E5ap{wbdxeqhfGl;TxW-Q8p}4Wd+wYjiZ3sE`Dyd9AneHCfzO;xm zNkLV2C8sk7mUjzA4RJ!Zq&jF8sfHJyukfXdh-9{}KQ$zr(qAThzpR>3$k6?*Wq6vW zA(At5Y)Rm^SK!G|kBHI}(~8B4DtdLy8PeQn#@J`h~;{Bd0;uPA~996WpjSmJAR8gld? z`BI-Ke7!Oz%#D&0cWJUGHzAJ`frO-Dz?0X#^^VJ@?fBJ3sjZ!%;mqzcb zihIA<$rmlRMj=Bm?|b5sr=ybT#6(w*)%GAJsMa*;@#FViTJuwebolTEKHE&Y)5(lM zBm5$CVI@!wUn#zfI}mE%;>gdBx~%_bQhi|2kLiq6Rj7yhwkR2x0iKjB^i0s=b4CXF7^XsZ)<- zR+WES1;=J>;xi(tM#|gd&f$yC23WedS{Hq@v(z+)wFZ-NqIAS6Sa~Lh^2^m#3kdEm z)EgS?u&HZe($Ze+x=Z-Ra{dDU7dI#WZ!X4RTS5{x30b*S;+Ax~2q82#oC);|C*N50 zDEB8`a~@&a)4Qb-7or6-2XFSrK&wjdYv`dflTvS9U1M^p_U}`EVKq!uT!1u9hMeYz z>2GUr>6_0Emu@On;O{I3%SD8t6!fNXyz7d`#5n9$B8uamx9Ij&7yKNWe7@ykeCXx} zD#4LRtn|_+TJn;d8#eJJrU9aG*E0r9&1))nvcIb?}}GnGFMM*H3u zXf{sQh2k2@XyS!%u}oZ1kpB2~w>XjZex}xUQ>UAQ6MVs$QD( z2HJtSVP10c2Q(0J93Q&&g?W`g*=KK4R=&}6YdK+TOG5>DpxN@|-{C|%pKqeuw`aWy zE~pc)!$akajK)Mbrin%I!zW&{$Ql}lrPUcS4?}^PFzhi8O^mBpT3E7x}(}M+_XAB?`7yMw57nAL%ZDpVB-~P*(J3*#@L(l zvGpgFy;$8S!_qWcDKsDQxiCGPfM0PJCp*Im)im!B6zlv;`y`bW?6|Ne`_ zT%KQZe%OHf_4N_Sb9%DH%J$Mi)7a13Ri-*adg8RGuzp=mYZm3ty`?|#rTw4vf>F_Q zIhFgBTS_o=D0<+<%$);9sjS8LXM8s|cG7ttOR9bx*5F8)RKBZjd*a-k$34l8U^_=b z-`{r223@2tf5KMi`xQdA!c&>xkrz=M_T)8m#`|+}LnF#dTdX&jxRp z8Emg&TFAh6-!&p6c)Jr?WR>H{REUy#Z-WN2t{ue_zTfg-R`1SLC+8(Y4U2(uHQoj$PKj>h2VGeSu7&P^$lae; zKO`|@vA{BJY+J{W+$UrjNPa7ifXd7X-T1YRQ+44u>(r&qxooD*p;3dZ^?zJ`CT& zz~c{(>Gq`7w{`79sk5e)q}E^T z$W~bq8e!L4j$~e)~&xot{r-oh(=^IWADNM)`k05Z}?H1j@5cV19ok7Xht|(80@t#e=TTlY5gPn}fk zz~BrNt3*SKc^f4x?h_i>Z_Run*9dWXq%|=AGg}_mB7gBz{|4w}o>5Sv!rV3WEl~j% z$Js1HSP^@QFujhdzF|ZHdLC1*Vw~1;)*h+2w5eOLC9=m0K_U{zHY|T zXII^m$HN!hxwpD7`DgBvyR|RJ3z{n3$WOS0xi=-(yc_c}4ioNhIw;jeXDBANa$#Bk z@jO;Uv9g!zo>BJA&ROXwoTckbycYSLZP(B(*#we-d<|4Up+(b(HN@eiKDKd#go~Oc zNMgR6zSYuW5PNm2s;~ff3Z3SNeR>qp#pWdG>T7N$au6%yw^Ikbk0J%7Pcc2I;hXc@ zK$zeu`_!P@XWw|*(0r#=$t_7)g94|2gZyl508lVohhxC=OSm?Y=ep`B%dI-D;nLYR zlGV5^b+;rQwKC+y=yrKm)SdawMYh!)cNQ7i9D2k?$t{shUwVFBj^>7?tFHff$N)T@ zeiCKWi`Q~3INNozqBt^|_ShkR_d=4dAb<%v1MFn#FCuC(_RFzbcSN{*3FDsRfgC% z#&|$~0Q&``wYAqf*0Jf(>qgcGJB^2Y$R*TMEsNf3o>2Dd1n_m9Z=JMe4#rvxc??R; z31{Cm2!G0Siy5CN0$a~YaDwJG%OpB23+8q>SMlaHt~TwM3Y|9}h`8G%_AU&sNKeBy zn)Kmzs2B6|hA1!fpTIG^`=d+8i_}qR%bm6V>A2x~+}g#idG@cf&o~op0W}=0x48w? zeSt!;=*YFLa9t!$#a z=6WLFn7^vO*ZN9=`VQ{uJ9=Tm5=x%?p5-sL7ak9qL|Pr}iYxctgU}u%)=-KLjCA?a zJZ2JU2qVVWtie!7|ZxHMUXP991lq#>&v>M%k7z_#mnP zy&56^ZQK5k&r(#F$n_^^r6E79@TWPtDt<`|mksLz877Iv6|jgriC)JPi}?;kO*!sR z1DWLs6Lx}Qp+VqCAl~8IF702o(RqAwYs64G`=X=4jWV{)#Ck0&M?-`hn*XX!9qZ02 zLDp2gPzroA*FUi0v)Q9>bUXN}(*;i?RvJbCm8}{CZnesBsfw+1Xad@!s4x-f2YQXU zy8ttJ#$;q=WBm<;Tg<~=@paLwYNesNAOi!?eX()1mfH^4RVe6Yt=`NS$}S{0zguBG z2&e%L+YC;X#hdxD>axqD?l54>+kNM5-phKDEs68XTa`O=(t8|kw#lIzi%!$-;h;KP z$@8I52MX~CvIJLOuKXi^B+0RQlhCM8iZ{)3*zl>6#5RO;TtmHUZr%S!+E>R_y?xtm zLKFl8R7wP;Lpr2UkrD|75v3(W326Z-6@!wL7L*1B36Tba4iyljRk{@fq~Bb7Z_hb+ zf9KwJ-}}#xB71+=cdfbR9CM5@=WVGLWu9%E2~Bw6u`;?1w{r%LsF(c$xF@biolZG4 zCwVyhRE6KVBzKDkuedVAs3?actZRu&GeZY&0GdfqGbuS=WB2m>7RPScslHMk@=jaZHO=Xf@LrVW z-NVp`b4UGMWMltiLW;X6VWq)I?N#6@XjNosiQ3UMEDm^im3maLSD_xQ!R>IEc@}n1 zoh~tXegn*Jb;myoCTU=66l4V*dBC+nJ}yJ!cC4r{p!BC%TMB%(-8*Q1|7aR;I22^Y z6I)+zh$Ve+y`*~E@Uy^hy@;DolKaw(b3~?UW$ITbQ*QS_wHcJKzM#te+we@<-5^wLI*y0;4WYOK%Fm_hZ zOB?8nCP>vWs}~~pkj$Ht4fe}Kj_mr+Fyt|`g?9I7Z_N(RT z%O%#IXTyV-*hV9yQrNAyv~2HMzm-CP+$ZMnccjvE8h{}WCxoUqSLdK=BG@Z1U&U_< zyX+4@Lb0hjeO-E?t@F#Ai41+;1-eJ834m7d(iVZ*gM-aT2|MO2 zQF7mLVs~u8agJvMcF-UWB37@nOKE$dhFoe~dW+&q3SOT%lyyiHx^}IYD3&Xt%N_4XpORos`6-tIl73)in(w?re_t{opqMmgxnQ2IG zO4lG@Ko=&b$%-#};1i)r*=ft!hZF0MGIw|@UsBT@;%*+$-6#xrHnVzOBAT)(3e;QY zN}a7&^+P&^r@1W;vOKVB>A|KygHy6o8~3atXJ;4C1gh2b<(`3!5#*8dWRqp=lvmo? zZ7()y_0a5uMR(@q?94f}L7wpt<<%>3H@-dCFO>OuvwQQ(#@cewT3DKeGGiRi>LPJ; zUN3a5j_b>8_0D4D0-lMk!M^ju6)Msg1v)v@;8scT0K<|SfpQOFK2XXq1RyXl8lN5v zJam|HfO?_9~YuUz=+*SQ$Rk4UGj+o=ri+RLF!ecwT<-SLGA@m24 z`!R2js(OWEgWA&;!-evVl}T=f)8+v*0&g5XIk3@S&Z&A<{Q9=j0%l|^4nP}CkCURB zH>cn&x%sd6qejxb<3rM*3yC=CokOsWg~06!7`eyrCDHwK^xW zNhlTp(;z`%jSYiTUIwd!fUrh}U4mUXSi61*3_$auUpu8 zY0YleI)zci=Ht~H@%u+*BIAmDH+Xp*Wtm5Zb}wItSv{_!BM=VD(g+M2rGdACYoq%z?U@HqyTC%t_(*4~NZ zH>lQ5~&$QLcJl*eGsgQ($ZwHHwpR|D#a7s#g0NKLpn;JqlvyRNSLD}WN zOM~{CeY}}*FDoJ(Pe-G6M^L-;obJRML_A-bYrtb28gkj(PWxIB%()D-^m6UBcp*Sw zhMPyR`Y8lVt_dZk9dgGW}(jv4k}a3Igj$fa&r98|rqqu{Zny=!?V3((Ek7 zMRw~D(8Dy>2hWHZVpKb(SLfQPX*ra7ZVZ#Mv@Z9_rabo=98wGlGvCzhW&E^CpbdEz zwhRD38p;5!pDxBvR%tgJc&5sw^q+!)ufG@^P0zW@&I73W^L*s0vi8p&I!$+3x=v=ZEnRJCtn46lWZFc$M#rFmzw?A@@ zyM~&s7YxuVU($|nIcwn*s)GYZC`^CQH>~2}yhPrFtt>ps{YVItNL*Qf)v!P%<{*3+gMM}9RqYsD^h|@TB>+@y4<}(yW1g(C7VP$Sg zjl$O?^f%^Nq+tci4!x;3uf5{1>zn6ipeC0))^Qwf&6TzCvxn4CDVA^j@s+MqQqsgiH*3`~M>+)RyO z7Sk90uGtDII>;e6X0K*|y6Q#TBj1}|uriZzE6_=G&J>m~su&>R^gl72JiPz+PGzlX zuzkK9+6hQ<9m&oH_l(JCT;9Ed>ISg1%9*fpg!VeDdv&7zp>eDLPAck?M-6x#pEU%$ z#qhj)>_pfUla&?94qw1_rh~w|Ah;EZ=0{fyXVwzlBhZ%{l>6w&TIT^;*&vmbe z*?6|jRDNDfa+6KuA~fuW&7NSx`{zGmHB3@wPN|wd;PwN=ocD z(ZU)h2rX~5LEdmRp_R#p&&^62%z0J8G0Gwgi0{LWQIDL4Ne>8G-V?C=;4hQ{eHT~x zW=8M=jC}RNKB${FYuV)R!??~bPj>Q^y`X$3<)OHqB4ltqR5N4yu7hJrL@C+qIfAVZ zg{KVpe(^wFY=KH;qK+c##JQM(*qh7h?vESptD*e6 zGnm&k)L{XjwHJWi4e&<~Bq=_OvpSW+ezn5ppwmX?Y@k?wde+^FhGx2#k!jY;X(n^b zX6dUGtGv{uy$LPJvu5EZGIV~XCZ^^?bGilWv>04lPC>N&u`?npRRCKI>1&BM&Y>xe zkd57czG+GCg7m?9JkU8Bz|Q&F4)Am>Afd*E)FUq&gf@32t&c1x~{ zH^IG(b#E)|E}6(K zCic?@ZB0bC(NDbyo#IZ;rSP?-npTN-M*-tgmT8L{@Lf!p-B7$xT!#raVOC21z<;UI{r3mDnBF7dCTjHOFSM zheeFSncQ>;YzWX86LyF+KyPTbfFXbRb3>uCy@T<@N_>#1;34V;Ci!D z!k)oqzG1OXM`b-HVO~hf#z^Vwhe&Z+Ls2!ym;F;_VkxoJkCp%A1Y3p!oNIRnm`)Xw z_Sh|x`0Oc4Yyef!mfM&KyLMsu(y5I?=Y%TDhGE-?vm&he*g!da7?n}E({5RL(kW6Z zep*-^kCv}@znCMDQNU_JQ06iDDUWQw#r4c=uP|(o%+2+`AaF)}e{7BkK*jb6+yeu? zGe!@vtXgPR=8eNh;k~!^$F?NM4)ixZhNP%Gjbo{xkG+^)>;|{}K=m>CnS%S@<_-03N zig&N@1F{VVMRMUtJ^KgJz0g@}g8q5r@RP28@kLFC4CJ6#5bkBPd1j=CV^J#iHa_fbNlP}kh8 z^Eow+Vkv^>;U^nAFHs1s=k8kI1yA zz%(vpqYT-KpZ^6y+~4y7L$hg8Y%*B*+Y4ZPh)-S2;snNr%m=Epp2AlN5Hv?%44Kb1 zAG*W*&QllQuUChLphtW#=oTX|xRu_K;g<}jypUUfQ37nQ0!Y2<7rx*TJ`v4C(8wY+ zLWr&{&=_5TIXyKN7{Z!DLmCdBvyCmw&k3ard z;5dG^4Y-d@d7#iS51-nxg>1%Q2m&2xa6oB1LIsgu6gXK0meVl&WyDgA9)q+HQ9z)K z2EQdb%V(GIdLf^={WqWi-2`=jHHrf=>p#y4xi4BF%2pd#jUa6x+?$MTfN{+=GjaZ5 zX|(m3_sB7w#A!(GrcWUoqijNzLPN_~*a<%M#*#Bz=PrtD2ZF>=@eW zn|&b#FT@hqgUMG>SKJk}MO5+c>KP4l+^-bmJ{G!lsCjrSUWj2&Tov9!tLnBTLEidA zTfX)A6s)$(T>BAW?N$ZTRd4*S{7hWc?j81+=MN3xzkW?qHmm@xJ|LW7YhAkI4*tYT z5LexaXT_t_TfWYJUR@?Vtp0{-=B?hAcZ2Z>zzdr|%qS?4`x##sZ8;VHX>H{K_k2JO zXYKdDv4w5<>8eaBoUo|@7y{ZZy!NJBKk;9e(r1ne`zyl@yFyI1{GY^UxG(8v!i-6M zre;XF_0|3BIx@ZR!>Q!5ikOZ`Z6z-E;k8ns23-XFXnb5w*_(fP*pcK)*VK$ z_E&%&+wa3Y=jHJb^R3T`e;Ix!PSc|SYH|oUXafbKL-l^0cQQmlGAmbvV9atp@ZDnp zkxK z;y0-8Bj_m7=ecy5Q3GP|>$3&WqjEDY;N)dKN0$Kg-HXVf`Mxdtwj`A`F%21$|i^eVFJt+Gm$lP`lOA$rQryB zxrPy;#q}Y>#wBu#ty(#6xdi{by4}_jwpvL>U}rxjV5C$a2U|8(qSBc$V^M>NE$oTKLrdR zkUzXN#xm~Zbjh%)zlOYDO2S)rvJ5^JMg#t$d8p+5ys75_duKA@a!D`+*WR2o14+}Sh@%CHAY4gyb33gnNz8fu+ z&1(*pH2Dl3X8NFvF2*XOnKWt$TQgk1hg4zW6Lf$E3Sg=j2=0%uE1tDgsZIX}-+yhv z@`Y!F<^p(OOSfg~OXh#QOYgQyo}ISy%?O&kfY5XW8+jOG-Cc5ZY!d9q0s=l)f}$)6 zu0c1a@+loQuZt&Ls<3=5A3Am>b+3@LGDl#2K`EGVb_0?cM#>_T#Z!;Qa8J3tpJnTGXgyR~Lw7Ced0}_MGw>hTsK%QBCN_W;DMRq0 za{!8?8gFnH5G5~5=+=2ZTHEm|Tj4g6Dy7;~&U2|zNXZdEFUC9C9=xjx!5gld>r2hh z%rT2pw&($aq>llNvi%4icCJ9A^cLrvxQjQjmzd@IFaYHOfaHoGyHm9}zVe@E9l(jK z$5mZ=AzU1=M~6qNvS5t%NomyBYh3~*q@a-NVXr}ka~(;bFUXHw?ws#@yRl4prLEG- zD^_&eisu~Av75l&rx_N-T6T4F6^?8(BrjKPTNi9RVtNdA+g)V z*c@k9LpuWFzMs9z|4~Cv@0xcJh+a)lfCuNV!S*fabg->hPVGFz{hH5S-|a1hSQJ>r zk3M_99T#8oV73a|HO)nAaMaj^dj<9!M_ads!0=rBg?%4lLcw8osI7C4A9YhfEe~@9 zWJ}Z*+Vpih7e>V9ZzvO*fb*+A-u>d>wq4>wdyqj|cXCegNQ{C6i!u}V^qg)2p`R_x zA3apcV^hoV+_2PX(p+&OqKYb>C0L8d$g$i=`q{h-nwt1igw|TtDm17r)HyymEZp&F zsQ01hp>b=h z9$DgW@p+ark0g2dU@W_~lWY)4CV#_BL?(dCQZ!}=-JS!g zUmVFYzBOA^LH?I7Z>v3E?+iF3-CcLTM9?y=lcz1t34=8`0CJ$2ZQ;i1z^16%6Fzlc z@ztsPX^zEEPl*rax_(pGu}4PQJCsJBqG8)78$m`g`|0_m&Y(g`hY?lDH#T5DRGwUa zPJ6N6-IiJ1JY*Tvcp0x$6$d}jSC`05XwtG8Ds)5!sUo0CKY8-hwyLp321#dOYQ5_| z(%FtJCExtGr;d<%hA`1Yv*;tPBDylqY{G=&FM&;!Fku7e7^62P&w5=F+`wK8-${}8 z!J_3A!PAdb*wjfW)X*HTKsu4Ue54GR2PyAws|gID8E5b?H1jYtv@eWcamA2>2Se~z zn1C(-G7TZGjpa0P7;!xvW;)THaT(R=k&&!|I6*weP9Ti}5sSyqUmlx4nzF##8eIX}K24S(@alEyfZ5>+QB9Jk0 zLO?Q=Xg4|1ibk>*(U*aj)r zOn)m`Fj|+~M6wv9Ii6kxuZdWI-draq=`$)*nD-O#bG^aRY`w|!?CV(-ZW)<|mgGXY zRKhXp1a??LfCKhf`4Jv4k%BY}$qo2Z-6c5_nVdsp0+F|JBv8qK& zdqMdz*YDPVHt7|2Rsw!))+SHvRj#6mQ>go;oQ&C$L;GB1!D-<4U42BrA8F`WjGeF$ zly)Z8TojlxDi$q(iCDu#=i}SERRo)`0hmLKfON{LEj2J&%=WS6heRLRW7iXl$DaBl zsX22#<*UnDa0sov8^DEPZwX)dlY{#)SiRF;Z}2sV&o6hB*qHU&yp|xx?87g(Fy2;+ zgzt;x#MN~bx2YCfH16Q~$XwR}PmG2p%YbJbm|k?j?d_=9lGPp|xbhX?z$*!KG5Nu} z@po1(mX$zgH1r?=^u#%z!kqhGc3k9EJlkzC+^wEHes?$HM}J+-oReFUlTMh1e7u)&S5Lrik61&B#V@Qv;Dr$pAjzw0p1b#POQLN3RR zCjiyLMn)pzTMQ3PQ;HapZuuPTC)ik0u;tj^=^vBR1GQS}Ds*Fsw>BBq$ zGeweYot($nGv#N!+;PUjdv@%oyD|slp;rzAZj(ppzffMNCaF-u1gP2{<-L7`A0M0a zL9x(snhMhf<7$QAgxv}!PCUS3vJIOk9obf(ABu@Oa<~gktdN6x1M34}rftQtbsQCk zEdG+7$|J`%yP~0e&S3c+5~f|!;$w334R3G>h2Q~Xh~5O|>6R7CBlLXKbHoS6drJZG zb(J%TzhEd2FCF`=ztv+B5(Zu)sWpP}- zm;tm(c*yoUR@hrl<1W4w=8+1;rY3(?0^wo!Yw#-IN_9%N0ICTBup&se;%0FM2>4UZ z-QHCYp@jQb4GPFK=Hb)}&&fwY8=_+*9k7PNx3<6 z?LZTp3g)Z^ZVMFud{ih?x-LJIo|?kD&urHbur2#>H$>tz8#XTg29f>oyLcD4>(0YG zf+%1UVa3;Xq(A1D91GixeWR@hJ}jyb8mW}VDKVhOmn+0Qt(ATk{g(6@W(?tSRPTBS zhT!8X0@C~lvu3xgV(-}vt2K5BvY`Wfb7VhBXN0_MQ+9tirA1yN`Xr%tO+pa|>BQHywS| zYcdKMUaf*c7Jy&a{admFc0w8f|8EZfha0Fqf@w$Qp6d%b`H)f3x>9DSA}6$vpc=t5 zFrOU8mb|SP#d~X=F9e2v7sg?k3ydm?DKKBOCoRPT^4e6O zH;e0b(pPf}VH6&3JUuRflnPLe2cWY2Oy^L2STnj^&{%ib({97I+wogsjc`sr5;(0r zK{A`rE{}m6!PS3wJQ3QB5fo)ST9vN!KX6kWeFU-O_w2XGZHt*e1Qg;6#HNW)z`LRz z2*d*|^V_R_<;a?SxdmkNSa2qF?ZKI*VtgW?;}%0)^^C_Z2%8IOkl{AeSq_TUzfKMo ziO{-?j}gK7Uir_-LG zi+oorW@M*G`SVm2NIgM}Gj$cp(~1x|nvBXc!1yMA0tu7Ol~NV#6`H`@AgdH-j*cPV z<_9AsFiP4!-)ZO-jT+{4RMp5lH8S3FW!xO3^NZ_XX4M442=3D14$vnR)H?@|HU^ok zUE{ZW`)KlnYhE|&) zEjqvA_gv-)xgJ(<|02_0#9Dc2Wa1b2=;2o1EfACz6@G!`V1YxV7biR4_d=`iiA5vQ z_jTyI=p)(H9C4J!VRLN86dqOurGgR5hjVPS8LuFMiC&RMImKQ#n7<;@<67TxeKVHd z_}28hp<_YuFQJp$RiY_DcKZ5*ehvf=0XmV-5GwoY3(=X(r4^W$(3RGK>?dF`Mf=-~ z%J$>aV{dML$1x2D=*f38(YO)@IDP}y>C6xxO4AY;iqH(~ESrIOJg)Rf8Lb{zF4XGX z`0D#a7!s-%PS2&{g=jF$$9d6fAy^gLuz&DAYHRdS{%No?%+7{PCUvJk@V zY~+>|Y=wnCHO}J}ERRd{4}dH@0Uywvp{@a^4O0{iV6DW2YnQ zJ5Miab)_>*(~GZU?1<3KU)PzL>k%1Cyyq|YiZWQO9A%4$LmUl4^+-qB9|j7gl~9>A zBergHrx?87gkqFax0yKhL)fY`O{fa zug^?e85e#D$u@m@K9u^jx-MvB{cA}yMPj+R>vtlvrY`r`+ZlWhqY%%J&0d;gA;q!R z?04)VGqsCff(yC3@LX5qt{5iu9;8GrhWI=k_KGzz1qccXB&OfhA!gny2GpPl0B-wk zJ;bL#SexXHw@4y6a0h3ozQdFYxIn3KQ&=;lL{)rdaMp-rt2Y>j4t`S-L;1ds%d6O! zo8g+-CZOx(s44g4%mo}qE!Rbc%;*=#`4A7na-gCdrhI7jmtk!O5pDsTkHvZcIJTbs z3p&Fmlm|)Zt&B{yzMkAI-7W>Le_4X!2eBr7iSM>Snazh#I!U8j#F`CZa+Ba%@-2hS z6&IrS@j>tFF}c!ra9)psA@)6qk;$B4X*tTJ&!p_MCQN9PeQ>OCpG>HaQ!{-$#qo1_dxI=Un3A-IGg~sXVg{4hT#3U`Z}}RJK(^kVk zNh(^nH1z2<`Mj-Z=)@6RnjQ|I-lyRvHoPfVGW8#=CPlJGv2BQx8d4d5ur`-@dn3m? z7=@wc#Z>q&U-T+_A_4zKz&eO97D=B#Y5LGh6#S^^a99h61s?s1JYu=E>TSSh792c; zMh#z*Ss&n*Q7cyt=F>HU(BR0!RzR-iA?fJ)NYAWeLa;S6`5pAym3)8`{Fw)N6VFoX zJBBR7fo%d;tPr6}WU>OXk;dp+Jk-&EuVaEz6k~80CB78{cOU+y4g|w730Gyj!gs_*8?cp9>7Nrfy9HDZx*2DFD{QXwtVc64<9AE0+RS5h2KnboUwbj#y_ z@E2#E_Yo#7IH&QGZiNcByv)B!Rg}(L@WsV7?F%~&Vg*8f^*ho@@xRg%?1!jY+~&5z zIse`l2#&z^Y}mLp7jeMG@1+J0NZc;^z6V3)7Q?^wjQ^vl_1Aa!y}BB>UBIzhXv?Y- z5a;2ST^_3Gi6#@-E$P!=pSv}MK;K*hZ<$7=5-YW}ag>F(a^xTef1|JUbx;2I#D87N z1~uH_aXzJZYs>%fnZtj{2G|>O5?;z%U)_KGa=#y#|!zr;S2+)I2} z=obT_!mAzDie4?g6$o(=8OJnpUk#is%Hx_v1K_#@u$#ry31`cit>N4Crc6Ks~QUF0TNXr&_h1Iq}b>N-QJ(-3Kyw z!1i*>BV!0Nh_Mk1Fe%#}x57yopN+lbJ`QF8MLEhl|KoA;37S{MiZhhC75zf>sc ze_86^y`Yv`h)kv$ckCm8n=<0_tQXA3K0Fbh$Ij$o@~(nOXRh9-HBBi>G0J2|j@Ku0 zaB$scx}Tm^q~h3l@O<^bU?#F>JLbkGVmx)Ko$NmCr{bN65i-(iy7kmlgWubmm~kHw z@&|mqpf}P4YPgeceWk}bp2tSRsLj1ZG`dQUGTvg?&Yit;8~$%F zBVkv?rgmo0x_8Ye8Ey^gSbb1K1-+aRa9YSqJEI2W+~c)5VCW!nNer3}iR{%L%5HoH zQ)Avp-LM0=ZP-M9c@K7DzmcyJcG=I}e|fJ7`=$S0db0c8yW|AC zIWr2ZD2$-0VV{RYFE)Z(CkA{4qEOA#o~6T=bl~f;AT;(F2`K{GN}R5>LE-bENE1OC zpHj=gR`%MJR_G^%TQ$Up6=O=JEOnff!q@++}0PN?Zk{g2_OVi6=5KLW$!&n<W8L4PS*_C;)JUrMJ4$6qPbV|Z+7xUL0jz8X~hG& zU^mphhGxm^6<=37U}F9G#p^gg*he7CS&+?JGWpCbNxcNtN(iy(chLPJV$pKY0XjUF zZa>PsTzio>Fa2~Jf6>ZBRx{x9ma?D{YeRDZUMwBoOrFZS!4p3}x(e+PHsZ)_SdC+} zz~#GLh1RhiYzoJqcrHimykowOa^#qbbS}`Xg@as*@CZ4WA%yIk=&ye#+F|$sjg|eZO+s*x`U}%VBzl{UD#R zJs%bnX{v^{@jbww;J?C~H$Jk-f1|5PKT--;V8?}1&Jf`DI^~TiACP60?4l?FrJFhY z{(k1Jj~h^?Ew0IIt~unRSz)7^ZySRa&~@1w+BbQr(8>~+vqH?0+!GPf{gdC-og;U9 zS3hoSvUX%WZRP~e#!to*1lzH($&=9JMaJMH&=(to9Dm%?Epf~Up^~kxAHn49p~n5l z9u7ys;zOg=pVS-Jjy=ua=aHD43t)XLLROz$$bEC9;>)d_0Tb_b#*5?MPBm+yTm6gW z;~{!AL4tSpC7tOq-Tn9PlIVDYN&Rq*av2*6aIYS{F0Jc?5|~fhB=+m+2|+i8S#rX! zO@F|F(?O3Y3T~1fy3qTfZUEO89PxmoF@nZ+?=+JH=s*T=4`NNTrQ@#P^5i(l=kH)9 zwhXz2uK^qK%KETj zYN^20iu#=izI`xY!D1Or`Vq*y5^~O%7eEVlKkuQpgyv7Yu{S0}R6QuLnPcxyUFDnA z7dKYzpEqgZoON`4pVc_Do-^wb$UJM;#cJr>5m})^E?I3^G~_9_F5;QG-U_9-t@-=M z*29%BlCONj0X&b*ArUiRRM>oCT8!QN-jp-|TuW1&k!j2@wU;o@3k#D4r-Wz2@=Tx#?(uQxEqlFa9n^9&Es0riDODQQOiouar3G_J!06DD_eH(H2qdxOt4y!&#lSEN(#a(2l?W&vr6 z`{v}TKBWYV|9U217HpS%cYcY8QgMA)rp>c{U;vr^0ztyyDf_W;S<}P&N%%=G{KDNu zygpyw-lG?|wU^xkQfh{2kGV>4c&6!!LS#>8A@8BloA^9)AD53_;QY5S_VpEwVx&%x z4#?xk1Y*Nt`?anM%4++o@ey_Il-xon#6^GpaolS<#gaJrkl#Dw{>$5{xSRE_oXPKZ zD$=e;U!`~b^)~Z2cSut~FlG)nJn2!zfU|&|?3!d}&#eoZ%g}58j%=Wpp+9aD76%>0 zF4*>`S@}x48)xo)L(K8nJK@KunnLe_z6cmsrEMnAf2;0s$Sazx++5F*CXgdHZcmA& z>AY^N)7)A49p-0mud6%7_ws|4RrvE zMEY_6v$QU$XuUlk+~(g6gH+&TqC6d3R7!FS4_o;tKs441;s#MhfsSzDP=<9y!M(Ty z0nP{viFRonxwUO)lY#qm%0tTRR-J~Kd-h!EaTkAIU;B3A*Lj#_!fS1i@j%L$>q4@P z8TX3jN9BenHMMUw|6dDjMQ(&H4J0L-hcqn)<$WlsBHX`j=GJi%euQZv&tcm4;46Yu zB%GJdw||F*tq^L_X=iHX?#wd1_tkU>F#Vo3op+nIUaPUR&>W(mw78{vB=dxX z4=fx6U1vN&UbvVdeFXYmcOc+s)4%!ShUbuiYoi*InmhwHyc95w6`X0- zU^UAWJ`~wqF1@}8t?1pt-d(V;Xnddbul?NTqW~s%v%78c?QZ0@T1e+lYJ`pez_&nd zYZ|!$M(?J3Chy31aL=U|Cpfbr>SRyo z&od(pY@zl>1BaLVT+cR1=XDO>A~!0i1h!zdZlz~A$(f>7FP1M~h_DayYX>S_SazGW?KM3B`(93qqstrP=)EWrF+!k|p$|>=ot6`H-e7Eb8XN zPto^?eoywZd%TehG}4*@R3GwS?CTS7Si>7Yy2`R9U&p*5W|Cc9=@grWn6 z;P7`iEYV2UdhQsc3|COC6HYkD*i)Yomv>1TS7b10@DSUJwD>0_AZw059^nH^aPvmN zo+!HT;`gHS;}*S&YnL5v(YbMp{*0fJ_P;FpUfiN5!=ekr1b~?x9L0qtzePS85aT z>|TRjV`}{KwxE4Ku*;o@!9@$x(*>r`MxhGX4GrgBEZ9$a?&VeOe9(-{ z!Bfv>FebgAhCfCfn4HaE{c9?Vgg}pSWx}%H zrBDYSHLU2Jg6iHJ28|aUw5JP-yPkjL;}JA^bsn5o-IQP4uDo}P9)*Hj(lW@cN8kz( zMVc7t!>1@i+uoowejfNwJ*m)bd4G|JvYDlCRd#GW8%$qbfcG+;SRGIV>Um$cdih=J zF38w>l4e{M1UE*j;Q-})uBd=(Wdy>&%dfxirH}?8G&iwiJ18TBq}>+_*!`>_ky-o! z!NFpta?{hDFZRGe=n2vVa^n)^M2;PRj#2B#X3$fTs(y6c9Aw<&7j&j#r=LZHQ0Kvf zHZ{rSl^=MFBX~FVc(E}$DpO(KCKng(8a?&=@X#$>iT)c?)L_A5mcBIt-iV+dLUq2q zo|7+D%(js6)a&PIZ|XStU@V*fO8ZD&vezO^3=z!dv!DbP@eZN7@UC9%C#6EK-+t~X zkJPUg&@6j9`Asi+YQOjp3$<=Ij~cm6KiD`iFK3p*NWUf!fc?DuW+5{xTM(&(N(V+8 zFvyiZS3&eDPdkj)$Om55XJ3;e4hM;7_FlZPO5wh?Ekv00A$)@eR7Pt?*l4sTtO{_s zD-;y0B~$HaQvEgIr|W?9~CEK$U<}8G1`G3Q+`2V1PGu%T%PI{kwfR z06kL~X6jNu?pT6Nx(i)^EIIaef+$BT6b}r`jvWeW-XW*T1V#6q^sqydP=JxRGZA|O zVF*ttGU*JK6|E=>*pGMSB)p0avJx&pCV6N4lSCCmM!qV_Qj0Q&}pE6IGxDVTP04S|8B^Bb@~tc#GeyiP61Gm^_t zeAx^#LM)G86NwwR6Q)Xd%)(3db^z5VURHSqcL5v$xKZ+IJI6fg5JN)jmYec0q;Cea z(QeG^m-9|9Y^X1IE~QbScsZCl5t;lxT;@c8(fJ$$YYGwM%EIjN`N_RQS6Ao3CcJCz zsv8b*#1MKC3f7dOVjeh0Qns`YmAp9VcYeXY$7&TOYV3P7E-`C7;LzvP84YwB_OZ3A z?ditg!(%IE`)ks0^Ww8#oYdH(sD&Yh-*f`hk^@YtT0scM_xuID?srL)OXQiIrf28T%U**Rp_mUO1@~J)aR)y@kdI?I zN;PtE5!LiyG&91YPl*MpeT)dS7pso1sEGRZCmg8 z`HW+eBtWC1IQLTE;sy}`?JMACw*`?_-#@GNl$@UGJjtPO+!evK8&yep01u5{drBQn zm6pP%*1sctu6+k9YH?tE@>l?@(`{wr!(p);cq}$WA(-foEgymh>-NV55~zlV?)BS- zyT#HSiQiojw$cob`y~qek4DqhWaY)=S1Q}@6XNk+{CoVz+CL#~$D}GgJfyH;+ExbB zi#qNbj{u-qDukt1^|Mu>|6U!fX5DL06*k*$7*~@jLxKGAs;Btv_q_}1R z8RUp^^nxb%&$U-F`jB{h1gzTfYK{W6CQou(;}9ATWjypMZ19-#sF679b08ClH$^A^ z*YAkWPEW8WlJIZXKhrPmc)X_@GU`e(zy*ZyxPY%JE=1J5yg&7i=R& z5wgC@@@-F6K0Bt|lb@bg?C;ct?bN1-~EaZ|qGj@hl~9z_vF{e9EF~ z@Pza*1`_sYxJZRxR{|Q53f{P+o;UITao-W#HFCJ)kl-Kd&%uPR##*8Alvv}Rj(~@ZSUJeovF*1vnPSP< zZT9#3(zuSl%05B+?fMxSA8cg#$HV@2e{2Zx&Xxs$@*ua*vp@cy776~@3I)6~$e%wJ z{G$^656k-ZCk^>we=nPkyz=&~yBqEu3UeC+QV8dn+rxiWijwI0>| z?dpHN+q(U@$a4akV0tfkTJgQA|Ni&kKP84tx8nb2rkVN)mg->k1aZh6B_rnBH<(cf=51^?PaX{y3)n1B6Wt?Tdq%@ly!4gq^M z{(PgsRJiX;%ud2DZh4-CaO*N*2xSQA#cYH{u66uezP|I%f2>w9g1CmpXf65aq^Rtl zhe9q2t~@u--f#wj=MSM769sna`BQ>yX=RkZpkdzxhSZdE$H4Bl83YzoYbfl%k7Dtb zE&+D-KekmwC_d(Rk{fXicY2?=w+At+0Os(hYisX^{8|V`x1F1i!#22snF$f47xfje zXgVY@4&hw&__fMoeqleX;sBFiW1;2OhQxkonhr9$=56^5h)v$ zRiMbMU0Ilng&G!HWy2U?76pz$_3CUfFMt-$fRu|e-7mKdv|;}*3ljVwYKSx{I59;b zHss20FMu+$!)}0qo?aeAsUH&~@tg>d%XELI=G%S1;x?K&=-3+`gR&wmA0W#bc-&!=^6{*5RL|AoWmq6LGImr?@eR=eR5AT^?dN10Vn943Hl2Wh8D0!iB=A zs4%LnpYNlhEVn%ow!M}t3IFiCNH9alspGoOFNz=xW^V6O%2B$S&5ld9A~0CYfm0B4 zL=SayO?>0iL;8|#^}-zcGjLVjI`kD)LRHLr7B_wnn%)3ytr$`lGgC$7CDQ!v7pW71 z2*DrJW*$wb-c~;q2dr4>6drl_{|xbf zc3~HczZ%2lV$H3hqIk$P*%hWDO@GUQ$zG=(sC+)S=YE4>kQGQ=m(D-}7|1j87Gb6L zPlFjbyNwL4)d@$Fl|X=o5wtta_Go$`@Zby<4R8MN9q%p9Uj|99RTTJjH@eqQ;9glG z%?|z+?zNXY_&CER!M9PcZ%?rB1ZBNp6uLOtgs8jlu{Ll7!%(pIr_ z4#I&{9jNeVMwLYsh>HR(;owPqeGsvifZRy%jXcwip?F*@n@z9(BlgP;v*E6a?&F0d z{K(uCkC#z~Np1j_$s|((0L8+xJRNOI+4Os`hHc-XE;QaYDusdI) z{+!v3LvRHZA7=7*LwfFHLzq>N5hBB0EE_)S%7!QqJ~aLHL9X!E0?#kLoFi7-mA3oV z+PQ_(bm}>CheDLckPc*Vy2srkE}6S!bEfqep8jA@72IYBI}migF_7g)+_L+vnX-cL zrEuUi_;XZh(MaL*9w3m^C?mPknX!7esvkZWZDT5NV;m1(&-cR1_X&2L3JgX5sMV_V}) zd%=ZH^dQ%ncu14$uU?paub(_iPA6Q4Oz19XNqRazNu6F29+jlQW~|(&uClhY&*dRI^3HQP2wbo^c}Dq?9nL-b9_| z1-5CH2nXtouIn>zWNNjqZYOb~u9KYkW=B5*L;lhz2Knw~$+;lyO|Aa1*_Zn*8zF0U z>a7p260V*H6wn@NgVNv$4Wv4MRnx+7%Z3|INax_Z)ZMQF-iz%j$N1*jtV1y)jHrlI zNCl*6)d-?M&`-(k1bwgd1p~K@>yOji2bbO_8_w0P!=uFmJj`CEIHb=qn~8h}9=#WF zUQqms+ZRk-Xf8CJDOXeb2~^ zDnh5d>Q+%KNtfLdcYCFb(WkZTo*(+c)7s~ct;ZRv$EduI$?)vt(~5Ids+7|FS!jp0 zktwfOB(JvgAs{sLfA*^O+fUkcbzLF;Uf@Mp&lXRDwGGW*r|Imv4Yi7s?ot;cHezEB z;6)FQ0Yxir$5;uSzAf`LTT==(-p)l9>Z6gCmoZ_gk?;Sw_PID9nH{m$h$>Q*Dt+%*f2t!BVP2-1koI5`V|*-60j4g9s{tk>l@foM0nh z6gK=7NfS2|>y-)(lVkdm{e9D{i6aLsAVP=+6o^MV?oC_ZT>d%J*K_)0Tk9k;DvL^W z7reu4t^cO}#4;FLNJ67}zO@)w5`=?ap{_Jl{}OdM=tsphlh2$~MbP;ls0C7-8?EWe zMkj=nr*%Wgo}0rHV%{IG*HcAJB#gUjZgX@QI?Z2ptu^@pni%g!;?8x?Ju_P2E1q%p zg81=`Z=^Yup&Pt)#c6lli~-hZNM!njZ?=&I;h8mKzGT_sO#E;)_&jC7k~Cgx-KCo0 zJlG%g1B|Ub2os9d;~K)$(0kVL^^@G4F(?12=W1E{ybm3puGh2S`|cE3iWw*SetnQ; z$kCd!^BR?Zp76px%S&s+t_SyutKd4kYJNj5Q4etf$c-Ad$wvQ?%BM>~g%+cp6rq=@ zuSsEqxJDLhzkZOW=>b<`d;bYt0SRSid$&`7Pe`#Aa?qM>CwBsc*zW#%kzHr_n^SdkU~x>=Dap^ z;sEFuFlk%bgl_h1JU`p)JP1T2KxU_V;%;==X4t^?nUL`on6YFru>Gnq`-7`RL!_z; zI>mz1krK{RR~nD7cl}y@4>^iB1ot={HF6`$%y2CCfawcm5e(QU^ZW*MIdan@^n0!h zIF3YHklcNZ1ACb??i1UKqXvvTpVs~7B+;nu*~d=s>9hhIzX~mKHpiy10pY{3o@&D% z9dG}9rnyks)pU}rG3-JA`HL!X%W@CWmRTns4(p1lQ5eZ5@XQxKCEBc&-T0ag<{ats zS{paNt+hP3C>v^cq4<+w&q=nm!NSUPdqs*IJppe`O1;Ax6}Vz=_|op7U0Vy4#4#wI zgd-KWmQ}N!(pB9N2}fcQt_&cmT;i$&<+#)~XZUkGut{EO(Nrq7e+RB;QRD`I#%s#1 zOVHD;q+s?tU-{$A!RjoQ37x10wPgt8i*uo|kmGi(Eka^I?A7&JCH&c(ROGIW<*x}D z1Oe@4a1E3@b4VI2_kpl;L>j=6m?fp25SpT2>Nh@MkOrBWZ&{eyt2DCj)w){$neM_` zxF@{cNdwcBh|nZBmCC#myi*i7vAhGh)(HIpQ^I3)z|eu$7WpfB@$|-qGZ?NM?-B=7 ziaaw&_x9|@_Kdkie2~s~ayJ0u`x~ADu|iZ2L>DLDe#a+G=yi#-oMTW6r^@`ebH9oI zadQ-ytCfMnF-~q|S}_HxBzw~h`4QD2dFxNPGtgKGvPw+kMK4e}#Ue0sV4;!9=};@5 zdaB!{;XRILL>M`~id34e+i6_XTxo2E*J|Ivh*H2(d({UK@Xdx8-tcMG-n`W2aVYpwmih z?uu+i_yK?UhCMxUDQsV4Erq%;y}MJPy;sObD#7`YF~}WP3(Gy(TleW0UyvtdxyF;1 z2Zpdr?lPc6MYmuS7J}<_1XQ9VU2F&wtyaV%*drc`WO|Clx++Dm`}K1~j4&siNB^)nVvdyAtKJ5F^`@eiY zDIqE{ZJBi>{PwpR(I^RIp)3wA#&OVs{R{%I3T;Oc+A7q>Id=;v<3iS#{OKwH=M(i1 zKXn<(c%Sh~Fm-xNjtou9`0e)PQ0neaH6}BaE|g{@;s4GjxuHpJB%jMi<``WT@&F^C zu$SGR!0E(jVUJC|=L(;`WaxG9m3#5SEVq1M0bP$eZM#eIK73FQbl)))R0W)Y(C-XZ z?dc)RX|KWgWw%eXX$i0=3_r@h?Wc!^8eh6$Yny)ZCV5O;co9t%$MI}j1*7@}tN`a% z-oRnyTh3iCGk#0*e<=IvuqeN7ZCXN91SJ$fx}-trkdOvJ5oraHmXJ;pDd~_>QVdW~ zxkh641?B`Y3cLddO!C#qf7U0D zY7`l5s(T>o182Y_9rSbKHQ$VocJE^JFmt$yM8;BTTdrKo!X3Wjv8su*rSEh6glSk7 zTgNiY0qmg(N8N-otW(^AjS8DO9T;!Q2IBgI0Dz|C1 z;i)zI%F9ePqcx!hBJR+?T9cXEF7=1x<-y7L$fPy$G8U4?_bqxMc5tJdIn3*4(x@*G z6PGRzfirtf_~+e)B#O!%C z{9XAW7`ZHYJ)E{3G`R$p@oSZOPTi)p&o>SrK9;)&Q|M`zCW&*zMeuGdg*TLFwD`C%i27n5fH`WmTF&oDA|3m zCSvaPXwAhx_mX-h0FVcF5*<|qP!x#vrKSe zup@}t_OAQv^{25v#p#8)n|1FTOx2{f;a=+81n6t^74t;~8H6$vLXI`)y;n-l93Wuc zS~X)f>dr1Qw4r~nG+fBi)SZB(5h1TjO_*h(80GdMNPa+re&FzZ5yStPEr{!;!5;%w z*HR@z(h~{_%)hn@=08UnrU01?`Y0PcILg$H)#AttA_d_y%)pwkXUHj5TRRfGd&mafWCei zJDD`P9PkGw25PwKrLp$5Lf&{WT)9#Bbz9&$?QZuc2^H<^snO1RZjB7EH53Ebaq6P? z@jj0k-@Zc_Ihh#JeYIX;OftVFgN^ut>x`wb5QX>qU}Dea0`wRq98_68lRfLtRadOV zX|WC_bFG^1j?svVa+`}~-6VUDJ{4;0#*#x$;bsh8(8;ONFwGKej>H6or>B({0G1A^ zI}F8OX4?vyf#97jfU-`W`?`1WtQ}eBNfGM3L3@_MfZG@j0K>V?X`I>x_X}CWx5u~$uu|RkCbww& ztE_GmaC@JkyGyr#Wcm&8969ImvVTtfYx4_%`fkLkeZv05se`6DL|Kv?v-TUNW#>Bu zmlC@XxeUM?^SBhc${A%w;q{Rb$4f~xJ40S#ipD#coGk?JVGMF(`A7InGdh@KpzoO~ z%BP#Cl^N&U*r&?OY9RxH^BynxKYrN0+9+|SmH&Pd|0F{aNN`-;MiHx72Bb`r#wt5* zyh1Nk3AapkE#BhVM0fz?r7UmHDVkm>ODB4csm#kGe)*-xLA&)-VxI>Nm)^nPfz+JTtjK#DYj0$i{U^dob9 zE+aurC9bFv7mdpLN^i0ImyhZ}+}mUtJ+A>Ug$)LBus;sopYQ7ye``=$gsQ+ke(Bb_ zJ!}9G1Q#0~ZN>Oj-n*-Ev0tlh@|O?xvENIlT(^(ymbdt&e2DrvwZ0d1xmF)o4&764 zU}|q5rnrR!(ualTC4D}7G9CDdoxc^Z>oPfWhV&8d;|`y3d}OGAQ-A(+ht9eYKsKnltv%uWoSc`5wnwEs|U0@SDw- z%GY=!?S*$kD()N124Gv7Ph2(SD@RUkN{GQl^C3s};E-ZOKMYW_A4STIY-zm3XtM)U zMLYKY)NjGvRzv5dQ-I-%b^>({bd$2DzNAn{D&!~h9j*18Z1slY*p-WL^W=%OXi z2uSv$2z&#$c43!xFwBu?;{Pi2TmD(j7Jf!TWEA)EC9<4dc-(ed`^9~**Ts2J6Jgf} z%X!@mN1lvLbYU{vRzxdcYhhEA?_Sz4IO;5D^)n7GXVG;xRnlPyf9*_ zO5dz1wxZR%2W&RZj&#IL#{H)9(i8^JW!$X^ zZQbqn6G#Ce*rm%)jw)~~l3-(reY{Le0O=yx8nf4eT#o@m8pnI*2M`n3AI?6Cn1x~@ z>4W-BlSs{bRkf_NY{eW5D3SF&IeNow@A_Axsy!duzr&9V*=89t+glukUe4|Ajq>3g zFeSTh^5tb`xgON+wq`)*d$l;``)LO7(VozSWC@C^m( z3MI&cQWfkD_yG}gzoE@=&mgxLWO>quwDFlA{?gR?Ka=DHIyz|2NJ`atJ~P#!mztYk zQdB+$Gtef4HV$9*zTIY_qubTc^I2XOoBqAx(H6Tr;chK%?L6grrey_y)&x_WL3BWA zf{(+{U7V(b@z^m`7w?h9E;EgNoJ_lr`yY@5fzq`?t5xRf`$R#{Vb6mw4@;L0X%#VW z*iQR;@5~rpr*&pV`7_?|;|Fm7&wQoxmLr&fpMN#%UOb|s`S$vS5jJMhlStss+=SMM z?ixQ4GFThoEV!6;t5+-YYPHhWYn`!R6+^kEMLLprVq{~>Rj7~`dP(q z+1apH(C*p(JBzoYfXF#0LZj6=GAFH7dG%go=N%}&(qUXFsJevG^LA28=7GFo?yRNu z0y)8N{X(oG979PwZ+`f6|30qLzE+`s#Rd^5&x}xgjX_|ZwdH)>wFo*s+X2xL)nhR* zt?fR7a3Qm#B6f}y;_;N@HVrk23DxF#u9=)4p)#a&=JCS&h!0C*a@hzfg*-KfAQ2U) ztyI9#OOq*jVNI>BfnGd9TygUUpc^s3E^HD7jUbG>G^rh1YDO)z*9MC^tvTt|FUWutD@!+@^Ou7l4YyD2 zlXLr&=zm6P5$E^$99Uv!uw!`N3FbVIlsb7&&433ongzkVEC0zgG z8GY!Z-1&sEKIqKFCM5m%jtKObi0kIqWt`SS-OoX-00j$Sgin(LV!lx7@K$g<{fG(-^-m^w&zKYEW0Ep?i1U5KzsbcQRWcNn2n$%)^_(0unOs-n?@s`HpjPUPPE6f4)LC!>dc*58y2Uun9RsIy+N)iue` zWqWbW*T+`KlIxqSl$s^nk8%ajxn74V=egn#VuS|3ouc0pplTlzmweekun%IN6{9>1 zV(T5yj7s4{7xqY`T@b-S3~IlB?}F(&C!N~;hL5U8fr8|;a#tN51Sg}Pq@+*@7=f%Kl=u7IR{0(uVxWka#PM#Rb&TqrI52&-8SvioM7W2! z_kKyEK+Y0_WYm4K?(IaJIT6gM9V*#()pQbvy1oDMnYFI$bGit1#PAQXZC<+kCFTdI zk4ujrn%&h?$aqE2yA!{t+u-B0UJ{g zn5APooa*+6e(vGr`0F*158^wy|2?#HL#1=*AJQENdwy{HJp18-e=uG9FCY3pp9l4+ z{gZ;tQxoIR_vO2Nz-x^MdktH6`juf?v`0G>aAPHCr+>(*Eri`0P>5<0aYz&=`1eus zvIHNxk(PGwNhrx-Haz@ESuSG<55Cg54!1fYv`Gif@AN6R$i>@GOa)ebk$TB{qNc0l zwy9C{0`KX{tx4e9=PYyq1Q82I(fFBXD&;2%A_)9^l+nCA%zM8N2?H>E`woOR%JA;> zd+E}K=>Qqyia}hpAqlbhoo;>;;!QIPr#NEvFb+C*9;D{$#2oC$`%cy=D z6|6y2CHnB=nNz2Gwk9JqRe6w^RKh}}(5y*xfZLc@g0jGNF2WvViYHM!ydi0i>|YlI z%14dtf4shuJc*C691zRqS7Xy)CIGx5w@H*T&Ez9>=p16X!xn7LG82u1=Kv)$n;ks2 zgfg`ATPawlFg4Jx{jvtXhA!@J!dR_|d>vxY4y=G^w;ubRfF*ZXqOCP?kA2|{7cmaIx-g{mJb{E>51cdcR9#y^NAc*KF zx!uk?wI(<%YTE9>c57YQizbZ^04f8bSS8obd}sopYX`>0zaM7UH?RLzn!vp&PHgBT zgX9&FjG;htP%rPN7;nk8i{1T7<~;flsN#?Gf$Fu!JSKa;>ybIvoKE>BsYLbN072|?SosuUqQ}; zm!br~M&!B!!&sgi%j|eT77??$S}w$8bC3NknPgJw!XBMWVAYR9cI8Fzs1wY=CxMn+OB5?}K;o3z zO@@Qh!$eN<=*J_+&fdjV1OFVV5KCp9igpm?qkxM3lRH!OX8Qpb3YaG{K6VD@J5J}I zpA*S4{7Db!xf);w+(2m-Z=7q}`7Rbwhu^MRXKbi7Uxf;vU&?{s*v`L2qHZA&Xyh&1 zzm9ufsrUfGn^;Drs2H%oVOU3<50xZqddAb{%~tRFeYy37G(Oqp7E1yY#}_gzCmuI3 zzU$jq?Lzy8#PLrZy7ym?9u#+%YdSIHj$)3k&;Exi&vm9^KjfeQzUI$whfWV*v7K@~bp-l3W!b;37;%pdO@NS|>Jo(7N_rrR-@r zPvJOF?%a`*N+dHmBa^{FZI^@BPwASsl>PLhkUZbnQ=;F_Z?*PQ?krt@5a zfaP^oS}?~@@GlWF9VR97m_>YaZ4CR}l8K2YWz}jA_i+{$CAh*! zOfcvjbP$UMu`dQDVVd{|>~Lk+v`vj^Eh%pO_k0-{G5z-nK(1 z#~JQx^8|xxuFSO}L+zSspT``6^mjB4)XVsnvKI5Yj?~!}(K466{hSo>AIvzzlTnkp ze=y^yff;udw-8{fQl3{08P#@nTMFf6{F2##{(x$p2@9O+1rdoDR!nqs28Zk zmymJ9cRj~q@XB!g`T7_8*Ai>CGP`l=lqPJ1kk*-RdG|D19mtj^KNEDR*F8byD|yS5 zdo#^-&;Y!2IUU6T1e<}0Vb9Tt@aJofBUC!?odt~!0ZL##J+2A5tf_(w!tSDoW~nBw zB+=$k&oClRjo$Zl^U)Wn)q*rbvx>6hx_WE2ZcKAUTe^qU$JKx0@li;xH#<}-or-`~ z#X*Rr!R+R#4h*?d-O0-L)jSuE$~bChhCI-H@u)bZWaOOoJnK(}5{l^c9T}c`leI6dz74I#g!tHT!OYP-x5UB7*+m-!MA zB2{ywk$jgCkD+js%UXLzjY&)97js>|7H97&{S)?5_qElfj_nmU2))dx8*q<;!97QE z*Qb7c^OE)5IDo^uxvvUp2>Q14plLlJsaR?QOb+Z?G|DwlKt%BVaAN6+nxNj&@R!omi)~V4ziO+ zfA{rQosH$tynHE=-bz}w?SO3;`Md%IUcXkfTL*E4*4ov%8esBENrrRK;YxlXsaZj0 z00f>&Uj(Re(CmW<7^zb7OR${5&GcG?9zE#VZoy7!U1VmNfPO*2PF7uL=73<^ASEF} zaa*B)Aww@`NoP>xHcFJrAX{U?IORz;2P&_QZ<5MvK%-YF9aRDMMvC^{0_cQ8D1xo9 zSO>rAJ9St0)?7ugF1S8Xp3uP}I^DuYzCb?~mAzIC@X2UnhGN2JtL~ikn@1Oq$7O45 zd@|s3O#;qN`rP%ms$(kOHNR?qdW)7nC3hTM`nx0DZ_`+Kq4(Tp{ba%X6ah|<9IZ!f z^x|McZTspSMFN9}P<1klYZ9?kBT90xpA;c(CU(z%IROA}R0`NLJ+4NeU!}Zi#P0Gj%?X$^`vP#UsxY+?v9w)TB)@JoKl1F72e6q}rSBPA$LB ztTb&~V5&zRtMCn(4Y5{m4XnSR8mR6Jb1|1bSQw|3)vS}xU3I@VHQ%Z1#wK56YJ!5^ zbqH`>SLVlhjxDlj3}mH&O+t{y?!B65S3!s;it_tk+N z#1ZSOUvi(VM>tV+;cP^?+lmDjS0R!u*JumFVwK<8V-cdwX%D?^*7pGaSA}_V$tr_& z5nQyvpWY(nzE-4ZuUAz?wRg_LJ3|sS!r^TiFkuf}-hzDfNZT(Da9^aAibJP3kPA?? zYqJ(6rM$u3nx+%MnuzODwy!+5zpc~Q9rq17oEln6;%vkQ#%%I=BqRhnj zApQwT&FIRd|Hcp`j#DQHe8i0INwf&D(Ba86O)mu4KQ+KqGyfOFpixpiIkI2dgAXEr z)rr$`$?@tzWoajLkD>*bEUF;%Kg#Pva{G8kN|sJ8(_fE*=^I;>Q$P@e`w2LKp%VQI zM+x`dy;@>M1cp~BH!6=&4!1Bd|3W6gcN^f`4rq)p8frFT)7)>@ z$Sae5njNQNv5ib040Lb6puo+2@cB}_nIB*C@G07FDx3rIy9*9KMOFLOs$rfp-O&LU zrDCM|(Z%ii`fNTkua+3QEZ?jta2DXy(s^a}ycgAW)hzX9)RVoB?qB?GUamQe`CUQy zI7xEsh04W0jv6hmo9OgK%yJfvo>ViY&qz&m(D)i)_khiQqA`v13B7jrb>@@xQ6R4wTmXH=pe0|c)97;8sHS3$wS+y@ z)ezF#XY^TO-lZNTq^ZUjhmL2p?mm=R%nTWQK!nT2@xCVcEz}vDW(~ZSf+NCV*k!@t z1U?rGqqRrywM?*hTWIB*>x*B(h^h%@-4UGyeEnO7wF`KNFV(Y_ zfYl&}@rD+TlUc~Xo%kVu&8N}6AU-}y72d6Pa*RLIgv{P#-BI~L@M!lQf{-8&0AbL+ zX_C^UF5&ynv|I?9HH?_;(PGDdl+9&RUWk}JIG{~UQ5?>l%}%XfIaAKpf?57rdisp; zdKY(K5_6Dlys>lQ*b6MORB`N~Du`+u$UqieEnoY?KO z2DC)Kwr1h)?k}|ZnVNrUZoWZV10;gn zMzEY{%gcHF3knO%Q_}Xr)!%~7V7Gb0ltMJEWpH=(BA0TWKgt9*jLBm(RK90>$ruBB zZ;Eeg+Q?IR~MxrZdWKP=hEIz9nsf05$h9w99MEEO4ml=ZZAM>_M`k1LJDj( zX)laIe#d$=Uwy1ZE`eq+j*2laJfV%Yk!EE1%d}PqA1ydBTnEb&+|xIm&UFlWK`_cy zBZ|MozmF9W{o18X#^no-dn`f_2O`Nu67^D(5X`^^*2$QA;Jo~ikR~H3B2X(!3q=+C zq&|I6g;_pi;QFZIn#kqTdWf(oY5`L57!@Cc7pj|b1^n3IoEEie{~c*P(Ag~5;mL#w zJ}EIR`Wx(otb$&qmZfF2Z>ZfMp{Fb-vW!L?OIiwCfcQ!i#A?xZ(J=^v;QJnNBy~9F`nCXOy~S1^dWz~{q$jZG>g$6^@BZ!6W~o^ zxPdIUs4m*f)-?ULr!m1m;tsgB!9t`pFS+2C>C+VMHIQYw@an--$l!wqYtutApD=US z&&*o>XV#-D6f#cKGwvbcQNG_{g7Xqi!iID5ikb4N^=s@20k<&d%{QD$+z=Av(o$*2 zl0xjZocIzqwJkW0X76orOg-IEIClx3jLH}Il(i&ZFL@WA#)e>^wemFou=$;&+BM~q z#0aa3ToCtRR^DG^uq)?_000{wsik|)Kn!IN|_ zjKWnpSW4>VjqfQ^Yp{2Vo}Cv(_U;4P{k;pQZ}S;aanK%qtRvlDQ$30bleUHQaQZ8@ z>`NJ233ecCbF(tFxxU=GD*&Z_lVBSV-k=>Ix+{7mnYo;MItQQ%|{cKBI z@w@!!)pJtijXPdpQD{a_r}mqbV^ianm7_{4;7EZQvyx7c)-Q zdIB01AAAqE5Q1mZyTEW}LG1kCQ{eV6N6-PUFMJ`Efda7^d5rJIHLdEg?mmy4%H@mqWSw==!WtN@xt66H!4^O_9Pioil! zD(v&Y4mKUQ?)t3|uTkV%!jY)$oz3XIwY}Y>gtfLt_NT;Wt}9l3aH1T~CcydJrPsh` zBHWy8UsX6h>=_aKyyn!J=XunZCF-cp6i}%XbKLrC8|RFLsT323U;Oa<)DKO>CtMSg z{YdB`7@Ld~FvanTR_KwSn7i-$8%m z@B8!VKOfnJ`e5?S zSaW&z3-5PLCDyeB+;-#EX^F!{FJ0vm4E=p@O z8^uRaT{sVVEIB7ATN`sbfHNbp|`L0G>mtf&NN8ygwxPh7NMC~$9yFlE7`3|fePF3unKUC{ z`HmkjtWDf>%)@DAz+ z+=qb3=x7oxa37)p?VbAXYcIIM@M?ub`{3D-m%KbtaCQGc2&GE`_%kv1BP?YT zm{eU2J3*ah)sVueD#2=ZEz5DFMHy-8(v>98cfw}Es|?AS8=|h98pChGH5qQ^+srL$ zU&i-#jmZy^uzef4a+jC+70R>7_*nxDULpEqFh@>?X1?`avn5fbH?EG6 zJRJhPYZ}7hVflu;Eah$4Wt$e+yJ7VgrUu{yYC=M+zJkhFVMRRjQ|>P~CmJ7R)I?_u zLXw#C(j0!<1f@x78=K5W zL2wnjx{_RX!<92&7BS;oSRVkpr=HM}`%u|WR0o_iAoFv3@tC5ZCQEQy<{N_SgzGv9 zEQx631t>$0rY$;8Q?;#0@g?@-3-G&b`hF~vf7_03YeoSsK2?nOen)IFf z$HW49)!yjYt-MbJKK!#@qy|y8J+mrud0Y!|!*We@XcDTu6}9OBeXh%_DJju?jd5c} zfOI0^R?>N*pVA}(IvNh%n#}W{)?b{~b=(Glv-e9E<2l|2Ls9}u1a%*7$W47AuT80` zpX&+7Q;O?%S3?L)yBM74!sx&UExa9ms3+s4_?S-ur`%X~2lAPP%upN6QvG&RrnxdjPvN zT3y0^TJh;I>JsjgYNrQhnpBot!BW8>{`If1pUeLuyGmT8l-)QVu)8x4Em85B-q$I_ zwQk9&9O&x};OUp}(t|8^%#o_UkuCB89zu2%etaVaOYqblO!!@`rJUqWevLrFX1!Wr zFYhc5KDxI6J?HL1$ZRE}{5#97@H`+Ywm;gg6tCj(3H=0ed{Hh5jW?Uj@!PJfwvj4X z8l#Z}l-|8j;mK76^3QKaFIPIfTB`pdhQmgP$5g%c|` z_Q-V|gt40KS#!3;s_)b&x?oKw=`2v`vBIgW_a;3ja^?v~>#`+8~K@`ro2{7YX9gI{&(=YBf2Tm((V zjoakij~f<-^JuP3>I0P8gvk7Aq@@~_vX(pm3*CKpb)bGtWw^HKu15SG#k|SLId5UM zY-KXs+F}@GWJGG0d21Jccdi%tYIxna3>4Nvpf_7FtA*!^-xqX|mk>T1bNYI3?pX=% z7Flv3_;!gSBsxI!;;uq^6fJtWx}pTGe{T^N&7NI#rzKJ$07mbo`13rEK=P4akR9BX zlB`(ACAL2}`@dQZy7l9NNaJ625!K53-g}I{{L9i}bjeK-lYDgw9LHVSNX)TP-I%XQbr2~C<>vJHcJ)zaId+4_~gDy(1Hu_;>CoU(rCWi~n0A7+!T>eyYk zQ8A>Ux&ElKkoBC}*9~hHV*Xw#WnXW-OSa@Ov6c-{Vl@1*CDX-x_oiKe zNt=yk?OWbj0pwKbOVW;T*Z0-}g#4O`U3l*gBo*yE`N+Aice1z9X%+uEr+ocohmg$a zQ#JjyCASDp(=|r0Y6cc#42V5&ZB{kU!kb*y)aF;+Gt zh;$VYbqBruDL8LeXF!#eQ)kulskR{F1;v^pQS+ep2%B^RnDz(0tq{!m_{{D(q>FLh z2M5TvM=#D->eHJ>Eca`QDyGHG{$ew3+}=Q`0K3mResrR6cQ#SxHey_=Hx_LdWTgzm zd%h;DUCIQYb`Oasw1~#e=0)o zxPl9K?0vh&-?I>Gd4lwXHYZI1(LkfnMEvb=#~|atw}Ho%2gFor5e88K9`~J|Pv(Nk zf=h}UVyCgiOlYV^IjDa`w!0V z7z07~K9S)3i4eQEKx0#7mh#2E1XkeuK2|?xa=>~uLE|g0H`7cue&qk{TONUnnILhG z*eKB5O-fFuDB$s2d>`UEG+|(3(&C3{g49fKOw(qWFlJ#sITMA(?J*BhH&FiA^wgz57t9bZXn1X_1eB-tyEo)F$_L zpX>C4OU5a2x2O94<^B;;lUts5cVCr=tDph zAOYL#29C)RPXm5qzj*^f5I%huoE68xO^5wm<@pPTFV(*WLLu5%!rnh1OM~7!$9w>a zYs-tj>Mg%99P{O+r6uYyrI+t+*AV=O#4J&c-gME4=n%zT(QvU&iDB$S_!eXi7c>PA zPa*%ZGCT@IOvw}(9Q+7+Utk_Jo(1^%I+o5TVoLZ#F@^L7Ma3h!VN4vts6(`1wL4+` zHKSDy8*`)Q)@+;?$>|H>xjAhmL~<4lo*t?YkPlNM2J8JhgX0?(@fpEocfjx;Fx-Q4 zPDgA5NxD4;ZWIqVF6-dyUq>Bnm)B`$ay3yzb2GzPc@T-hAIOI!#{oAJ)X^Vbkc85z z^Wy*$$n3dgHt6F*tLH(9fqx-R)yNow)Zg#O36>jJ2j2I@k>$W?8wbT(Uh%~zc<|x= z%X>wtYIRluQLr_>13uLRrqRUt7C?;|`hEnTjLsKEqOnlZ!~wlI7A6}z-mCLC%KpP1 z+v~+=>G0|B+346<*iIb7B$3kcqw^E@U(^Wq%lA9$U)db)!({MWiU(hVMgvRc7LLp_ zd)E`(20pL*YDjR#)LqnZ$jG(~ZLQzziRHHC@|EV!Hq7QHnK`??dHeRQL`QFKzoxA= z=X@n*Cdzj+(RcL{ZDXz6RkC|K&+&Z}NCK@6<Ky|PL=`A$?51NeCMdpAK zGZP&4fqZxajt_e9(T_&zkLF{!%!hvJzyBD*gIQ))L&1nU7UDDGErX$aOn~Z|>>ufg z_8JxXJ|{6Wf4bpRj1FrkC;U5a?~i}^S47}JJY=0>#fk(SM*6#(K68I2B#y}(yyOs0 zMMOAuQvZKX_WUDeQWE)5HGcc=QtlEf&YyovtGxe`EbtkAhDr*ZTGq7R@DF7m(0gOze)SI{jdLwehhKIn#YR3h^b7c$6%T`X3X|yR6G(?`S0ca z=Z_FCpS4GV$!+=*-|ElQPL|^bFWJe2kuG|6WtRSbc!_^rZ2xzX>HF`Jmr+sZ&<`az z_~4>A6%3-vSN^xlElK-of4!y8ojml^@iGo^N)q_6k}*R1p8R#ENXVg8N6vMi25W*O zH&Q<`MeyJ6B4iB0-C^fkR{(pI9Y=KH znJKVqdCW_s&}&XhzQ4ZqA6H)U{qfa=Tt4{b| zAq#~RL?v*yPX$OMFIN+4l=?_qkv{`pBba>+cc!&-fY=bDKL7^GkXw8OCRSA8SzmZZ zzCVAiFhaclo(oxqHfcyO!UNvR|GA@m&z`(T{t~BxOpppvbRB=EYjk)V_pvifMM64w zo#*@bO%$U(zsu9jxtS{nZ#V_su!q&PRV1sp#@ZL;HHt8DGy$I{Stl9!^mrkM^iSZV zQNw%k(D`6*Ska$d0@mbX;9-#~lG^11v0YKXS^T+%m?R>_Q1I!?7|QecLhk4%jCL4# z$6s3xJ$R5rj@|>(cd(2USMCvA&`a`rcX6Bj`a2dV*}+@)zEs(f3W!!zjpEd2qrym` zp5hfa)y0|ixnH>>$^L{S?G~=TNONk@k@)9VBk9lq;1#|ne&(7z2j!P?XSSiO{HwE& z`$mm+T8sqmx0CK01kcP{TgV-XL0hM9G# z^T7~!V@$;MnX_ANdZLe7mP`yxZpKq4p2(Z>)!V#QpW6SBI`Y_RYLD4+;xoK2|8o*hHIRP3kkzkgUGAdh`C=KW{xm2X?15pk8R^$N zak?sF#_pxsi!87u_hh@DrWmQ$8KbSw73uVhOCtRQiYZ}4wM#|IAZLWx%e_P%!*}+? zm9Y|v6;aJr)JwuN2ZNSoT+ds3P{weoyx?Dy82Pj-EW7b8hkc0%`L=0oaUGY*smIbl zI<^EhX{WlI&)5`58Myqy&4e)(!f3n-^C~*mE9k|LghPkdH6glAAbMQEN#*pIxFKhe zrWtx^W=Ux=n6`QzQJqKjMMN2#m=SL=xqE(nZKFXwqTjmBDI9xf=jEtZ=;s&C6j*sD z09=02<+st6Ce?j`FU*NkKBKW1Q86?VWSx%yid;n8$g*!$`}dsb+~WapJ1}vPZ28CU zEwYmk8~SY61iNloM@b+3LQGPEbhOt*61EX%Of#(b60je*lwcPOl44C0CJ9y14X(uj!zabq7$=UuO`f z+~v+)w`LqW2E92Xal-o5+}U^eO~1xq;UiVP zXt?gqbfSjOSIA5M^E-el$hyn5dKqtc-76NR87m-)imqEEEms+!_mS)-N_8^`v`=K6 za^>zv)d6#~6kIO9dvHz)EoXc0ymf{NUXMd2fzt(dM+@}H6><%W>1W@bw{AA$NtNu9 zCI2M(Y{r8nsyX7TY&aoXDv=qbF^?L%eCES(^mgl}H#!$+l)ZJ%YyH;`Mc}rX3aSA} zB8~d6Ux)bWoxHbWq33;O&OK%45^r}t^8n0k$nP4b=RO6}kb+?<#5%4<8ve0&F|fKB zhY~9)@VOt)-O4hn#=-R?FnMPF8quJx8F%H+E2tI?zzJt7|M5n?O@iT*!Y>!nQQ><7 zjgxIYFuL^U2C}|V4!!&AKxwZUAN9R4$g}%Y-`1F|_HF?(at))zOUodadfKd`yXWbZ31Ki@HSyM3a;Wjx;JCf^d2z z+wL#NQj0iES~YwEL0&OeQQ5pZwC_OZx{zbu#uT@Z9%plME&rsR#@a9F+Hw`9Gw63G z@x^<*Aa*4Lpf0@J-VBM1wt@KqUg{5XSNNeGN7eITa^J!VoOO?G#xbr15yg%u=T0DB zQwZROT2OV2aS=7?ff)y{)9eii)($7TvG2AQr|l-{lvdUk*&B{x;hO|WzL}_YZ02JW zJD%=t;0mEnRXEiC!6qr;!EEXD?o$&Pg&*hLpL%AkQ^ueR4i;xD$TvIf>}f5GRS%{_ zH>-@Gcu1!Ansx+6*E2XFLPZ(&3%w9atk|-q05@;mY0ok}RC?L|vvXmnYyp4EOWiWN zE7*GJ9h7}#BaJPW^sE<=rSBd3eY`ciPJhC-(EH3T0%GiwhV)gIX%shbat99wr<$H3}3 z7-@wNwN%?mG-YFTlA2(O9KbYX@7EBUz85#k5w= ztnDEuCHua@B|Yk^LSA|X1|*U%XK|C`$pb|8z9*3@x}8%VD@mRx2V2u?r@0KQnr9G8 z&b^HdNJmxz{@!-;2bm;x)4`MN=%e5z2QJ7|&m)BE_mxn5RRsp?qzZ3JxBxH5Y7->A z7hsIS9`+Pxzu2(XpiS6Pu-U83LM8Vl1-d0QcRbeK|0^i5=PgfSgtKbYp&vw`q;>7p ztaSYlCzse=PXQ^b$n6ej=dUa4JUiz@6@EVGB2GoBuk7{x|9)`i!28*6dfuN9fEY_+ z0q!AK&CdyOPV;?~;nt8ju>>Ucf%K_1Z-I(r#Yi?D*9W$(joB$V20&WK!zXq^?C2g= zcW;13ytm>=e->Uq!B8BFA-ARP{FAb#BuHv@8U%Nix3+Vs=9|kNjmRi9ngc19h_4Dw zrG~$ISWf#m7DQ6@ct7rTf+4ihIhbC@d|nQ)rM^D~#9HM`Sjs;XCK^LfyPIygsbHny z#DA8!pjAV=FEwTHu2Hz^anavCh=uqC#q}39TjuAbnjvTBCmsnSA))=o17DUeD*_d= zNo>?K{DLrTZ)vf1ROGKyv6~CKTP)S=_*_Igv6DGrL>|R=9(`fB8?;kpxFxofFbW-? z-powYelRiPwX<0ZEJ4SW7zGJ!exopq7>d&a=xt4bN$k}^OOddg`w{k@llX3z)Ddci zO```;_4Gc)tm2vwJ1FVdLNaGcSk{;yuBEjWHb=khY(Il8Hr#Rh)~InROl;3+@F9!i z+dzaaI!y+m4);}92eovB@{x+W>b`iCT3LEJaG{Zhkc(i|*M!nrzX+~MR*O&*H0PEQ z-T+k-i}yyop;aiHtKpC&c$(E9$s#)?esURDf*bT1G8+$c>hE1#eh!pnkz_@n-SBrO zeRAl6+)G;#UVpsGg3JQ0Z~A32*?Vi=d(21>b3o-P%AY+e1l-SrjO9(KUyZ|@A!o*N ztC+;2FRxu?=8fqjzL-sG1r@PgPk~*E*87{+5OXJsbEm72J?Io~1_z{d#Sc)M4GYqs zrk5V$R!mMxQ~8~e09!HLWdhcoMNTjMMqRyPh8`P*U=eMDqVH z3*C-sZgyH>qEF?&eqrf4Xez(HWWeM`T3C>()93~5wwL*^m9h^#z`0vSeIsk?J5 zv|IhZ0qh{Pn=nZ*qZD=d(0Fo; z=#G9%{|_}XY*aPO2%**1+eaPy!tT09P`u_=LCzcuVYid&9>pDz3K$=zJVuWL`u#x zjKbLkE&9tSO$qH~K2a~l)xwiW(QD|h4!mOIgU<4r`1P9;TeZyitt(_V^JB;{m!9r2 z@;tl>QKRC9W$U>#=>OS$erR3^PB`j0sSD`i>R2EeZ)oscyu*(E7k~XCS$Jx{DL#j# zfo%kKPb`~{zJUIJ>w7Dr9298+*=Rliw$aTzD^?gw=WSfH?qPr)1J$L%PbyH3cMIva zp7}>0?qCr^16?g|yQ9)x)Ctzl=93Tl?KM-_Z9>hG(w0bi8~& zM3(mTL2t9k9EnrkDeXZS>W+sirto;@T&C@S$6K(@m8r$xNrFUWt3KtkCiZ#J>nU=? z-GvSr^;D=Avkr_*^tR|Pq%NTX=v-qjEVDjt?SNgq68OaVQ%tT%LT7EgIhQ}k32|XE z{}do^k>)qR-n&)5`IH&CQ&M)p%8g(&1|0X1mKRGh=4xSd^z5GUP#+YjXB!D*Bk+3q!v6m2;yWi#t6(pWFp@)xLxt0$M+?}q%AN_o`K}dn5uY|h04p<| z{But1G{q^WU3?{Hbyxx$2KL4jwaIMgH|yuinYQ#6`FI{8-<&!pE{ref^@|)oZizz} z7-Xv%k~{@5x%To41!nZsaQGp=GYk*;C+sa>^#9M>|Kd%1kL?4FLlygw!`U0oc~8)5 z^VcsCBKwf1ahp7WkDV_u)s+u-8mU^CzZEOU;}H<~z!cGa6a+h;bu_1zBW%3pWL8GQ z)q0kqxeSpm*REs95ah5I0DI0~00J5lVp5dgY{(75whmsKzDpA2O&nl$ho=PDv+_ld z(GH?GJm(YJzM3S-6n~eue;(1 z{k-gsN4xpzYFk*5R z&EEcX451fFvXJBepmPP}7pbR1#bIE^1bzWQLQecXCXiL_q;=BM-vj0XJ7ZrmcBk*2 zM@$unfBfdFYD|suu8Ux`2S4v_bc(fzu!3G_UP{Msb--NPoPf(HcroVb0BXZ3;ynL} zI{bbF#YOXT)ctp$0TN`@#N@u&1ibS(7EWO*1#qQ+lLW5O~@anIREdLQRy8G2B8KcW`FvyjLIu1*bhxN>c>_a5xY zZyhvelC?|z5qc7a}@Umtail@TzZSZAS6yKbrw*{0Ub6I3wXzVi?@n5~w<23l7y;=WR z{EI@b(wf>#%8G#6T>dW8z3+S}AJ=E5>`|$^LvMCH0L$3+V4`RM^U8qoS#U60ZP1J> zMda*iZIpaB1Dz2=J){F~102J;t#9!+@S!&A9hnkV+qSD+EzTt%&&zu?Br=W9P3;%q zcz)-gV_)8uC#c`Zc)9|sKL@Z&{2X8unm-viq5ZSr5w*k@(FO#+A&?Q`k`roX==u5q zC4Zxcoqo1tSX^RdTL*})&4H`qv7znT%`fPmi?%k+u#+N7i-EO><)*LmN*Z@drv-HU z3t;fEl&c596oUE^x0QbvBsD>&kNmq0I;0|hy~doouse4zrn$xYDRlxv-hsyu~O|9wPj+9s<9l!l0-UC)j!t3w)H(axB8GnDS`~SFm^LVP;c5NI{)UA>tA!ICNN@N+kGtZ)= zG8H0I8AIkqWS+&6DXEambA!wYWgZ&LV;M6n-t$^()t&Z!_Osu;-_P%l-#_8a9 z2}Z;mG-nN9D667#fHbGuC<+pPeUHVG{#rD;p;a85ID932tQSBW)y91YRUlNhKwKVpr)^fankxZ z?jNlmCvR(LmOZ*PFk0*K07w*~mS%^$ZvadYhRhJ(ZSjnuxncq>xQp_}&ujN}JecRj1VvJIK4BT1g+SN*|8-)JNDD#kKEvmt!7dnfG~F z$ZvY#9c%VxZ*x;N8o=5#3zXc>CQ{w~S%mXWPBG^>i9jr;iH^_QQ0v-xZ8|@peZ+9}PAf)8#mG08e7VFF-Jui=f!0~T{R_>O*gd>0S*_DZX_6aRA zqaM;^?>${hy1x4x-VdG9)ci!(nHUUMey0o_GaFZPipJ(P8d+hP6Pr{6;mVNhT+MZu z9jC9@=a96LJ_tEyKR>UPy!a}gVflr9!sbTpRP|Ah=KxSMKz=g{@0)2(1NI$trg^!l zu)7*CE+y!-ww&uXZF?kSDTdi~-^n3x$4EfIl=}WZ#DmBaQ0hr;14HI7{EFR#9}T~qF@#lZ zeRy(9GmE=dhG6^L<66^57NiBO9=m^x~GRRu!i#9gE1!8vf4 zkzIG5k!T9snUMYyO1qEX(i_ zu%!Vz-c!yS{ymsJ5s<+9a=Uu*&TEgR5x{|C+PQy(u< ztbMy9T?6!?RPdg*gUGQb4*M7W2j3zCAUg^yi)3KSvq5Vr991ar(8w341w462`ztB{ zjoQPv;d}pjZ@(6MrvPE?n704^h2Z<89wG#A6QEw`>=50m@SptKe?H}(U)3BX)Cv-o zXPvg7&HL-$)rb&Fy84|YVb%&f^8^yZuRs6iZ~pPC8Z*L2TG?=pZLAUpyuC_DIAJWQ zAeC3GuWzjWAOG@S{uWx}_$|97-~lz^+WWbrgWAMEwFU)HQ^lr*jg*vs`H3>Du>^vM zuyotTt8k|xk+wt$-E+S!+dF@IC;$56&};es*V+WLc>FklJfOg_Ngkhm{`;lpIZasl zQ>JNGf8R^+-tdg5&(DFsw6q+D=FY&F((|ZRgj%X@G`=5D6y)TI`d^(0noZX{5h%TO zy=W-basX&-C)KAJBYxY|tnCyFQ@y+(ji{aPOKIz^h!f5+D0 zg%kX5**cpu#>y3sk3W530-|Vd&f3fNM@YD=q$`%kcoFTw1PZ|g|1j|FK$kcxGJF`( zu385Dc!jxAJ9m-6P~`1N-JyILCAeXx$sQ=ol-=r-hE2e_NbaEX7JBbB05$mO7$_wE zZ-_k_0Da>Y%y!@piB^_j;Qi!LQtqtB~g96-{#@1aoUji+i0j>s$qr4!=+br zzc@Xg9x~USiqAPhl6L$~HV$cLaNM`c)|SUx0J`7nlRbY?DB??8`pRj)(@ExV1@7|x z@@~iDGcTSt**|UzyMf<#gC~u^X{H4Xb6|XL8MCz=aAuqa=&3bXARjyoSx<&;79We} z>hlK7LD-_u&5F?-&M8L-9pnV&z!^8BRu<6IVP9NwdGfKjsF)VhksYTBg zpjK-x`*jgDtwr9r1@B_`(W8`CJ$RUPl?mw4d2eL#k4B&Kf+xpcsKzsVi0&)MzXoC4 z=nIzwk7Wx_hNFZ-H{eUs?y~gWZ(|+aO7Fb%*#wcC^s33J<|GX!t6^hjH#D zp*2)*@VjQa%UU$r6sA-{Nr9~aY|nJjuwI>;WC-S>6^yfh8-7cvi#>AS@~NVa(a^!F z9)A<{WEu-S-6C+&v}Oi=KPzh3&Yr0FG5>}4X}z}OT8r4bydIsdg2Lrg`_-{>Xi&s> zmTsAb)~pFx*JEcWkdm-Z5QhlYaBp2Az}4gZqp>Eev?1iP9M${X(BLM|#bN<1SIqDx z$@OvC6_9&ewEz>fb%sZSW4k5VyU0BVd>uDZW}KXYi$!zNEo7i0Cn0=Y-?!rl;Le5~ zOQ|0KfL7d3WX{#dd8-->r`k0}jJWcTL{8yKKNSOnfzl$)U8F#MOR6r$uV&GqpGed5 z(a|86S0Ok-`gkJ7Kwt{MKhop*l-b?mcp<++{lW2OMrZ@!4&E=0{Y2a3ATy&%qS6p# zzt!>;?49e#-AETO@=5CPbsY%RWptUW}K0P^)Y%r%!XBqSwHbofw94SS10fOUW z9*@G-!4vhns#lmZ6lT@owirE^lXteyd%&ol=$UynFx<56W3(-OUL&L?5Fa=>15>Bp z92WIvgAqIS@4h3w`ZO3q%&R`S>{$YL*8=d*Pk6?IsppUS9;q#cKrtK}RuiG^vAH2- z-3rvA-Y1$5eJYO7-u!xhzhqYlgmUZH@*Q!&-kXNqcF@e7cJ)gP+qficc*xZ}BX^9n>RQ5;6|N_S;a^418XQ_Xu>)XXSa>vb z5f{+XB<;*+mj#{7nQcLK9vu+2A7RC(W+%|tr}}Mcy({<3xS|uLmW*J37{K>XmJJP=BRk@^`YvqBJz zw4VSY8CumroMQUQX zO|n+0T^xFRldVJT&(04=8QWa-A6*@&a6Y;${0YWE8AAF!7CJ#Y2>{*XqnPc5c3)kY!_e&0$o)o;xne-HVo5FOut+0$ z5zOd_F~;YM&|AH#|)$0(oW`AsA7d?;4pS&X(Z7YeaHeEHIbmv%E@N{ zJ7liIPIlw^R+Tn>SNhzU)q$}vi!Hh~SEWCWf(6<4MN?2+ls|l;+u=IOX_umSzq4v9)W^k zd-sdsHce_%(^A(xKA7_LKEsX;pYo?WGEoi-|FTJgHhXM-qO-NXNfyhJsa}c)b;32g zkrD0sgXp7|)&IVU1ZPc`$l7R!*ih|^r|8xUI2wengmD&Oqx}0mFrfdN6{sHwL9Fc) zNixIV4KehfM%hdH_Qug#LYVm#1vFjJ+D=jBr52<%giF{DsiGMeM;avOC698_NA7YY zkIu%7gpHut?=UIs_C!z7QLZ?up^$zE`XXxBwGtpm2^vnk9iS?Q7HnXhE3jC*4}h~Y zsKD?P9v5awSp}Nr$ykydXy&3?(DF^WMOh`8?MFz6UI4sD2B4#uzhVI9GUwA&S|1Ht zmIEXF$LLS?v(tyYj*8B9-KT9u$pWbMha$HaI`9j2t_8j4KJBMP@s||tpsp{i)Jy4+ zN3&);uAc79N74|fC!9%gyW?)3PXlAg7BLQ22RAQj7kr1F?o#qJ--SX=kj*65u7#VI zIRtT6WRoAQ4YY4GxUj;NVfbFU7f$%2ZuM$IJcY-Bl=*ZW`He0zGz$;>k6LWRF@#I!CDkc;2mB(xTu~bBYpOqS zB?GVc2(Cg+UiM0pYwTLb@Y^8(!7xP_GF5M>N!`OZVbFL-F|_Cb5>Z7_Cz&8dxd8`mg=aJ^WPZJrh;2T1AKE z)I)yM>?wCkXlQ^N%8BC>H6Ftd07T3zZL-b)}djzD9`Gqb9z;Bwvf z!e#!0`+Fe+us@16&6J99!Y`pH6G%XMzaBK(^0kjc{M|9jYm;&270Pz2#WOAQLET6C z4tUALlI=U2P8!cBY7-6#RUHU0WY;6ZD4f$=J2`<#7hC#vnVe6Rd%> z6DzRe9)4*l2a;sc@XWfywGe=F(+K4GPF@1wA2M~W$u*~_0YmulfPW8$u zZ2e{z}Br>C)6n1UtL{INzNRJYQf;Z-!Sr}@0RYLJPD5* zTTITUFQu~QjMN<7a)3l$!74_`)UP);Uo8oz(dJzQ#yLWkZHIN|-?z&$w<*`NJ?#Na z+vt9c?X10DFSM)VeLeZD@L=tC#-V`)wu$2o^)7NSc7P1o#joonrGj&l!sfsB8f`NE zvWd#kC4AO5lV183uJ;a*DQM$&^o;N=FFhWX!2K2U$0EFMX1ntj!$s$Fo6gU8mS2x4CJ9_W>9WAV$(u%HrIX{qz03r6PDq#Csj$;-Dnq_S@7%z zsjI_SC|znG+~~JOx0_&D1Q}ci?2{>Sm~h1p1ETKtPJ`>DKKQz8y^)b-2csj~R^*)N z0(qX_02_g|2Jk%bolm)D9xstyob@|@XOM6fQrHQ*K5(B4Ud&~ukJkrswVw}NCR8y$ zcefrN0S2{7hn>{*cr;XnkA}HC531J%rA5RDe{lWFz5Gqzq6IJQ+FUt;$tqij?fvFM zu`LBIbETk2hgnMn-pQK}tjME*;H!-s`wGNw{J6>>Y#tmRG(+(sbHrxk@=1~aDT^iO zeT74vSqGSS%HOxPI`#WhggP2cfvHI8^4JsP^ndMy>PyG4#;C}XXN#bZ(ju9Vw10SP zck0)ZN`d_X-0f!fFr_7?a7)XWkqdu2)ue_w5D<7bO&bzNYfV*9j;!976_ftKyT$C) z+SKco-i&+iw%Cv#+Q9Z%{q{d+`$P_S82m3OZDd9lSiPlsJwUXTq!Hj8CPgZJm}CfO z&mmxy`@u{twN<-#DUbFeXlyL%4a;v7q5SJ~y(cp`P0UUA_m^W~b~tiLb?S3}c?0VC z`oe2pS64AFfQpNlQ2(0mGh>-FxwcSH5rI7CBA+9563oR2nVBoZO1R`Ofz4tL*f2y7 zBKx8ddRh!_Sb9AKQuw!rH5RzE+F4}i~H z^T2EKP6J@(dsGfX)ycNc=u2Aquw+5G8}&-b4m`h*Wn?(XLuyPInBUD3FD(EjX@SuR zD=rZuv+U7PKq`TVGQ*t>4N|e8=t~nk571b$RY)Wc`RrUZyr6LG!=sPD??vfUFh7w7 zm&36*J5z z6_6Ly!i>sGft=K=F)+P@*)`(!kU#n#ifQ zI*5qi?pr;7r}!vtr1(GvqZ|+?9297SY;@wnACv4og67dVE__Q-+7Cp@Nba^N1MuL2Ykmy>nztC1L$BqnC$Z*3#kSqLeTXgVFWv zM5Ke9;(|ayAlDN7nIedRR;w@=Q$T1Z=MBFtS2a}vYKS|T=Sd>v+bIJ(9uc0Y{ zHmBDnpo4FzB(pJ-;kKG=2aB5*w=?4v5z%*&zdb!8N>`UW`N*FC#;|ELErO4DQ>m^nR$ z9$=?>oyC1FqyWf|aZL{4GyB0Z-xhB7HP_LBb)=Jmc?KObPjnuCxz8fq$FDGMF8}Cz z0l4}&uhcuFLAZ2^q3ZY!U9xdh+#F4=z0URHjiJI~=Z%NVFA}K8a_ZF-GNT<9-%60S z@Y#Z*P9-M`h@G?b$CAHX=i=csbAc8gZtxuT$H8W&JZ8s=yo6$wA&a$qeN~yD%ku2s z>RShgsMfyAbuGfRH!~Z#3#IZ}9Y{m- zEvD>eK)^5$%%qJM7^OH%VUxx)XLtySqgx{{%b%K+)((`IQ54V0B5sB^+eREsAu*r0 zEC*0w835n4O?J5X_LcRLxI|m&cm{O70mLV;wWoot{b$O+MZ%T)_Yj-Y!m_4x$dj85*YTDrOWF`@Md zl5U`v;tK&Qo4YpcYU~Pu;V>hlvFyGJaKO@|jrOg~xw$8Oof~b%4Nl!VW2_;hK9}OI z-{}xbr(fOkG~1LJ%qQ&L&?wYEG?yE{(Pi=I9@Rv4y()khByK{eK0Ex{i~1FM}qKK4UJJQ-zbv? zr`S7x%l>SfpX=)F2;B!2c>awn?R8kJ!6bja9NzIT*PrYjX!!#pV4g32B7>6rNDP% z3`j!pN$Ai2)TDd4k)7ni`f0|Rntr7ez?`}jsH_d3>bg=nvYnbb*CO!PX{$fjS9CYrx29f8o3h;LC z?;8XuPa~f*tnyU{@OF#GN&#iplUX#(s)Xz6YjLQMR_7fVxzeiwhrV>lKYPvPer^^j zDG6(BU4C~-z}HJ55q5>9+`*hHIm_ll=@8%p8IHcq>IOMNONK@U9QL4DlS#&W!(w)= zz(NStUMLe^<#FurAzPt3pQj zqa}{udw5RXN5MK=>5ZAohWL|TXW&I+R98-&PKy3or8f~K>7g}!IJPKLTIev+{ybL5-Pktyev)M;RYDm*) z9py!y!(HInuO@IGCYN%aDq7ApJNAL*it5gwX!YKZx`Q^UEq03ey*fdULYam+JF|GI zZF6v@3_xJZtOVZ881;jhl{ z>_R)2)sTE{-HJBFCW~r*-`@&Jplta`Vs=I(=7_nq0q}z(`2vFnmY^k4nyr+`jAka@8#xpHh^K&T zp94MJfVn(fnD|uT>#outU;JlE`f-^(nCD*!b;Unm2H{tlI+YZa4j?Iwb}EY>O^DEw}@sljAskW(nREO;}%&+%{0*x~c9X zNI-Vh$PpjLN^)$Yy~sc?@nM?bVIKNMWe^`m`M*h&$qUa{fBy50{QQQ0EGG=O#v9Yv zMeW>-taYlM&FGup$?HK!IH@RVt?2RHI>kcA1JEfai)B>LtZDk3iQ$Cv!ie#=3$4XQbLfDpKTz9{fn zA@Hb@K+-o>lf*>W!~gb+d(W`qfe!8c=i>hOV(>-?9zT@uy+6OKN&D}c@|M~d;Vx51z0#jbXQ|3=rwrzL}?^1eVkT^yv;Nn^H;!hKo zfB6#_i0&1vhvWza+E1W?ayL=d)wPpEdu}h=AN-7sSNQLn$XkGLCIr}8HasIKxe$?q zJHSE0#eU~>-<}p26|M(9sF0b-%Lna`cV4O9{`*tNjBcIiEz!+@fL_e_&|%|ZdOzKH zwV$`BZujopDD5(ZwrNX+r)QLvA<~yH2$?AU-yhROk~8zV70VGYu1yvBJ3y;!inPbh z$?6K&O(l6ULK+YOU^K^M;UXfl063BYQWumgU#{McFtZvrZ*bPC1&uTII~aPauBr0JH_Qcbs`AS{1=ihM&;kj? z(+TB#O#yXc346;(jL%wxZAO1S2(xjUiE$9)voLJ4kx!CdryUJ-!rMurp&f88cQ!#C zS;-(u(!*uoL*#?0j0S4sF^Jk+Fqfi3n=WQI&-C!9>bX;N=$HY91H*85Ky4KQ(A(~V zAb^S$f>sEi815maM4kPw?K4pBRbuD@ZuE7~g1GFgm_-WR&m%Ct`}y?z3LQ@B7D;rE zt?dGSA0-l^&TV$GjZq2eO2Tn&fU`IDneJSn6pfzk58bC{wLn)xADi_Qc(I2ly=Wfm zJPvIDjsftIKiq6QL8AIM9jJF%Wm&a{*C9Pb;J~D!e%HfjBK(=N`!@?4e&j#|g1NVW zt23Z|sq-S;WCH&Dr=WaTg4A;m{CW@7XXIED-nS6GC=SpKAS3MV<6dM_Zk+Ck(VL4o zV&_UaYs0u{Nx~@a0G$+2kq5-%RXdd2vf&KMOd<0CFo)?503DN<6PnxR0zygaVI&)m zP~!}>`sl6&--Io6bA|cNfX%PpXpmRF@kd?9P%4v^C2750Jp%bqCi<6|jsN9_Xf^=X zW?#UBaCLBcJ^~%7_{Ldaj<3`cJQHMCS;!0D)!#W|!h#Qr%7;Fc>q5j&34KZ^?o|j( z#G(&ZK0wd*x6oNbbp0~^8X-(#2AY5wfDdZGuQnB4u^os>6agdC#t2C?g(3PskfA0p z!0>&5#%wzDI?PV@SM*2XpoZv_3A+?1#%0l2oSm4+YLOsYpJ(uW6m<+BVf63&*3Qkk zg}X7!FrWfjSS^r}QEje#6GeN0zq!=u0214ni?=<|)o@_(pVg>pcGsd|Aqlgp_%gl- zNnt(Wvfp8{yDMzlcLC_`i9ZetPJd;dFOw2PlYHy|ICwMgQ5324ZvgSXtpJWGQ1v4Y zxcE?wei%jquWE;@xI6n@6+s8mXA~N*0X>wuekBo?-JKS|Hc7lIb7=Syu0(xsm1TV~ zOXFiZYbhM$+UM2#$8E)>u;+t$BztEI5u7tH{Zl+Ea`{qAenZdXIQy_*)>bvR|jwbT#H><}VWpg1hU0`e2k+HChlA}c+eNANz*9pAb1@-Dmf3%}xMQiOkmzf5CzWG_MxTS?|+h_M&x3sq}K`qL8;TW?*t9N7M z6YB?c9u%U59yr%52+9V4Xsi~;e4=mq%VjzyF~#VNr_@OLWNVh8bQXAHt}TN#Rp{je z4(nN4@YZZ~x@w)a(gP%nX|Q0Juiy4g_HhsuS59}^WFby~R3u?kX8+-?cTYmvK7&Ms zFX!-BzfwNz2tn8pmGscZd@!~o{bRAhx?9Ap+#Y+GYiCoxjQ|#FZss#Onoyw&M9n;~ z;Fq2rEovk`?TW@DmGNekwj_-IN5;$g?|NW#x;F{QVRl~@LJo=TBVEc=Um^Q!v)c%HlDCs=Z zPQy_&3pcsl_k9Cglb`GE%cdt9x&38s1z0o8r@DLG3Fc9c;ta88`vIA$IPC6PMim$g zi0p+qs%1>PQf*lYu6ERQbhe3fm5*fNM(Ag$k3!1kt}qwZoWfG#7gVg7NsPZ8C`tQGe@#Myy^ z*^vpjiUCYwLTPs$nDtlEiVbZpZKFG!Est5g9}5&0oqVg#1Aso}=-GhD!^17R?o79#JC+{I#G7rS5Fze|&22ceTrIS`BXPf{NknXL1+mpeprxZYaFi{X;0~$NuJq*30In+UI zjYHGRAC)jL$YX{k&8%Ul>&;Iu&Mdl`E&V!$9LVx z$qrPsuRl`oqq`g$g}r8zPXebNj*luHy~jm6a49N|Bs#hZkhtQ^{|4Pf3(;L-9Arrf zBwLFbSeoVAp*4_t8N*w>J9%`paJ)`yK?MhZisiT&nO!NAn_aG}z{E?+g9sw&#YJ6#Zkvb4So(R870xwz1JGJ128=tDHGNCC{)KAY{vr&(ppq+JUvrbz zND85)&6Fk9L}ILoi@ihvuF{m}APN6ze8~n1An3Kw7}=#arys&^f_r%Mo|#l0yZOqU zC)dPJU8LFidqxjGjAsw2bMH{**Bsoj^P7xb?Rx|fHvf_~80YwzxB#&gr>-$HTG0oc z>$4mh0&KmjU}ceGxCUdf=nmImrJ=iSy&w0t-W{x?b~t~uqrUS=L-BpcpQaBQr;~oU zStuI!Cb-O;R$T^bFw3~i`quac9?>-qDd?Y6WhP`M)9p2_@L4mv*%R$L+8=YY9Qa_D zBCBkh0%UgDTfrxBudQXwf^_g=n`rXXk9ssGm!DV3-3L_JpJ2qx*DcP>KzL1Hn5^kn z&mq|>t=*%VQ$gFfZ?0)`P~q4t9Vz)5cktBGSzX?#RhHG23P4j%`m*bnn}9Kc2Ootr zH>8|V+3p~tz0#BiW}O3gb`f}x6!d$Ptgja`xCnhnvKy=u!EP@3+3eCl%`W@JcP%b5 z8fXo)8MFEEX`m_przu_NUoBXlpvI?I+aExcjLhjMxp(rc3DDO&hR0xF2KqiWSH+3Gu^V4&Abs8F`Z+kLnXk|ElXPzwf z-cU-oI`6=o7tFKb2%7dfuy!&XPptlkNG{qe);o?BA{GotOa1hQ@|_`@yE`h(ZAQ-G zS(NXeAEa)!n+(l`S~bPYf&;K33~jLL>Ue%>5bO`~W;q`>fkVTQA+8AY+@PAwmyk4Q zq&_U3HF;S+{rRjJ`MwxY+k|LtJ=CMMI(Mxi6c;~I+&QGxvzE=|J#z?ck9a@v^^yut zTo39oL?@QqEak&ed4<3Xh;A}ii>A)3hI(?Rz3={Etpu1tFaxF>$8L<>}H(K$j(lFWdp zxC>Yi(}SkrHxUOGwD(Ki$)l{{qWC+(!W z;sIlcU1os9WD0IH^&Y_U#TAdQfT*zsiZ3fx)f=CbiUZFXgyX>DadFkTgJtR1Pap=)U5#eij2c$0W}o zJfDW4*w zkIPWfP=)$eso;(xXEYa^3T9s-;5ug;1(eRDfB5~UiN+wKnZtfBR2-x;3mt#D=U@ok z=+X2LdVCesPBbAd<9sZQ-uf?8EqIXll5hKg2s}O(k))eHp9hwfwZeXsRpLz=q316o z5A;`uc$7cdT!*=?E#TCUqM!mikK_oaztu&^8i2rm5Ym~vZf2<)g@5f6u6d_GG%TtI z9#}z^w-glg5147>6+SgThH^uMCk?911^42>;#07zH&AFmlzMPgIln9&Ol2QyoFxgE zQU=e50W?FV_X#pn3%m}+tV9uTZcKrTzt$&@6K^KVX?)#(&AZHgS{B1obWHxo+66KGn8A~1oiK!BB;0$QP$RZeS=EAA;X zYfaX5&t`aSUAaEdd-K)_n+#$ke|Ev9q3j{ugHu*#k1c9IzHBIIvB~+ zI74wQNpMBXUmdKEQVHWyyO6iq4pCGEL|Kz7;I>eU+zW<#=^MVE_^bFTjErb0cXxy1 z8U#f6-p!pI5e@ts+;ZrbPH$4rEL%7yU8$&WsCj!MCUrc0T(&a{(n*auf9iM$OzVn} zNl)H5RPk%49|jJeXS$0ybNv z=5-Yg;>8EzEw|N1hp<3myZ}C``Gu&j6zI3hFyATnTd2+MHQ|GF=T~_cw>+*vx76FU0iM!wDIUC71LS)CE*2ZB|Tna zfp^3aMk>}ro78H-$o0@vap+3Yf%wXVPfoeXb9h#aMD5r_Bxkn)FbqRKaO;r-w7G!Q zhaFI-OUAm}e~?6{dvc#UoA2^wf(QCBiD$vshWoly+a7R-TD~M2XXGBkITAKmJZPf~3Sf!AJbl*rz4qvQc54sM#li79^?sfRUFODPc zUq%|HD(|rcqf-yDa|%Z>_bVnr^ww>dcJ$f#g8X{b%0N-*f7ybND}h1n?a`OqYnbAu zp>31V^Qt?8^=&YARVgK+LsY>|E}%8j4|Shx&%zpJGVG~df%5-SB%sx8hMDtJ>Shjm zrqTQ>KnRDqr@;p|t;op*2yi%4Ojuy@P*AZUV#bVH`!tk-SD*PcCn5H<>q8dr`yl3x zgs!%mbhqZ)uN*U~B!NylO6Pvme|?tJ_6Ydu`3=&zQ4O1;at3Y-6Qj1edF3yAx zOmlQgTyzQmBe750WW`wMo!2xL7N>2&(+2O9cN?xExZbg&V($Yk4uX5lgp0Z~Bewq^_hkPW8|KgW_+PSN%0>TV!{lm^d~AoN;`lbA zgU-(@OD2-4kXt~2Ox5^x^thfF0BVzp952%VtcZ1w8(DUGbC)KG{b`|+f{P&YgNgI* zufiDj$SW`wL1APHZA-o<%wlP9x8(rQ@Zb5@@c)0|Uz2_k#bfcT3Ip&ZC>lxfpKx;* zG6C0q6KLJ6t&QG2hOBAH75bIh1;;!_%|#Fs+t8VrDjixXPSSbQ4w$b2M+X4pEts9s z&6$*ginTuQ9QKR6S98w%UP}nukYu0iS6-zQ;9L@~71>eZ3x+`62gtPERaeEYhv9Hr zcy~tfL%zqjP?US^t9;R1iwbVGpgt=LIW05isVY=pKnc9sY~%!*Ck!AYm4SD7;i09h+I%>?t4@L^l-Dpe@(MI|-S-MwB(%m5xAXka zNtik(687!1!h>twA}5puU6f~>L#_7u$JA*z8d7=D|Tl;dwL)-zPsCbr>`nW}AY{HxkYIq`4|k0cl;*2w4Z0>vv#m&x}&iwBc;Al?*vZ+~muAp)nXRnF-qJws74@E)nyL#|Wxh|ZW8 zF%-R_?hvraz89h;dP+^JwM6v({qAe+HB!oJHkv0hCMJbMufIj3CUU{)C^O9I)?r#` z7VaX;(1FZ%SS=$+Xr{mv?io(H@V3uN?B8Q z0(0=xu&0(>ICuB7lGN!#uh_9GC;KRMQe-~#f3@;lueUce4Hp%=Q>T5a3A(PcueR}r z4-a(`x{e`KHS=$gt=_SR7dF+5M6NX-^tW>6fte2I4rSOj0EJigf>M{8P^Qo>Jj-H0 z6ZlGYca_fI|AriUA}+`e6k1niat)gkfF3MY0ZbnM%~&4-C*x;e2hFwI^rSR)?h-sTyv;Tx%;ET5fe=XoCs@q9+U&sDB|vD4}nwd7Z2axf;HD!l=BF zJ*#twv<%sbaat7>PE%tk^UPDwH*?&c~ zIfSR$fDk_Rrh5e#VKjhGQX@b<5dszPNNG?LQqBG#tdES~R&)F`qUQ@dM>mvpnzCfB zXd014Dm<&~7JfNGqm5MqNjyXmOE^Z_vs^FR$Xl=2;W3(yaq!?lL1;CK0-^UPD4=Uw z+iC&+`)Bd~k}|ZzhhA&ml{pmJD{1w2|$`TQ~B6e&u;TZ}nf* zsHQhzxwk$g7XibJ-~L>Og1FrIu-sb}BvR2xmg z-X3Hl;rb?E%=P<^`}0#a{2<~(%Ir7WcvvV0lnI}>2il{$3Uo{V<){4i%<$##&v-iB zdV!$a`}yY6Wr$yU7p2$ZO5cz_2uQzu#veaxcRWljgckNlMj+Wn3PcrWBAV9|-o{8O zQ02IKYU9%V$5Z=r;l2I#;Fnv+N;2DV<8rrb8$pA~QcuG{NtGV>V~*8-@sUh~{cCqu znGl!$`97u;_#JeLk<6%WKYPPQy~EE(`uUcKM-cs%RTY0eX}R9q*zk-%JD?;yWXE1`rnqI%~>O(Nw#flpCJ%9$D87LJ0?+>c&p2K6{n%)Q|-D&_!HUzVsJfvy_ zL>u{X-db(Y_%(pnrVaAi24K(xbjmW^6($@~?3z^+XtKfV#EYh`em~H|>s+ID!Z*MZ zbG9LDxd)icXi%gXh#=Bnszn;O9K%#7Xzm?anR?;*&x?m&$wcfy*0+sNaMCWIQSxRW z??7oY)hy>(Gk{zEN8c->PhhFh*5gv2%W(Ww+74i+-**^N5oNwwNje1m(Cn82qb)g1 zq~sa5VUp14QfG5wAcz@abY5D2# z@%yLn$9>?8%qAn7viURY-h3y*dg9yxTcY%$dS$#Hg*h25;>D4(%p<%Z?rBO8FOGP) zI0UPwP^Y@jb^J*8lI7=DxAtgL=Epww+FS|KJnNkLR1B`cbs-XrSG&_m!k$S3z`bwS zs_$y4Niw*L=scAvCo}q?pWfkWI*xzq_s9@|0j4Dv#ESvJ7kSY0zXU3h8uXB?DhpGJ zfSF!qN(A8(g($DOpJBK{oH12%#)~A{ih@AwNZd=2izd=loplSxYuA5;8J+{gnAws; z?G-{JP`ht z3Y}FtD>!g692b5#w4QgoJ}erJnKicSFnhF#5DpT>AutROg_#mh#6aw<3g`J$W@M?p z(t|psqub7DL{c<1aY#4n*70kk*nrSDq>?T#>V|1c(~OipNkB@-D4cO&V9Y(E5rMdgb?&-F`8wLc>-Wy_ui2rg1Ua-FxfWqK{T|D#vI!Rj4+SA=ug}hG;%;qt zKc4inqzpJYc^Bl6z6AV|`rSj|3UU-pOaYr`{RW_!sDWQeU5fE$!rrLj3AQLvvlEXD zNZ?}MT42@L0&zylsol3LB~%T*vw?bvW)3Bm(8p1MMVbjU6UQ(2Ee=RD!5b*$+{458 z|KsO>WH@&d(-5pF|4Tgm1RhhVo(aGYv59~3M4NBsg~Ldm>V_(XuWXl ziTy1!rZ8FMbD*+an$XU4rDIU@T7^O$tqpRT(wXI$-M%m--hl5Q)*N5GMOd zVbVzql&bIff?^Hi=TOES6%{ZAF?ic7kn0#+a*|Y$b@j_busiawgDh05$cSeY97w58 zeWP0)ZUj$YG#lA1J3xWXi?bSDd$$(XoalHl2~URntA;3YxT z*#PTe206o*rZzXvTF$8G=a;HovGeyGrsy_NZKrtwh5857gc<^Ct~{m8!Y^Bs`vvtC z3>-^hFr&rAeK3}avHPBci^qpm4kHzxXrPjszX;XZ$MHihaEE(c+F`}1^aKlN4)ZcE zzd4ZxfLI*Z1@xCkc{+Fs;rdKmOW!=B&oY8&>D@slcO3Ne+`ReLaC)H24WW@X4ZX8T@sk9xc&_4ulYZY|5mf+z ziHCO>HP^DhIC}R`C$^6Rc6l1&t#52nUKyKCPgg}Wg5sx!cMwtm*Ro@A9g9SwE|D^ zB1iV$WK=Mi!BT2{b@pabojGI91^K>UB_Dc|-1|@zbvEtV&CZ_4!BKTiJ5ek1#HqdeWW6E}Cnu*FV8>47tF$6xeo>X~VT~SKQM&TUA&FREM0GT4 zn9S{GhQU01qxq417sEcD!xmk1fI1oUN?JDJ9C#mJ(7P1Q@cd8lT&gqfnv=yc0 z)-!D1w#}>A+9VWP$l@{(f)X(&^29CsuUCpop*e@Xr*i{C#WP@(LdaK*K>HYVn3ORK zG0R*~t!G*-<11&J>-Vh);kkQ+b@(ar&Ph;6a2aAqrtT3s)PP-^<6hA*td&@DmJ_X+ z_EG+ZcdylaN`@HC$h!MTc|aFW@+B?}yZc(;RW7~)>Nuew$%V6ayQGN4b~sr~?ySX1 z0ezm@l~+Eqo~%1ZNqYT(5*_s76L&jaKl{eDEN|__?*jx%l8_ zDZ~MPuqPQ}8gAMdl8n5BIesnwMH;!K!jyf;MK-Do)t=bLaEyOhT4nji5`{C zbqM@c!(d4+!pY$VNLwR{U&FPno}8LVK&z#)SY=5{i?W=tZ<1^`V|&R5;BJ<*_)0l6 zA4RfH=JUpf9s9xcj@qnNlW}ek2bYS~Vi{Pj&NQnFX~@%uIDnx_Tc?P?muCfiImvJD zo(w-2hx;(2?By@vC?=L(C+(^ znLkBQX%dTFzdi=$9t_8>gjd{MC=2+)>MdEz{4trl61fsjzyJ&pX$CPKm)&=T7#%OC zEcYq8Ql(Id8{|BWO3V=eZ(kw$>tH@(EtCB88t4jRAWldcn~vV)sNmg28MRsx8Z7W> zQ^ht?o(6o(1iUI`8wdiFL`sTNdEGTr z<|~n<(tr<7oV54Z??d|t9b+w1!bg#lO7=sFN11nm0Uv_vR0zO^!56EIb#i(VVSPqP zgU3nsQpE8BzIrq7H@j0^4-U~n#NQWXN*HHgfUf7TmnpIasE^tN zSQaO?TPijdh_FP46@B0wTw}&8yzA7A z$e?}3^!>vcj-@8r{Gp-{58u%L=wHVf+JjqA=U=bhi5pk&j^@`*|BYdb#GjYleljpm ztu#brxCv{!U2Gt@GU+2U$fR(Z@+#rYt;GIW`eCxiUDhTndCV&N!w*=Wg5=NgQ)aaV zHbtK&IFwLo?qN+F7Khq|1gnNe6m+5q#rvxaFKWWk{2543pCsaO(}2f82i^>33zm1WcpgAtFlH6vU?PoGK{ zA9o4W5*|p)RR#9RBQ)K~on?6Qi>K+-%eAEYM6?&NC{or?l0sk>0^^9J`uzq(qHgM`d^&O@X zy8tc?WBkikWYs}Lq&A@g&2Y1ZWyhrVGwO+b{2r=S#<4qK2N+}N$;iKQ1!mQx>rC%< z%=ArM<`2=g(>{j2i}hwePt`2kl}m(cN}5IU7It2jp<5F7S&2ZA$t zL5rCos;_%?Z1|`Pj<^Le{EH*!>A(R``Ldzlw=;A7XSGtfuxtzEt-m zj5Xy;-aiJ8yh!#ZxQ=)H<8fKw+_l?Zf zgd+lcI;+$CVeg;$uo*Y=mzP%5@s*g&(i{z;P=ARcy)kW{ScjI$vEl6Y*W1M#0N~{| zzE(WBnc}J9X5;Z&jqUe04?Y^q(#=Zfg#4aM?K<^%`hFOCL}u^~Z1Ur>9LQJe4cER{ zv%g!EKcoIJ8x1J4=c-^)wE^CmoPD9~ci0};g82m#^yXj+3lU;$r!E7Nf z6cIS-`QtT<)!MZR(Hy&sz}=l6{EzHihZ@_8)a4ZpB_>xsq#Nhk_S--iV8E4?-M>ev zX8LaiJ_3HR`(Y*I{0&sx4~$gMyrx#L$`o?@4rZ1NMP{K&K875>_$U8ww=<%%?WPJp z3mk?Jnqv;idq~hsbbBbHx>I5tT>WAVFj~EU(uk}h%mFSMi|3_?ei8>EwX+FvS&^y6 zq+8j`8_ja`F<@ibpu%r!)|6oFdjiZIub@oY*Gkx1WCTu5Na90C(Jh=9%FJG1N9#(U zSC5$NUylb;_XLw{kGCoOyqR5;&%_nz4~;;Gc;equp4M%nS?Oo8FW;c!#t}tLk5kj9 z)`h^x@uT9t^<2pQ?E%y3Tiu-3r!XZs2|I2Zzr!(`+sZ$pfUOhhjBofE8=*G@# zso?k6R8d4Yq|QK!00lApT{2-wd(m5?&_nEF^2~C-x9jefJYR0{zmiE z<52fc>$ryar0^^fJ9lnd&x;SJJE-yGGO-ZKp~RmBRX7XVuXS--(4UedoT@|TWSX4G zD|H;yvI%psXLjQu)bK}`Zo$#NoK@>1({a2)+UqO2%xKu zz?>#512(y4IQ?O(*KhB+h-Q)$aHY4Fmu$UD3Ft@`DL}yONIt@VXaBLebtR_PW2C^smtgEQ#IZGzm z>kx))c_)i!JO*k)sFoyv5+E`%1Jym%UkLN?_J_L!Zcn+xi6@qY&J6&y+8V5@1}5(Z zggSvcMaOtW_BbiOAW^&wORh61k|RFa_1q!qD?aUY{jbtqzhe-&U&{x=(eJ#9*>EK0dYj1{h|X{u1;uyzrr;Eh}GtO4erDF z-MDi*ggyfwOf3>p&01|OM~3@u81_<+e`3~VtUk#Mg*ikQ1&72<`0*|gtm?t6?|=Q3aV=(5r) z4h}C4a+?~i%z;FwShsjG`HWA8kg)y&7$y%K55@gX!dGTXjev!gGjx?zw^R4t=`7t@ z*tKcLnONm87JV?s##rY|8DK$lG4!ScyqwEj+q3v!N@y8f+%O?)M|F+Itk{C5M#pz& z+Zvpi!jr?>d_>Osb+M-`fe5E{9yc1p@+Pe*(@;syM{~jEzTqL5o91k)e0KrD2kQ{h zxY|6iWL7LV;uD%Tdp^+*-daz2GV9f#Y42t63d<)VRY78h3p|6ctfAUJR@f@69mrqs zI!+g=KYBn%cqooBwFEc6zLYyu3_4O_iM8ddTy~uMO`-i&G4wT4wL|!b3KFtl877@V zl>&QiyC)su3Wa`DI6`yfPv%r?v+4TT=ikLYV|D4P@}I949!#+-x3WvTJ4J$W8nx#p z6zr=EyPH|~a=(9r@w$|54G5V`^%gc3+LEyu#EJD)p2^v?Ho(cNy~uF@@^p|(wdA5c z&VTns+W-ySPVjk&6a8)qG6!fnaJ*np55}r3Cg(-0y}X`%r_jASjUor-y!>}xHo*Bt z9$~JPRzMCw?K2kFAJtY<8=O49gRasLuxk5gdhHu<_l*n+@%k8}QV-I_Q{U}?NK;0g z_%7~#1uX;0%&^QCZ#XutP$tFfUs1(-^+{Tvz{S?0x%S&US>Ux94oKudP8+D`Y5<|S z6`D_avTQ=$yk|_pYF@MY^+LrM6c4xMMy=>?jGH;$ng%kjO0GrMa^<))-5Xh1jfTwp zsLmRM!OWlYG89J83L-MYzc1)YR>hY-6A$y#FTeYUb{^e@)0iR%fc|8!#c0~Go0frE zHe_V$Nt}2yOL@50D;tqRG{*+7ke)4do=(#^R?@uM_UtiINGhfVgc4 zwu=p_%E3c;Xk_odppo*eC-+|2W`+mlV~YTz)_CVb0{J_RhfkSp40CzHNtiT{l|kJa z>kZV81E9R|>At~t3zEH}a;W)k>AKEdu+-s9BA-6wzWhrdx$N4{7(rzELVXLdt!lwF zk7i$W&S#BHHU=+6GM`wQOg%i@FcTCm-!E@GrO1*+sO z<2K9r5u-BKg7^MYXX}F|=GmHm9qo9o$s;vj0D}yeUe4R5aClQ3d4Huqos0Y{wxvf!dRHuPoeZ6UVePXbeN8tU{K z-``A8=$uoy5@Ubl0`a+cMLx4iOL}teg-vF7I(F<)a{TOK@5?#?eEGc&f_fffAv_Zo zogzsNh-t?&r+dvEWmrv^b_be~tv@wYTd`{)wTs{G8~4~8d4Hl*9+F4oFDf|bQxcO$ z2FlXOqYzgGM8`_O7#%j!-7t#cJAO4gV=P|hNHw{{^3VHd@XsKXgl2$U&H=P3=INiveh#|1>&2t!U7G6ec{@wZOJi)RlATP+h)i#ar+*)0#Oy_uL_ zJ=CGy_hC|9n$QvO?yJa#7wS=44ggI-sxJr@kPEx&mq6g%e=bxMf0w8(5Sp~))6)6t zcMLxQ_EbDdylo}|q$h*>{gTfYz7%9yhB+do z;Z7Sk2LH?xKktTbjuLSYz_IVFT>@6L8OzCO&n=7@SCILA#kn>#`vu?V{lpfUSaK=u4TCx0KXsCVBA}Peq$qP!G8f_2+)DIwTU{ z?M0>qJQb}VZi4D%y;9up!{OK8**vovc=#r~T@bDWtoj9G7+l7Fz-Q!o-q=TAXxJP- zZ@;nk+Dg2rD&Pog-O+w%p9bNgCc6qFz%~EDGmy75ih@h++=#);rwkMG zy&&=txa?(1+?H#1)^#AHJV*>~e?6E6fG6}P~^|h6JNlEC-Ps6eGlHq00UuDY1>-yIP$NCXQvJbVD zf;LjXlF5lEiXrqklsj(OZwxK}*Ju3o;jx{BopL}H`)I?@@=PV3p5G+kEuVHS)!hh` zt^b&fcONbJXIlI_@p<~@MmU1Rb32i9a+2&iujn25jWJgLY!3h9Paa(OA?NoyfBlY% z*MzmM0v)>UPC?$kJl_8L+yDG;GK7X8(wpMNcjG%YK9DBF`&bJGG$wK!0~>iU&-AWC z1Ca=Y{+ANwalA9xKfhn{swa5*g+m+eI0CNLMtIIk^Xs8nu1A6ehY|G)!f$-E`^{Q> z3qF9M%jF>uccQ&OS_e}VUzekssUvaB)-b&VH|I4PW4c(Ss}?34uXL#`3V)W3_>dD| z(SL4_0g-9M3z_N7-#=Fo)E8^O`0ZwU2phS9C%o!mNMZpA=e3}6tImdf$abQ= zd1kDo4!IQy2@&SZ|2z%Ho|b-peAoi|pok1XsDMx$MD{fFum=6n2B`}7j97-_Ax|+S zV8AYHvK-Ca(D+lj`(ntB$O!H=$-NYTKfMVlR)LPHClc=LWUywtc7cWxh6n)4&a2qTfROyDGp1%sn5@ z#xx3Dn3+14U)~-nbYGZ4N)cB9 zVMP0QbhV9K9cd)9q(}S<^i7VY9V{Y&iDMp%N);Ty^F_U%QPIpk%*)O%dJ^X%ogpA_VU}&WHrP=UE z%fy)K4!$O98I?;7v)OP5BY=+5@wh?yxU*xT+K|?G`F%X$Ow{*S&c>(^Eh!=&0|(T- z7d)P#yB%S?o(M%>BJ`GyJkrHEq3JHuJ3dmtntD>vR5VW^7_b%+qr5tw1n>All!s`= zBTu?o{l^SOXi^(PB4Si?Km=C}z@5J3=Q<$eetmPT1*PH)#@^qNTJdV#p2qrw-|MlW z$o*d13B?wN9O*=<3n*#B!G|NHEz>@)2i4F(;Hlznp#y{f{jCn1R`cr1dP>M z9bz^ofiPzQa2(=A1WLeOvY$G%o3itPO|%Ud`Z#&2UG?4D6|I7~rP80HOKVfRteG?G zUzG4{aqVtFsZYPP>`GdX1l@p)>?H_PevTZT7#tk|-O#m%QC^(wMec-2*+RQ+F|OGf zS>kTh5+HRG~kj{fYuzcU=h$k)68z7B)4-uWbetfxWNlErX?r50oaQ^)(( zn_el8v7##V=R`w|9J2P8Vmc(sz)JHHWqGO2-nA3RuD9hydLK7;z)mr7e-%w5(-pV9 z;}f49z2NJr*)SV!?#eRheQNLQ+AmvAhROl2#VcbeFxQi1RM93_P3*w@iB0t%oN>{sEEyY>vnBiA6#~8%1dats5fuh?wPzzE^mZ_ZGB!vU2{S ztR_%17(t?%eH4I$EimKZu5+HRmPVGEjTy zO=p5BieQQ&c0^5qhuRAK%5xAec9rBszYER9?Z27SE?fnPv%eEyXes`#%5%P%7>?O6 zh2j9&M6D%O(~lv>neL?A_-S304pU&yYh^dVgx<=M=QwFG#{fj}uN7Y!@0+-0Ev&PP zU!vJjp{1z>GWR}oD}#~sOMm)^Mf&3lRq-*W#n#O%hItx2Q-HQG2rj?eo2-GM69&Va z&j_kEg2eVjXip6rPZF~FJa6pr8;e(NUkFHVy7zXPH-AtO%igB^b_j;)Hd)ZFgfsh` zd381>Hbz^3F!a^3Af2d>_9b}{JFS;E5v4KdtUx{D22`egw>U48tA+OFB8w?rwlo5p z-^4@;OfEP<$n%_N3CKX(mZBR~Bc^-?+L8OW?EJ(!IqC2}m1SnI4JCb9q7TseR| zYtb~8ch=n%1~*ab=o_`TRp$R6&j#FPJtzB(Ny#x;SG6 zpd4dPD#p$J@pn5wQ^wvTIpzr(M{THjj7WQEk8Vc;{h8C%4)3bjQ)#ozw3-tHl(6ghvu z6Sf#_u(iZI0iM$34TmD*H%g)J9H8dfWkAWq%7A=b@3GxnfFI;8#Rp)z^ z(OrDOEgg^D&0u!>BIvIBvGySFnln#qtUEl(_SSE!*Vf%L$d`T=?4=%YQhHd)x&9)P z&L%yR=Gnmz-GTz#T1bwKu;zW1P!sMQ-E$hV^x)HjqWBL=QqF?4%5;!OWRJ<1K2d5_Z+r}%2%kC*Q?dj+ z;(<_`i8=7pSBe^$vz6d|Q>Q%bJr+K)>L^l$-0))Wk@K!#s%9KC-F;bi$yj7A*0HaW z98h65T@J+7%@oCtflbO1rJ!|J($;qRkV#E)+A6I@8CSh$tzecp1X*o@y$GdO*FY4e)vwbXnKb-LhxH$6YKC9nMb zx0^XVfy!$VjJc5yaVy)XU~LS46OVr`_qLc>) zeoEn`9XndhHuhM_RZw+@*Tn{F59)v*9qNsDd~l|eGX%7YM2fHez9}bCrC6_kV^O0A zv0Yrt0cP*LIP&dLfO(1x0sqeyX|F`MZaF#P9@`!Wd8F(3@#R|ON8Y2g7cS`x;PLsE z+V++_!58np%j9snv5_m5T1nsJ;DfNPfRJC zjT2GqfEVw}+l2e7EheY~DGr{dF9=;O=u!G{!aS-X;n|NFVLUr0%C(ad9hip806rh0 zbn%}~x7`)YzKf6Oq@+e_p02zfIADjYB~C4|I@A?h-_P_9yvgI(pNLh~TW zrx1Br!Bq$R&I$BtnM^Ag6o_nnQ^|nB{UHz|Jf+eCSYto(I zSqqM(`<6doVy(PF&BL2L4~;~Td1b`?9l{kBQ@|cpdy($lm?=8SLOt4EZv(_3<7}tS ziG)*%Ea_afEM39I|rtiNisim6XKQ>*rS44>^nF-X{>#< z#*ij{zKYZGp7swgMKTy&lEf^Yj5+{xQnTj|$5pT}l6B`7iT7WOsHt1Z%*br-ey zYv>`^T#oFwAOCP8TXYPoyxBj@nlC)XJ5IO;Cp>&*W%H^D^w{zdCB zhj*Jxk*px+gN(2stJ)85W3s~)1K0(W|z2Z z2MVK^n6Qya=aIPr+Yy=<-q~%Vn-~K+j0`vH^ptQzxd=Wt-Hzhp#m2=Q=5geTzvXOA z0iw94=cg1oH~T=@^>Ff~!?F~XHX7+xzPCAb>wo#FxTUO0FbejZU0fYmiRiyXNfn7A z?7YjnpfQtPz|=m}gjY8gZP+t}4O_L>4Ant@dW2ocsc6HlW(sy0yifsgh4-pKKR197 z1pgzYi1L^OMRU$60U${^&rj-}n*gRw6XQLNCZ#*i_?Ig*!(gDW?*&RE9SQypW$jGk z=ll=cT#rvzn3M@G-#M}AI?EJHgsMAswhciWE5v)S2EbsuCd%}bgRA`dUl)UB8wcoH zPLHmRh~s&fLAjvnd~I72F@ohPaMvICI5_4cHN?u$C4-Ft|Hzhj%JhX||L}}c#Of)y z6y+M~L?Am(Ps252V$WZ)wlcM;=_GzyMFMQzie@|ANc(Ka*l80fXLEQm?aoH>{<80h zDkPlS;|qsv;x-RcnC{0%HM*>jvaW8w*Dhk`7`dc7lEdzZEF7ZU2lVYKHR~6x>RPO) zF4PU_&x=iWS~8a{z$+3lx791cEw{^l z8({Nw67yAeVEB1=1Z|wbpAH)E_r*S9x)PFlM72d_ei2-*+GJ0d&jeg@JX&3{I-Ab> zIwX5qH5M^c-KuMlX}F~~u2>|Bqz{WfN`RTu*ygCv8JBComQ}ep zc)CaMe6^V$adOQ36J}kGEtk{59r${F$-*E#Pc3Yo^ncW2dtOVveLMXlJ8on)vc&b| zFh-k;_n%WQlpExcdGi=siH~F!pVjZ(?RVjtmkCUYo$ZTG?|6UPI5%)~{hbj7noaln zHOQBsHMytFFBLRrH+rEN>fHb1YOph7(jerZ4Q^KZGvC4z{n;Nq*Xvgjw9jm2*lAVW z$7AV;X+g5hpwKfN8{xy$WazC2dF5GS9QWQJsR1v}A215~BydA9t_%#rq5wKQT#2PBl_RK^YZyFdS=L*7PO;*{D|fcAVCcD6|rGXeE07tVC`9EYvg(1}qVn zx%TRgba-DxVBT)?aWo}of3CRUrW9Q8fR&D+P8e@jN#ob$=Lo%sluRtSG~y=M6m`jV z=ch&>z|G#nDhb~U@5~NP8rrM^@65q$l|lS%-SfD#!?I*T=egIx)5kLEr;3-}h7N*c zVu$i4Wn!&*f$0+TF6|9i(P?F8pDvKPoRyp5zIX}$#xSXCleM3?vX%5?TjzY^iu_&@ z=K1gO$KL~|+wd5t$x7bP?Ml5I=6M5v5j2dh@iO;JXd3O^PFdk4ScBHZ>!s8b_kWu0ykcuu7}P`*f<0S$ic(9q?xX3V3bNwkQ*2^qvC^b6@`LdOOsWcnUj^*+B zf|0}sn#TBc-Oj}z>iDWlA?2`Wfk|3Rp^+hV@F+>jP{l7|6z2=+zSYMRN#Kv5MJYiJ zq;;8EMy6984Y~X)fLM%-!xr0(LmaT9gdT9$Px2Xka$K(m)Phda1KzeyC?0)0pCxUR z#z!g_!nqq;K~Ag<-B%oenI}{N$ejO(hBkWnJgbiWYx#DL+*t)MD<~xzF!#FKT(0o# z)!Z$!D=j5(5<$|?Oir*%kD97)wnJ`&m?w>bBt8Aek8AeXafyGwxek40Eo zupJm6QC1I}^HU0wUJLs^kDC&lUDSJbHu;jfn9Pd1$;O&OhSK9{VTrZv=H_a5U*Yn( zIKNdIn*K!16OkWt=mqq08Ei|GLK2qT3<|Y#)6-G4e_-$Tji%p{Og#TIgilCM!t7-J z;HfW~!u-eeiaU|EasDf_=`zF(%7zJleVJ#taOCl!AIOfgI|GWCmG?Fs=D9*PL)h7G z&p|-=(;ixw5EU|Q*b|2am<@}dYc8^`rhT%a38KjHOy~lHA=J)}<>vsfLRCyMY7I%e z)=ZaBu^1*hgPd@=UI&#+R5l%2`&}*}+~|?e1OWNCC}-R<1{^yJDvA@^bp>X_j_I}C zIn;7yDKsMszi3qogf5}hmU^+^HlZp(-QY6k(60OxVB;DKTWe~HSLeS2w0I6vw0?eZ zXWadDLyqwt(~$Q%Z7MV#=vel}+|CHV`tw3(ZY8|X;Ri-HJ?+ zjkuI&`pSJh$cEpx+Km$r!!})IA8L+mE+4h$pM& zvQK=#c`#kEFD2a)l%LB!V!P6hD-+U7hoi4y_m6mQ`kDrNU@85bH22>UXtz_*ENpWgF|^C zn61K$25z0pjj)faqJ8{1%(J|2UdG5r^KQl$IA(?V(@ILT+Kg91CYSstth ztp`L`mG#=xvk2sECMWJ|;leH*p(yPHcv|;dBEOMh+-m_dMz`PJyPfF<2EbE8Az6;j zZr};C4}fn@(3sE4Qu)`dvTu@6Spy~T8Av7!4K1<#8q8Z6_~gA;WAZQ9U0H(0kUw6o zcGJihAdy8$J@dm2%=(x-Y91Uv3&T;J9A?9i2Gbb|yVOVf^G)9vzJ^d`8;B-l8`lH- zyDG2Zz+293UyV~;HXrl39l4^Eya!*74zLg!52J$VXOmYi7i26H=+;wHU19S~Teb0x zHtwH=@mo$*a{med9iyk{^3c zERvqSB+vhyKE%RtL3lt>?gA!91UO*Fwh1obr(5c=a5RUVAd#(8(N6~(FSXWlwSq#i z(zKi3I~dvYDCG{7%yXK*0xeangKn_1k7lBB!%>!^(Z$LEZ|7o0$Sce3GRT7TyEBjv zoT?K&1$e$WyL*W9M`*`w?>$_Dz2hq!2D2rvR@atTCFFmVq63#^$bi30jk} z*gh#mdLmw6`O;Bhg@mM^$qY-j@YgKE0S9YvDP1L|3)2GV^16Bel@Pw|_w(ceP z%r;lVlf^hL8bN_a>B)6o)$vELGER&0c&;tWv>FJc>{W#Z_AEVcQ(;c$tyw_oGGm~a ztoC;=WlR`ei_u@GdIW$&mxLwW18{3lpk!yyYb`>9L)=PIuu9-@A2^N(%id-Y5T(!A?TO!>=!4kxy>TE24 z>THw^I0Otg>weOmtGrdXFg|0ppoX<07aXDD9?-v!7=D*_ew73DUTWB)IL=-3VM+A`Ow~TXou$g} zhX|;;Wm-TbQH=vo;^Vv;<0Cq|XIUjFqcS-$qpRlyRP{TkBhvTj4=BtRh7vc7xEs_S zDQr;@owQLXu(Rj|GQ%&%?Ic!$#JRepKIJmVl46e6!^^((@z`Z~Q#Q3|v(86ag|=WP zbtL6Soqf7-Ep)ABo!?VvdC@3%Vo0kc7wiTFk!E_*`$C_w9orMB{$rr(s(0dKOOZLwSu?dPi2U!}o5d?{hkEF5p_u{wER38uR+{)8w+O!2b z$xcqvnx0FieC{x6$<2`MfK&tAQ1`0#SNhVPi|7QL^_yen&W zzq&kMS=w*s-qftriZhG+h~s{=(7rajwo%^%$*yanH90 z27mZT_>~XxB@8}CqhJ`Z@b$oY1gxjaHu-v!%Sjybl{!XXahJ0d4pl+0iIXaRer|OG zNV(oqfYUzNL6W9?8)Ig7Tz!$m+Ctsj5f_i=m1-vYshHac><8!`#u?B3hq$gLu(%3eDUSy5C zJ2a~l?M5BN&LB02K-AO7T@c$@?l|1!1rAdd$O$I=9Gchm`AS&CbRP(RviU#UOxDd1nR*-OZ-E(8 z$h$WM^h-c@3ra6VDL>)-rZ-SvIf#HXis_ASJJQDLPRm9#d8H&pTJJM6!sE&J-W;Xc zNH@~jK_pFx18L$=`DtgO?n>alHgGbcO+!ueKXjb`@h8cI-2_LU@MDH@>m>?d;XV?V za|~k0K8mVx?)|@h&_7=zsZTH#p~`aO*!XYMO^IB(V?cv!Jk&nE^}qc{p{;mkWff_J z%Eq5?;R-KugwI;eQ%qoy551e`1hEKZxFK(tM zj_?Ep`TiYAotj42uAH_4$H=gRYW&Q9yWHCea>4DQ7dN6)yDGE^%YB-egl+ofUqN?w&vU2>D{r((RN?1?>Mmpu zXmyf3^3J_0MR%>jK0=OZk8-qV8`wgp)bRf0=d^WCiAT;Q-9Ls-EG-_u(mw^YX-*9A z@ou4`7jAV)LE9#Dsh(?uZQ=~ehMf%NCjT#nPA`uS!_XGWK_7-N8R3kPps|$(dR7fG zb7;ea;(Bh={er1E(l)!mPaFi&!AUf^O998-v*0RM9mTV=HWb=C4mVHjmB|MyjQdM= z5ll{i=?tD(r%{sHl^nCMHfZ*00TURn;6Yx>BQSD7$qFgga^Eh%5VuBZ3xk$dp?nx& z``C)d_lGHn%xlTrTZdhvu32K5+WDKB_BZ^0x;zNzk4Ay``{kx+EViR zeg9y1P{8am_PG*?GFE}F>gQ)#HGUK~GqL>s&i9XA-#GiF^ScjYG-y~!24RkL8ceZI z7LI2=$D0HK%tDum9IbsE3Yc03unxuH5XH62c{=6O_hK*C#TQ?m@9(gi z>vGU*0*Ci{yST)jcQ+r`F2Q`~ohKXoBDJtw?le%iR`E+!CumoK$5V_Y=us@=Kj=k! zjK{EGIuE$RKu<+M;pwj}r7S~zdOX7z+oRY1MFpE#s?IT>suslJ`d7RQBm%^BFk{{U z{Uk56-h#^$FG^MNK8-@wi3gsagPKTgA(LfhgZ)N@2qtz@btvK7+6JszJmt3GS zz+r0o=cN>*mRCZPM#0j$3z1-vw^66XMJQ$uINorF-qCwGXVlWa zpDWPq+YGVTWr{1Q;NSuKY5_gB1w%T&>Jx=Eq9D8xxa|7>i8l5Tf}^>FD2XhXis!Ir zf^i~GkpZFjh8BG-`SPag@o`U?-6v^%#$%lSN6wnM2boh>VvE(o)kTmo3PbCgKmFqq@!$hM_S4mvxJ}_E9`NW5I4zSOkEbaEEiSuB{W7GCM1n>xymoIy*&@og@RVQ&%MC1^1JdRpS{$+d`L9%2xSS(#0DpRJlw8>+SK`8{O3xRf%+1DQ7?UsD3n zkalYR>)+(ATh>GkWM|=b@=a;21Qz z+8<{l>6d?0h(R@1@xK;7T8Vr+DCo!f@)hj=hD$=@ix*@1S;oL!!EMfT7G>VywmN?d6s7(R z&yfK14|9!Gv=d-V_M_HDq&Ixs2`c(BB(6E|@HjfT0(GbcM)!vOmCtyQ-@8xo4~pK_ zI-KtT6ser&DKH2i*4*G&1aM$`@&p4^d>O@Rz*gXG*2GpGfND=${Cvn@D2vRXR6qih zC&f`V@!QaCzOZLA>$~Yrk^{_YYN~*yrGqSjg-*ugA7qNB}0_ln2wxLrLFs`Z*dmvnwQ#A zfD>7pM=Ec>*12QTH_2#z2LAI>i38uP4gPsv=8uIT$1e!lE(r}=6(64Rp?`8C<|{z# zQ%+006s31dY{FIDeNX#ieQ`^iV{Sh`Y$>D8ImH{`t!zP(z@VXwjj{Mt5XHV$k!*wn zZsOB~p}Hr~?y$qN?>lz4BJri6IuIEw3_h!cA^YV0)nihx1WnBsD@&`T|UP_SRuF z&J#+Hv*a^ZUtgB*gfG;UV@+0SuQETz&F#84hOLe-ht;|is$z!>RZG6jo z4B~G|=}p7PJs9PZ)B=gc;J(hI?Q}QxD{L_(T1>5*1#(}`D8+`lcP33bPkrjHs2v9$ zLED$c{BcMgKQ$?TQa}%geWEOSVJOkenOUkE6?%Eh%@x-~qTCio2Eo;=*_SOpE1X}0{2~wTC1(>2Xx$n=LGGL*h^Ot6GTukr0`$nfQXXVh0+SeK0V`Jb9aXTyE zdMErcX{^F z7`MgBYnLpZDb@QaTL%__R8#ibVKJxdk)|ZysPv_X&hNs_>&x6NXBB*NvS=F1M{_1I zkes|S`3$f1NAN&N&6>EKYR%4~yy!Q2CNzEo=WSCYlQJLw0|z$4IKcIt!zSlHtSvc| z(HXa1uZr!JR|#EqPMbCiqSyP>dd{daGr+U5c>Skj|0VBtApSGidvud0C&*$VH zDp-cfkP%fl)CSe!FJi%ZU{0UJ^XWPta5oix0OagnBBs?H0|VLUSg&r*31{BX_o9~- z+RKO@Nfn{MR)L`kk3NpDHAoY>tRvrc5ZawTUDmO6jbKXt4v&1;QJ_}1sSI-0+PR4i zTAxFdiuo}49~Y&2Dih5SbL(07YWVH9@8VqLqtPA?n~_P__&~}W&G3;XkjEHgA32JA z!p_mpz#vv_DgF!i`Bs=&24Hp87F$ZjpK#M`jngck?+ZUMd?9+AgH#&zFW`-L3Xo|2 z%qjg3(g=X^*Kmku4!4yL9D&&kKhnpx0WPl$0(Y}0hP%CIw1|STEl}P_GxrbQ25iY2qQs`QB@EprCOo#1q&UX;nU4l zCq|kE=!fn;zd9u~UG31)7R#pKyK0VFS6C<6%@nnw@} zG~sY`=fPlsdML`7jlY4m$w;UK;Xj==z^*#w-4boISgP`j3Q2}EhiTq8OwO?0;AkdoEvUtHr6>+=JAV#-szy@+S#yQw& zwg$SyEhR=+WHNt|FMz*PHV&hG^~4dW;Pnb`AA#}5GYS@&uDwdaN@VIyl<)AOQKoA! zfQ2xnYYN{8#!YNQtfTp$A;CU=9iMuJoYUWba(_AX5oBoIG;;RlFdUat-(sN?vV4sB zC#r3_O-_Q@TU0(6`kH5I4TO+e`Pf|H(J8j_6|59#ath6cyQnTsrcoR^;&!-kWp#v+ z$bNx#Y|0i&yBc6d^P7I;B0WiYh`@{ZNr|jjbZ=IqLG{@j2_lfhS)FP*2PY_ER`ly3re z4Z&n0Gln%o=3XG248}1z+@#0B8!8PCe?Wz0rla8DMP4Pp#hB78V1O4fCQz0Jc$$8k z6KwWgO`d&mOXR9w?2gU??%`R;raT?0>y)DN6{Zy;xBOk?FHGi@I~KSYI(GJ{d<*6b zbmCE|EP-XwB@1)o(Oj97zw*h=IB=esTc_1UM`CzhQ%*gQANOFDVB8fPd2GRi; zBri}fIJ2ce;|S+1rx9s8Fv4tqg^wG#)vWk@0OP|b){bbbZh(q~)&kaP(KALp2#y;S zqI0b`b)6jfpy&{}R|R(-H85s=-fZ<0E6}OY@WV|$T6<#db!TsJe}GaENgPV@lYeX! zwF;b(aO8^+yPxj644Ki1yk0U9wMMT4r#>zZ@VLKY{xCD%*5u>W1Xe%vd*U1`Znv(E zdauT!qbnsR&X97n^iB0W-7kn!Yu^Bwq_;qcd%Gv;m_uiuHm_=MI=8QLQDwm@rw(SR z2?y@fRdP&S=-@inI%Q@(LZJ2Ccas<>;uw+(L#kvJZ}+R9j}!t}bbLYa9=o7fYp-4n zo?-5J>_mp+w2{cYc=G$v;IcmmMmn6#KT6pAG=v8JgvDvC?{X;a(#w`VWCXgpdB$6s zSIpXW;tR(gyX);Ch4NVvmV*;tIL;AXr19gGe@WAs9ui)pXM4Z{0GZ)E@L%`lle$Lm zQT{q8hkf=6-VLLvrGp z!7yRGX#%Jhx8}N?EhFN=Sj`BYNr5|3vQHZn8Y_kc;IzxkvIZ*R0)j~q858Ys+pzT$ zC$8nx$jkADf!g(O7IcRruj((Aw5SMn8OZt^8c7I7p0>Z#>O`l#grKyU;Levi5f!o0 z#Ng1WzdG-})*`{h4{Vs#-_^kim}-hyS%sj|qvclP!xEI6SL?P=@(Lq{SCYi?_nm{4 z>@nF>n!zHIRww9^5VK6I+n}qzaw|=ur*c`+(^A5Lk$A1pIs=~L==^|k-8r66m?yNc00#&w!j5CjzOTl zWVE>Jua&f96Y(s7Q}YY3&zp4nOICw&Fkn~7p6!};z?_p0zkt8CniR5t9lWM-5ME2p z!v#Yk}Zc_>R0olP7n*uKlS9l{JDGZ= zv%%ny;P21ZB$X33mNih2FJF{qog@NBe9w3aMsP@FmPf;0nEqxk3ko^ z;N>q?_pd~P{Z>l^2E0>6)W!y&KAj1vq!+9xv$`KpBnrt-19@sDbB!q5+lStu?|7)o zXC_Cgjvm`3+5|?!2>p(QwehZPoz(E8{F>@J=-)~6sy;6I(0qW>v6W|XGowzanhh!e zN|Z@Q9}DZKl|N-JC_4X2>#?Gu#oou0Ppm_$cjuQWaqdl6iJ5ADvryMvS1hrlU*{%1 zHhZHk8s4T_XUI2jb~SEWl(x3J7glpB@6PwL5yxZ8Kf{frF#%uALd)*HqZcvTY$D5# zUE&I@`W2#BSh!0WdOiQG@wh48?u8@W3w4w7*)9!(9kWNHB<#X4ZleoeI2KN7yeG|r zFCbjVVf6hw=&y~gN+{s>>#YyA4Z9{_dWP#?LTCh!86r=1u00pwIi8WVKo}b_-6n6e ziwUioJ}P4?Yh$1O9;*~X2C0>I%pE4$_ui2;-gbtk+-m3)aV)E`wRI>!l|=dLkEqbr zu-hTJh4O@NGPv(Cap~q#he;2;>&0+vvDkOj5pEH=Z8mO)g1}p0_%YgCU2yyVIwp)L zTLn?fU4~BN(iNf6}^X{|g(#z?YF;gW^&8=<(!}!tLb{ z7ZML%O9HRygxDk`^Z==u#J*O4d5`Xttlag6c*|EUqT$FjHj%a#*@1;GV|QYVT$AG7 znuyu5grb(S#^#=q0nj>Lb-XtP3Y|4zfUW6AVgO>MWjFa)w4&QHdMpsKZy|SK*PNpDK_=XyO8aoZ$ItS4JHx z9cdzmEhk>-!KAs_Y>ipggK}rncagsylB=7?=?^q6Tzv3~n~PS?qe0`etyVZNh6^nB zL*&b?UU2#krL*b-$13}wTxiWDmxMeyjN*5&lYFTi63y7Em2#f-4xCElkxU_eb^*2N zmIAiIzbI_?95~*xnxdU=-3x@iZI1Nsy8L`f8^M>&$x><_@L%qncbjWd9T*^5KAe$dV9*4oHH>K^Gw(PX#6+)0mg2_*m>2@?LC*5 z;tW}ueBMFjA!BV0k>QeZIq#N+fyVco4Dq6CO=Jp+1!Z14==)Ba42X z1pskmul#I}VcPV$qUo5f`z8yoYIDbAgx%W>OO|m;2!ub`a*iQiX$)amS*?_B`G;DN z*z8Yd@Uo(8zOtMK!`hpfSo+U}BheOcCYDd?dWs4qe!$MXztp z4Bw0m!S8??#MEDn28i07qr0z@zc{L&ppGv^w(rka@jXCVmQTz2*T@z!oLo0;f-#@B zCLL*64i@ZNYUo{~4qyD@m~mW4NXXuw?)w0oSumIjBxCk(RbDi@&XE6^vUL}GtMskr zRKxu;%gO>J({b<4FgVD}YgDHLGv%{2hA*m@?#laH!6?o(txxCTo+jiAmZpno_lk{U z&i|Trg)gNRCD|SrH4(_q&p-d}#+UeSY7T?abL?&Q%85RzL*{5ANLSell1AF3=_u3k zq9W0T-8Wt(T%J8qW5xJd`;Ag+`L)FN&it1Knbjl716Ca9rk4E_?1if$bkEJc`G|^o z)T@PQiH+Vv{1HEWvc)x529@)2zrJeF+1XbAY~bWetI{Hv4|!&9jUN-|X&#cXXSba> z?aG$QtUC6-)zQ>P=QBIuwUA*e-Fi|+R_OzNS3PaMjc@QTXBMv`k?nW&RbwB%6q+(BG&gfC`r3Pw7$l<9?J5!3c~=$`c$ssv)>W<&F}Z zpfwTqX3I@ozXz`NRMP2p7YSXKQ{d8gC4Da;V514spQ7j4eGh7nUz20t|53a3CGgs2 zu#nFxeV+$^=iK(e^SIUHmkrl>2g0LG#86AOkj+tmZ0Y*V-6VbY?}r>Cz7?Oz78VwG zA#^tRS_&|Vi-2-IIN`0q_ii07SjS+Agpy|orN4jm83MuY$Wk{9NZRskl8PXG@W?du z&PTy@ZAV!7e!@2|bHFOXx0Qd3!xGL@A{EBNmz=O{vdko9a$9&V5CDqUC*)v*!V%+w zdkT;9Rp4YXgH=lqBUmJ9aKZSK>(v`g?hOyZA2tZ_8%W4jX$UvsQlZAR zjW@!9cq5wN(hASLp!$mo_vaHfTrxc5hone5kg*eU>sGUa8|XD0JBS~7o0dfLkdM<} zF>rsD?yp-3%t;-><1<2&aA?Ctl6XELd?eFO(v!P)(*B)Q_a85kX_rPR(&@1s-O0Cs z%0x=u$a>up(jX}zDn9Tn^KTp48VK+1;4KJ!8RLV!Df8#f550AsBB!PU|R;RBUled2Q6E30EguL|kaBo5? z;RRSeauRHk+KL>r`UeIobsV}L;*(qyo|W_`7mca%P&f@uCgH7RIx-_K-Ml zD*M%6@vnOkuh*;Qz8DDY8E<@VSD^!Pt&E3Z`;qC>myKX!{r_{7*WJ|-NNxyWu6cy7 zz4Li9_#hrd(GqEJWs*9_E~K)+o*Mx7YX9Xj;?e(SY1g*34h4gAhabpJ8pi#)H%<1G zpd#F&cqgOiW$-Fwg8Nc}Arh8i@h`=8Ir5GBkfcBH(Wrq(W90k3_jg>GGsS=MT*-`w z;+g%HIIsd>FEI#}EWoZoMHK)HmnRgZCXa8>5I#umd@uN?20+7832OR5aKmU_4j0uo}b&lSQuW6cM7wH(h78lOe!jX0*B5%oKvC0%BsOEbPF8tr2pZkQ0tdH0U>~bjpZ# ztc|JERaYSU=n{VKR=-RNlR&PDMZzhzhp>6y9Mdq~urHR%5qF%py#geIP3^onICp8clN zEjD^Ka7g#b+rtxgn+yfM@HM);!?jxfmWKR4*4QW~fXbMhbl!k-!|-YLWvAq!aB1w? z_n|`Ry26X1F0N5AH4EqK>K4mZ!Tm^4R~LGltRY3L=f!X}{7vGDjVl@E;86+Z_XquG zBi3F5%|wtZQG&|?4hLQ)@^E-|8AAJwYPMcuPuuPxR_nUGBW`tLq2tp6Qw7R|CrSMP zS`Cx|i2kY@VQc+$d)s--jjO>B@qwLfm4m?c$eo$&y4LNsWDWqSUZ-_- z;03S)?YD&7YZEbyg2)XNf7KW#x6=`TGtBdvY>K(zi06g2BS(P<;1GIyOZq@{Xf>Mn zl3jfSBtz|N%}}<}2Ozq!6UM)TOYmYJLCJApJ~N?{h4zd}EUbM2J}XW7Bk&YC@mYHp zh|koY<29(*rFkL!T$)Sxl}(8VKKF_0abN37OaH(FVaY*&MyV?Xap(^^uHiz`Jx zD6q9&*d$6sL@s;6KwBR1-CMvXs~VVPX8ZGFP}PcfV=jjUEh0@Mw-fBmNlUiHFQH=G zVf01Sv_Q#{CZ5&oSwq7_!j{#3za9T{9AYG#RG<24FaFsf(c*jF;3AX}jASVkrL9}q z;G6kB99x`|qTZFEAR=Zul=L&+a?>OL0H_JkiD!N~-c!;O1*Nkvtw}5$YE;we>gpV- z8*^L0i$V?|tqp?1w}k;*RL)R*NVT^HqJ)y;d;;KRR{$o;anvU?J0 z33+m5>LO~lqma8}8*m5_cW94u_3_*%D}uLj<6?4_rK2Vao(h|u452>XIB{F-V-uv~ zF(X-KJnSZ~;;2U6$sk4aOsBYcJO8GaEqke7e3hiZyfv*K7;cEG&6KWNn{(Me<#KB} z3I8>Ov3Jr%FX1tdARkSVBSO*5TQv;)j=q#*&Q=UX~|ntf@>&6EX0( z&$e_)?l07q0FMW5;U7tCEAF`z#esx1_*p1fFg1PN)h%>%!^#2b5Vso+oQb4t>bSzn#KyF{Xd+&bzGEd*ET$)APOQDDkTaQ zA>E*~5)z7_gi5C(-PnYb0Z0l+C@q5YC?X&o(xr3^HFSRKni;)i-_L&E=l%ZKKejV4 z*Id_mu5+zp9mlb>piDloDyOULkn_y0RT#{Tk63^DOd2vO4ZWOi&dZOEU@_pkHvKuO=oU;tXgs&S4ia6yjq(QEi1Ow90B-YTF!paD@MdpqNFt0LAfc7Ig`$ z7$AaHA=TB6SukOHN-jA@aY5v@Z$MEz(G>tu_^XT881y{i>U%&CD?9lp#Z!~{8<&rH427RdWjv-=thN}wPQk7~>7+!~SGI>+ii=B)ETcp)-< z#5rQG@Ya)<>0?o&Cc8lr@bQm~Hxb zcZuTA4r7jPiH5c@WG2<5E6l}Rc&{j;+83R%f+S5Q)hi=0T+lu)q34%l2vMvmFzpy? zFNI-B?W7AbJDX-jWU5E3n4(I62GZTr+DHnMPR!(fHcD|Z=zfbR8e$)hOx1wobqEG= zo{P|hjuO&-wcekju?FlZtC9%?DwjyywqP*2NFu@C1AHzRrI7jQM7lV9D4pTi;VN9z`R%BgWd51?(uG^FDy5~ zoVB`iYr{rk5Q^QQoMx3Xmy1e%=*b^xgkg4kSv1GgSG={WGil}n!KaEhTM@eHcDWHb z_u7CUrq4_4MgFCI-}IBa5nN3s*_=9ZHabfcs0WoKQ=7~0zs}cucy+z3S~c1ZAl+^WsjtEN_U zv5ppV<{{$#$qiGcpoR_tFr<*x>hX>cSLb=174Q`ZQ#)TKe`9|5HX$V~r9_~kmm`jk zoO_1_O~!GmsGttwMduR$yY#5EP$Q){b1@Xs!5Bx|(FPXmuAGZ6Pn&gJhGa+jdsC=i z;+Y{K20>z-uoB(#8bEffW%v9CR%iH%knnOoqVy8J)9+>4fCg^RacCWd0>V-W`Id~$ zCsr~v^nkP>S{exy8CLBzgR-aQ0c*!P0u4i_U&Gecwnm!Fz3h%tlbY7NyqWUW`iP_v zFlUTKUNVK*%dSaD7LjD1YFU}MPsJGo1U9ZTxJd=3y1wRHlOEshHMrri7|X(oE%iXT zP;h$k$!SR5R;5+3PtN@dC3__(_G?V}I^PrJpWrNg|*PHvNw?~0kV}M#?`WcoH-$n567L8|;Z18jmew%nYW&hmoxBIFS)O?DWHO|nLI0%1*X3fpmSo#OlU#iA*v}GVj;cZIQCA;-7I$6z zRG|)Do=QMHDOuyZg;Ii^su8$VvTXq}rxfH}X#3Dd6KnBg0AZ$F@HvL4F^)LJ+l(>6 zfZwXn?=&?9aqh89Y4NrR=v}&8y)*-_*>x_q%2uCxxADQ=eaIT!-& zF+;VYIaXoUywJ+o#3So4!tgXO`?$NJVIl@HLYA}$7C-dqb`?wk9od7H4g*H*OgGDE3s z;>CPumsWib#!ZPw*W+O%4{O4<)ATF0V#=WR{FT5s(d#>0q}R&s7b#8IWNf9GS+a1!h;*$WYc)TIX z_qk(EC}gBcdM;xpn$=Y0`3sOKDN8crmlzQZ4)I|pL`>rwKoQRxXZB97xPa34)RlKH zs6x_V<<|K@k8r1qh<+z+3twQ#n^MTh1Pa$++SH}bxSCQb3|-`m9YmOv_rMmG6?|YR zt6An?gy_>=Ub9=8<-}q&I4o`^pKxon!bYqlOp@?LCq0`%48mi)xm(&Emu~rL;-Iud zh454V@a4zfRIvl=gY`K3r=h)fheV>!d4!=6 zMHgXNk!(7$)7~flFGCV+=?cyK4_muQN@%nNa!u?syIX-q*t%1!Fih zkm-HtM+yS;c!B41t8pTPtyphti-AxHKn7AxVV6^Z04A^$hdCvjW@7oQyW6|B$_w=G zXc-V}Q)7M~xV>xjhB0|7{^8@eT*mMd{`ou>-1h_5%TRca&p36oPwm` z5vkA9zM4 z3_6b>kez;qlaLchSXq5vp1$(^Y;(WuZl1OTE{;z?ovh&_rZna_GQ=GxQXD)?{a>13-!y!V z0@YJmLPY(y7XV#Px-ulkuaKb<9=lhL3Rs3Ifr6)KLqeB`8}S9B%+C6J0RmjnQOEAP ziSc2r!g`3^v+PID1K&3@X}M5x@`d>`U#NQe8F#zE49{rF*G&RVEs4rU=)M|Ox7NeS zG|>>1`n<;&D0hR%97%otu#44=b$y638-0e`ebp|1G|sQ)thq0=}c){ zks+^%mH?*j@KXVjBe*15sD=7#46C${CvgyVk&j(kG(;w`xxyA_rN-fsL#@aFKGzJszR&Igf#H z2XM%W+V-P~@**MnMKB}s3a!bmrF>>BD`*pMr_7QRG%FV!D?Z8 z_QFPZ8=Caw*b-9aGE{x$96_4-mx(Yft`J$P;gB$b(9Y?rcYEGy31JX8!s+HrLXMY7xgC>8}K_{XN6(j?=ij`G3*R z5&=G}Ymn*8eTU5-b;S^(LLwuN7FLoz!XX))qZH?Yn;*>%}044YBR-ac~x>(QUpF5B-7xd@l<*Ae5v}=-O zAF%zj#MN6j+7uFR z8GZc-{YtaDi+Ik)@6$=>0s*fk*~f+&rr>9Zkd3V*gP|{{p_1igZ8DYGhhU_Y4hVVR zz{6zLlHH&b+k*_;_Md-+VVq>b_h@k2@UQN+dQv}Fh z;O!LwK=r|W>A4RbJDZ-6Fg|)$UdH3AyR4YsZ6CN|NazH%$C089tAlGj5-#+jdwtz4T-?>6MHyTJ^!40kWwDFjlEeRPGFiF0 z!TR!SHq=Bx?rjJCG2QtZdd@>HgI18<20*}1Y6b{RNRR(}rwH2o@ee}Z9mq!`0Rxc* z(~reM!NYT>AAPKk?Fe!Z@|-sSZ5n{}F_nNc8$m3}zB?cXHUS0D`?(0K<1N^31J;qR zlziGAcXIywfBK(N;rhl$XA@($uNNr?DtzA<12d%@n5HKgw!aRy>d%AO_LGzg{y{WN zTr}JE0*d%1en~U$BI3TegF+v_y8iv*5YPqp>QfdRIfIVGNA@3o@eu(oCAwSG>P z@*gk%>;IO^Ro zkif1f2d+zX@Fns8?f2$6kEch_={ykGey_F9;`u*Dv~y7yj>{-+p3) zBKaN7|M5PBv9V)%=ts?})1e|5ihoO{)(4LS)Nkv7VY*)1N#X$?%7%;rj-Nk~@%|Nco-m z4jdNxds!ht{|_C(3Frtb45pCA0{>9ou|x$%fn9;d++m(TJX?uk8P8Vv7MLaa|{ynd-s}yhkJb;N=srE@aVq)(lP(ZzDX6@t^H8Q|jfe*8z>ud?4l3QjdxE z1A=S>+|A)NU>F*GzE5@mob|dQ#Bskuf!|ekWVUYrihU{grBDgcDVWh(jjB!X*aXQI za5OH)NVvxhSGSUd??tJ%JD7q<8nCkqd?-25`4g{s;HIZ>tpEz^PW(uGy8ShLk*oZsgMwk1~2?6rWi<|q!0_pT~@cmGPp5Gv7EJC4}Nxawm0)HN&X%E6t z-%Hy^dm0}|q*zETQ8m!pJbQR_@2N4H4=@J!FcEj~ovvr=&z zXPp(lvvcW*xaEi2#lfO+2qYzfQKi6>aWy=Bmo)G7DI#Y1cMR}N0{dCeiL@tkiRH(O zG%P=N+{Gm&Wyg@}RRLi1np_a8p8}kA%0bY&`y@c|Q}gh*nl{`TU2vxZo2 z&3Bro-mo6qLs1D1v4(K>jH95iP=jjzfPIf4mPy2}@E2=n#q^@GEMgI{at z%<@~$xNRZ_8=&8DH0xlZ-yX!nU%JUH;W%}pssf-e}eAwH= zm})q~cV1_mw^&|XZ5{rL=kO*x%BIT6MXNW@CI&}zklb`?rY;DaC6>yuetpaNVOw9J za#ZV3Rsff--agD8y+F-H$)a7*(UKabGEM3QF6C1_E$HZ-a;c>(Wn^>drIaj{6_tE4 z^5J6ea76)U$HL?Y5LcN0;yQ4)+VYo+2zK!RT>_%bNj+kbRlk5apwH5+z?5yO$#sAn z&jQj=^ny!YuLL~Z5fZdF0rHbV2NJu)yr{&!omtCKSaSC1zV|4U&N^}F-s;gQXp6i8 z*yj?sIDGjqgU@ulkI}+IQ@C~tuSY4vAHY0CZ<0a1``5!q#D{?JumKR74{^D3TiefJ96#dNGZ%3JKf*CeQ_S87 zL*aqY^Z~^g1bUF*kQsN-D@ka2H*c=$b_t5T?PSzZIaYy?yqbEcp|Gdwc=lz|Q{g<| zTHgK#8qlH8d<(m`1!>s<^)^E7TT=v0bf4%L@F5-nq-%GMzoYKl)oUc`g+Ro(&w_Ej z{(qoB5N(v&L$db2W(>VR-PdBtpSCANMdx5O zoSO289LHM}!7+M_vx!z720u;L0T(GM65OSYowHXKo-IINvDRK)T!ncem7qC2v1%-f zL#imRrhpP;CEe2uT?uz;5CqM8cTZ8OLfiE@0FMYvYy@K;rfyB#Y1K9fZ&aR7`xYGH zuv`Fg!Q+ig-&kM%j55jV0@wq=CJmun?k%61-!0h942F}ArCpST9tdF~g8Ad^56Zn@ zd?apv{IHctm!eLW)C2FLil^4l+g5sq2_BuzhS-opioR9>r&t&1!nLw5Q>7eFfPz%% zMkJnxI9+IJW}G?9o#K7mMYlP&8is#G82LnRVVqC&u5=7jNp7{T_~?bEW;%p4F{|z# zZA^%FFq`qylf+zqYVVPQ&E;gpceGWBb|>d8wZYmeI5PU{M>|juN1w*Lo*zPW(uU%T zX|F!ACifU%LvXvV_)C0f8M&kL%`7R34YWQ%05j45x^A5>JIQ;uG~zeQWj}!{!QY1C zO2jI=S26w}#TrIc9>giNCYW;@Jw-)~Gw?N4KZCuc+I94Mx}^x8L;a`!`08G3F3Xvv420J*`U1d4Wy#0ncGW1ftrEwBTZs(RDVjW7aS=oDPinv3b zj}q#(T*-&Mej9M0z@ht+&+2>vsFPTXFg=BWgRVDA289?N6YHR%#8wjSYR<+KG;J7gZ00 zX>knCwCMd+V+Rd7C8?*@S`W@y&M2Rjb6c?$ zyyQ|Pi0kEC7&G5tvt!^bWr+Qk!G~2OHAL`{C=$) zKY7fPl0l{WS}kLt<4wS-5*{RtO(vbhf{Tpr#V}i32G2tvz|&oSBC;I~)&8AdnHRvu zZNKn<>tZM;#||3CUBb3}CyhWbXB-{yHO}Tm;LDKOKF~I-0F-0p3t7ZlqzOUh3;dsn zE*gG_x3vu6$DyVFao3vE)~A60UK^cMFes~Yc~BPl{oH2vY+cvSl@+|%pBt&m(iA2jCm(#Cg%?^hSf`5g z&MaV_h@4IiIPlLtKR1KVDnc1~u^QPH&|+n^u#znCyv0?7!6$+MY^qTLff@?am)t}6 zj!_&Qh-1s8w#PrL-w`!ifq+Z5d;x|rFxx>mewxXBJ{bJ0bzw*V3m}zy-3tv8P+O?jq-V3Ti&7G4GN} z%;vxuO0cW>_HlL5uM-MU7hR9L7MYUy#W6HxZLvHnhdzF#sW&pFbLyka8J#p8euSD$ z`H*tjDWQ5G%5kr-q=j(foGeTsGWE67&5kb|UC^lSa@kGuj|VVsH3zPn{GzGe9Ebb& zM$d05!O|Qn{zP6zp!`)Hz>&J=#Lj{w6gqqip&_W2PcnwMO73I=z9+}RqK(U1(OURU zK#94)>FxHx%c_JsUI>Sl9@w%q3htWf_)sBE0oKMhMd~~N2d5=5_>G0Go=ko7zhL4ZPSQ%KRKNr{&@^JQRI!EvYzxorw0 zCsIEQA~tsnUKP)d96X1TYYP{!dfhRDB+bwo4Rl_Ho{FfB8T;ThR&)_W<0f!w_|O9* z+$#ZOskMXPKjFLR?ZE~jfsqMFm9OgLS#uy7sSedOEx6Mqn&J!3LJ+Fui?iD5)Qn;$ zPh5PF8DTFuV4tA!Rvd}rJaET9?GNCgtvbiB#$wV)ifX zeAbDJANy4Bfa0Bi)b0Lp%zNbVtNG!@6R2NA{spu2DoLR>Gpz3SnP%JZSWCOVBo$<)>BT*WalF!DRS8YklP znD}c!<-->!h#=#gc{VobT8(vGz3X`TK6IYJ5>rh@=qD-fP7{Pf3FRaws(+)jAmDpS zd|)shPW%&DCLtBrk1FlO;^q#6v2c>WeLvTU0^3A#OR;=i^h zINRApKwcH0JqGv079r)yDK@IrURzbT;?3AQ|h}DiQTq@d2$*fai zinXE-CN==XXpDR;5==%xXldDq&15S!h8{?HT-ym{m*S=^(IEU2nc3Oi@9e&|4xSPm z;C^-Q;6!o|bYBIQJZIBwrY`>0ZLlII!v00)u#!&(pms90vt*i8yMjw$&(h*@+Nuz8 zBSGBX+>6K{*MT`Cxk@%4*z8lbez!OC;`Y;cPo)%*YoGD-0MAAW)~&OTLn6VqXd+I5^YanOdx6s&#}}1!y2SlYni~&cVUKPu1YPrfIN%*n#PK z02D@!XtB_U+D0NNUb7#}y(ke=4qdMBb+9{gjfJWwaUB@a>K5E>5{htp-!9g_5LGXV1fA``xFFFLnh>G5lm>#+>k(R8GSuS6O0FAR5a)g583 zorCTo92SdX%@rJN^!wTSNgq5s3)4%QdxmskW(@P*+e5Sa3Yz}yx7uGtm~;JhmjxyS zO&emRI$k%XGo|&uX1}5;9^Ilpkr-Ws8oIdJ^ryr(mNii(vdmh1fx+^#SBsD<)ns76VhjnspQD@R`_09I>O#o=>)r zvtuHu71ZfqZIP3QSX;PqW~jwK4sTT@Xup0EyXb2JZ|Pnd;%(6n%fS9aw_UTcaf#mT zNM=_@2{1lDuuuXu(47&4Y=TQV6Giin8F>bKO>bHm#J=)5OVb9XGMH6X{#urzyz^ZVq412=$Lyk~ z{R8F@O%39iU285EP*q=lklmmxO6$!9GTvMMaNH~Q$z(Y5!IG#|Vt>5_WfI>?6q8Hs zs*1dBqsyoQCo+g8e1tT#5}@*sjUF zH?`pjm``-q?HJ?ZC$%fM^eiS#xqHP3vaHx8CBX0Eg}mpDNe_*b zQx5mu0nmor1U4hjt*;cZgt#t(%NSS1l;lH85a!F8F#E|Xfc~09i;nZEDTA0J7;Hs_ zCMG*ra6zL62^#c7Z1*}JzQ(PueZ>&w2is^3z%p|6_Ct=p;7(Y6X0&*qOIQO)J+aSV z^v)%|J>Tey%lB!1G`~VOX$ykO??91ah3T5_!uw#JINjt=t0K@Vc91p{0XKARAW*Wv z@117KvHws@rq&Iy6M-dlrhIJZFZ2L>R?zP+C(TE6Tk4RNKxsMZVHz92tK)Oz#V`Np zV|7Q4$}TA;E$kQo6XvH5PPvK`DW8SG?jxP@T^1H&lB5!)bh-LeQsgl}nX^9BCRtx% zurdg!vy=NwYtlk5jIH5C+(_B_fN_}s2f1DIY9s5lukk$$d^kpYOlSB5Tb@}3N-7qd`u0fi{M~|sYBNeNXiuKJS zFu}eRaE|e7)Yl&N8Y?={PHHZ~`t7M+8Sbzjf&Mh_nnm>hf!>he)%&2^V-1t-IIZWH z+q+|QL0$i>6n@__Ungt28v{(sn{}g2bNvr!zJurHh3Jn+*&W#^UR!+x9ALdIhfGRw ztA|Gly=g6rQX=Ogzk(|NCG0cS@{nsd4~AGFiqWkys6TH_QSv`km-q5_P`!3k ztX&?rdw#JZK*bk{n3l%2dFRLgp|rMNGY5(G#~iq+iUTC5le{*1d{JR#DRsHHdmNC1 z%c5$6ttoSHEg^h=3kmG`gj%8jbO=>*(kJ2_>ocZ{Y_ycC& zBYd8xHmc6Ht=r+{MNt2R>_H7M9xi#EDR~@zdT$(`4ZkV%Z6_k&Jiw)AdH*^aYCn2<9vVaiq`TUVLzKc&ti4BhRbK}TW%w~TWC=26l8C-}F zptI}k7NxWQyj}PU^1gM7+hg6S14NybB}>zN`heM=$|#zs~-9D${O{@NV%AdtUh|*FA@YiE_b0GT?{&D_( zg^kctPlMSPYz$E?+XWf_^PNCyUFK#&_pA7A@^%VT|2@K2WC0*`g-ChfA5HY%k9Awc zjC>F^o;+N0)5wId=6+w~EFJ!M>54{${aUi|65rk={nx*^M**aci1UTLbnD;4W8k9| z2r7uL@T&KN$7i?Qm4CgF@WMKtBvZ!nk9&SOfxx=qCE}KK`K0#09*^@1ftZ2UrCpXS zy6q~Y5(&?SLmH)&$nd5G@0{~r_wB#FKJ#Rw@SiK? z-@f^sb^-_Zi13l^$)9f$AwF#a%vbNZW0HT{C;s~fNSWhLk(8CJ1KWQ^ir^u_dN<5_ix$dCI-xQRpG#P6oGX8a|^#3?ww2HH{SFBU# zIACw``X3eMF_!-ho~cS#GxRv1Kn;zsE~wJqeZh)W;ex^P%+G9~wu5ZzIpj@eeE6#f z^EMkP5$JP%>o&AWpTqbDMdG$K~Rt$&jk9O zHq0}zn`}R4SVCS66zOw@jQaSyG82yr=Kf6A14Xub-AL@kZ?z-OP=}ZpinKMal#=Qh z(mH?DoxLOqrr?)yc;6-x1m#EXdfE*Ok3_Np!!w8=Rf!wEO+@T*FjMj*jHSTIolB>w z7jT^9N@8yyLRUJEM6tu@Lat0fk+}f~YY8B0A$xTWKdkM~6GLx-oX-g1Un87o(S#*0 zAUTGDmOo;8)lEO9j}A4kwP;L(`#SgW3+X8Bw(Wx=mOYIpPw;>RPr{SyEngO%Rj#5- zK_}Ogq#BdFl5KxJkyNjNI{e&T)gp%(a`cPSS1uxULkOn4T>k(S_VjE`4YRjXg=^du ztG@^?`v^d+PzW(nhrmEo1(4<$$~hkeRXzR65cE`n!27cbkf4MMk9N*MfBq8GtbvAC zItZLKGla;Z*LgLEj>{u5`+279|!{1Xb?67 z{ym>4`goO@duOA~7T!wW|K{;Ov=*gSpl)9D@F*$lLQlNh4F)gXM#|6iCrodNm|6dos$AVM=F5bhxvj)t$D&uhLo5H zIU2#Kr8o87FCX@cAI*QnrAJt9!Y&BU2KxYWVr77|9)=lBe2I*V40Arl(dP1~ULVfO z$&L^5^WIyqE03rr0=fAcoX=;V4f<=h7bO?FVR<%_ORw8Bi{rI8s{;T^TSuF;`%ihl+On z7=qBQEX9O|nr!MGs2mJOhW>_mvLhDspu)KZa_a%@?+Hw#IU3WzgObU35AgfG;^Bw- zG<4$A51DKr+x@wcs*$jgm43-Vd@ZFSp0N*7>HXp!nEY$iKMYH|)(K8`+iXCxQI-Ec zcro9wkM7Xo1?WdP!3%^sl&=eCNmO|p*h`fefcKXfOKl0+2=RDEMyL<~h2L9JihO7L znt&@)=vWMVb6W#Yzz(abwfvxzpcG;VB340NLhz(CN(2!X0-T5hJS19rGpCr?M~^i? z;f02n6Q5>26=MV5o>IUL>t3*=R~eZ`BNl-{_V%UEs}Lu0@<>z?8ra7B)k~VIPIH6! z8x356!|Ej-cSW)yionX}WTujd(0LYPXRztL0Ep3#+I67D2+picm+pw9ULi_q{!rKh z?Ef9e&@0C%09<->jh8ys^1+rw&?c2~+98T5mqbNM5j|##d6l*%0sUkzx}3dPho)EI zI;lrJw7J+bnGJyr^ARPUTPKFCk@DGlqT5CIvy?YD!IGy#%E+r)Dt|F0_sOf5m9rN_ zm)|o)8W01Rbk{tPoxR~qzuhR;o#jzy#VuufVE&-9HS4eUdUCmJjsk)Z3mw9#yFG9q zdSMgqeJBQdwb!1ii-%eZ!2ORMf!X&Z2iCO%e=!#9o~As^JlK~{a68TPCvSPM9{5_r z$~FUOX1K)*y{)2=dr^!+cVe$+$kdDW4sf)tbVStmJmviv6;o+n1&5LS1Tkn(sD&99 zI_IEaL7rZ+YW~4fCG)-Gemt*!4~5YAEW(E zxwT$XNgumK4CRu7Nr$jb7&ab;c=E_fCYaPm4?o8jr~f(Sc`l(#yuE1+?qhy+*Za~f zGpjIPQjjhNan-PE&f4`gHg?@Sz zi-UH?Ssx6+J!LpDZcAl8OcImRYzRt$Y^yGT=OeGKThqGM+G^c8HbC%2(cmghA5}0F z$qv_RLy#22+n{={_*T~d2g3ikcfZ6CQ0sKRsF+dvs`TWF3_3$Lk&tI>3?DDaXEshG zVGVkW{akt-c)4*|_vJ}an9;?bwbZ5}Z-7h#*m(%y{Mvn0RR%^|h7cF!$)G2IuOP|i zvND*HJEus{46NMm3pk213ouNAwh}#N>3okxv15y?0y|0$Fz2wSJ(IW*r&3vaGfRhf zh?ShesQdm=y)>OR=tBq9B@B|TgbjfmapkQwxih+2TTm^MfhhD8_G%#Hl{G!l z&F4FHRhK3Zp>wtEy?eDMX+%`Fj=%nrH$nP?v=>yo11S~$47&1NWt6v0UAA0ats@Ed zYWD6*&0wWAJ?)=F7iO?nzw)#9g~gdz8_|{0tu@KE6P*;?IHmy=ra#6ZlNBvQ#7)GW z%-m0U=u<@lOx~OPX(Vy`8Q5t!U!vN*wbTUIJ{k-}k2Ev}&qve<} z0Wly}nNd&}q7z0AykKa1CD$fZ6bW{$n6|C@Y^mt0!r%84u>bEj{%>8M0vr z!VwW*!Kd_2{p;7+S`ivVIs>`@qT*E?Nb=2X)E;K4(j1!lPn zsObzz!)`V8PvYL@g%}pBgDkJay=j-$ZO4ZW+X?e~DwTeBOL#R%4B|do14CE2A`!5p z1C=~5O**gnId-uR4JV&EbD*PK_6oad^yDi~a8`EmvrUQ+w6UHWrTH$ho~n!}=qEry z-x)puLr*9tJ3m%~b`)ftrnw_UE2j-hb`v)ar5rER-F@e-oaL#@Ux9Hqp<`;YI%C+@ z<^s+K<+KlM0F*|fy7Do==szaFmKqTKaEv$vf*}HQ^S4ZPX z>MEh{m~f4VTR?T$Bo+H=cwy7^u3ROBup@_VL5q0r!Y3x7I|d4~b;*~f=8)!{?(oLa zkpD?cT^nUFXNM;VWIUAG-$HBlHlUTP z9|J0UpHEESqT%n{8}Ml_-j&k#5gL45#`I{SXzAmpKJXq(s7m_$l`snz%y_|UWl>v- zhimjFoFxp3lZe^}&XTpF5Y!>hJl2o68bbl!A7&F4wB26UP#ix6#Q?APOnGa)4G}ja z0^CurbM9$46+jEGCqPZ);>99p3-5NxVhGkszd@hn)RSHt&l=tS0AH*5P$`LxxRP7P7PHQdsMxPf5P0kBraG+OM2ivtU@#Fo$hN58gchR7F zw0#!;u?%J#n9U`CH$umN>{7VHjJ)W>9ca_89?<+x-E{y{wu!UPLB8%|-`jKnQyQwF zD$WmrB=7#mo6FZpRwjjI<*O)Ep^uwY=muJ-sb5fI&0={p>ET|D#uZZrM zE@HTQ0`DrikBVqoAp%%s0R{CUA_;mn;N3{aPeb*)dc=DrNK|3TBpJ`)JR>Vr@Z^X| zOZ~;2NEOGNjmHZOnTBzldjggN5jjB-K;ll+bEU1CLDV74^2YZw8KhtebL7+dTr~+a zim5cyZ**XFAlhsp!e>N6}do7HrU|2z|D^E^6{5$!Vc=J;h}_%Rp3J-r|W9 z?1z=llE||-r?-QwmhQ}nUkajM_wM5KYomr1Z3#3bmkzZJSb?{HVx|*#YeeVeG+e`^ zR(ulg{n)JNgv`9`9s*{pN|Xr1`qf~GG3LXZubunk{SVPLy#gSbYSfh5#b55?Y{1gB ziio@-yr5eS$n1#6it|kW`3U|&;7*7h=fzj%zAw>;GqxTT|FWPu!t3r4^W4P7uo~SY zP|Qnk1QmR|>MDEei>z{OcDzf4y>c}*4v+u32WPP2 zaJ&;s_l4z4gUjl4oh%!y=zX%Hz}#tEi~w7ewQ22oaiBf#{<_mkaj58Rm(RlVi65v# z85#-bgQBW=%HQ3*k@*mpq3OTm)Uw!2du?;AZ|gv^8}!Ul2Wqch!*L<(S#?7vXF*dc z85Ccz<_lC_&#!-zZ1i$~6cEa55=Umm$L8fSbA zmT)fV?<(`d-P;m;_k33Qxf)KQ=FLZecYq~&e(d*MC4d%jh?4J!LC9E4_#qS)hygn; zzB+3r!flrMAiz8myzU1;YV&fdw-vKjfN*d@!y}c}09-N$ zTF>`&+Grpwp8`C~M>9jOXVL=tdKl}1nA!0(dX0q^%oq*E#s4ViJ9-iwkLk&eYj(22 zQl6m8cyK?jE*Ly16Bv$FJ*tDX+z9RzFDB9p>ox?_Dx|=S1nP-`XV);1V6p@5FSo{Z zOWanHS*=HN6*p;@;m{x!$!-Vd|7phOtJ7Oh0qySa0SpAW&zA}JnGD@dTRPvJ7Jpp! zBG3neTk-2tYIaW;m}9zPjzCKEHA)YB2_r_}F9n7@2`Aj>D|pu|BpuTaJUouDcno9k zl(of=9IiOt;2r{OTR?m1ANRP4*}!Jylh=daUI6%r&P7LJU>WOO(&GW<94u*j&!C23 z*0bWfW{vC>dzpi4kISGce$-O!(MYW=P!B_wjZAh-($s*m!f~X-2NGnmoaY7UNl_1r zt0Wp!`BB5Lu@?`7&e#=U#%JTbrF2FRG7s7JXL%**LGMOD8IL(^116s6T>Ec8L%lgS zn#>Tajw3?Dm<5J?rcY|DpTJ29^`HQ&Rl8@~BJX;i?Yj{Uag|#eu8RC9};VXl+kLr#4Dg;ee(+_uKDz<~=@OGk(L8l``_T9Dx;E zDM1L>7S|UkZ~?mjAF%CMU;QUm<9pj+U_Ep zpNa+h&uidr11hZ79k~udjNArNU*o_8{1%el!2Y(!9))0HT;i~6F%bkmq?RMD9D?B5 z01^jdSCNapj1PW}A%0~Bh)%5@1SCu)?UDEs<42ZjRc4&h1R|=P7wDl?#2;!zKZmM5k9asaZiF5s=1}U2AI7? z-_U4jxeAA<0%iPkgQ1q5^V`BH@K`*&3~~fw7`4u`QUY!_Xx2cn zz1M)rT&Tyh@{zOtj|!~HyWf63$>O&j3I>;7eZy-#XV8KEs!1238ZA>V*cDHsv& zPX>IfP(=i8oK2VKe4{)SX;vhp^-~TXC4N?I2E`)unwOL>vYhSsC^50A)i7q_a;#;o zNn79#B91HdHZXLLK}}v9YDSBIK=6?ggc*8*pVrta4!`!XiZ;EtzcfL8}s7L3NZr=Z7}cv=5sRg&>b1 zc6N3)W}3gDH?WoE$kh;{x$x%G(u~~s!4uq1gBpoOj1Q6T89dd0`_Q3-#9BcU_UJu~ z7wKW`cL+@ABt0&lV$dy2lc)%nA* zt+YUONjPcEE@n((k#o;X!IqX5JOq5<`^|h^}6nmI)pMd<(kSJAvQYK>C*z61>;y!re&iM}S zQx3O$8Ey|)tVamnGZto&cSd|uCd^L;6l6o*9NP8O9fo`qpB4YfT~Z2~itp~7J)7X` zTrU9hX`YRCHNoLi5fG-m@OPt%2NU}V(RlX1-E51uk+#d!Y^lB=3>u06$lcW8Iiugf&d6tO#T;ptZ-gl&FxfUPA zFkPonY~aw`Vp!IwErh^f><33n%B!_ko9Ymv}D^_Fww0FG-I68hl;_8W5I%NpXqtTEX~@4oDee%I)Qk-j&IBgEHl) zx*7tvp3_m<<(A@**<%|2EF1bV?AIan=#ju!GkMM<`n_s3g{E`2MwY>|E@{f_>zEWG z?#ng!e7_*}MLVsy!|One@gPPL!FL)vhdW@mzW1wM0WZ~kM%`dx{N2cG7!1qaO`K%F z(#wDL(K!0!#E_`Naf`?%8p?BCL!A~GwYPSB$Z>buVA>k+Gz7kj{($w+TJW5%by&UK zFZ!jx&#E?V14pXe%Do~1p~|F~Q?xqX>ii+4dG)E;$1c4V>B`k&M)is+aG1%^zIQ6L zyfLI{ggHP!GwPdd@8K!z9E`+yHS!FmNanj#-jWEgeL2@M`Qd0xfCsojo6H`4o$Hrj zk@oRwE=+ne1m@;&5Ff`VlXtn_!Gj|o_a(d>zw?a0wK70*bJ-FM!<2bNyPZuwEnZbl z{o#=ID#`uHnw|@&abPwV#-e=b=25jX!&m@X&pJH&ESBZ=!K7YA(fI^!A4!t}Mmk;) zJGk6Kn?X_sLM@gq9sCYs3y~5`$9}Vwtl4Y0(%>73x-RL zd-5d{ackVFNLXjH{sduq;F1u`&GXgT`p+tWB_icXc>@4M*~io{Q*!hBHNS3z?ZZN2 zc(RrA#;45kt5IBa875^S6RC7_2CoWatYIPk+PKq}ht#guprEQ0wSKbx%^{4(=wi5B z?F08& zL?3PgK6Der$#?y668u}b{b9H{~ zCa{N@7M-G^9Um*_$e$T-)Lf^Am2XnU^5p1VYiJ@cGAL#v_ne!S^w(C|0Ka7soBvi) zmAsdwv$7EF_xHPS`;Hl`3q)+rF5SGP*R8L>|LY|ZWxr`KZ&<(FfquwaClo*SX29ly zVD}yAFiB63PcYZ|we@WlB+l+RblkgT3&!qIpU!4jlOLpsq*@_4S$Nfd{d|VK8Nv{= zpRSmbL)BcHpS*;N-uR8~eRrS2!B}Dg^U>RsUi1~__mauI=cO<3qY`h@*;JgD689&` zmWJ!*BtBP}b*15oM4XloD0TeYZrrQo{~6D;G5Tq+>il0p<4=e`w99+mwF(Ax)Be(T zGwn^1+!#B?js4}v#kun?wpQ@TGPfWR_XD*gTSeq@SgG(aC^wr7_jP{%8UOPTgLZnQ zuxe|H^Mqwi!WHDfm2vEj-ZJZ`Z5F z`_^mw9}J{7}G* zOGL(q6OaG>8B(zyAraY+(%{{TYA#5-hRHG**pyK@#47asZd({8q0{?~ft}`)K6Ct^lWr$ntBp(tm%a|N58A?}WRby7Oq*-;4FRG~rR^ zp~9*fr(TBq{o=oT;aE}Pl&xS?*p$;njyL2cLs4f$6^D`51a~$?9hlG)1rm$~= zGd1hm;hVMmZI-V3qT9dZ-@lE2PTuDUi|*pHD)zr$Cf6igLU3t<&2)JnN=jQC8r5Y3fs%}1Bu=|I$F*f^aH-Wy zSYj?X@FCzWoJA|OHq>B0;no-G`N@{ibA6U2O6xtD&q({V(v2JSWiQ|B9Ke#Us!6S3 zDs+O`k!P^{Bg12V$#OZ@<7tnj!k-YL&0x~DPCJypzI7^a){`**^{6QJgvAo`n$+zA zSzFqf9_TlGabM~=2q2P1o)~%c4f`Kg?5m4daQp7T$siB*gDBpoAKB~w+&1{(5Hn#_ zn-Lq3C(o+HrY167=*31aJ%rYc1?~%xbD$Eh2!p_^DihkNPhjHx0ZD@>&&?I&(BBDV zy600>N70`T>3o@rRzF5xe`#TGB*9?0D(j z!7?ah#3ysRtfgDEw+Ds?TtQP>i~tn;RNWj@^(8L1K*MyoQ!sh*lanX(T^}NU=R8Qd z+Vb`y3sFiLxA)^^x2;MkRWe-AJ^TR`7A=tX%BO<;SjCae_ZcNFLLl_HZY`*$H3?FU zo8Z~XLN50;;LZaPdz}CeDlhsJ@!ZoRc_j;Jb5&L_bFr-qLY zxjzrOOe7ROfo%S2$LS)+&2YxXYy0LwLMn-oxP7r?sQJ6&EzV0=mqKmXxrx_u4(n1H zEgQOHJJ4@JNO0SnbpF$dCj@k6v^LQ0By?O2ol?K)%vT;U(a?*iG7us*dFmj~`R`ym z*ZG;)Jr3N^<$l6;ZnE%tLgMB6en3cP2SWzzBEL*0!)-4LKFg#ubZBSj303;GS%9_Y zh0b<`(tC=R&yFA{+PmpciSvt7U!Y#F0a$4Th43L-Bif6g`oTFuQ5(&r}Lo= zm@U-qdo4g=6poRNLcKDm+)Onz-_V@?%+R8gGpXPTK$3m_axwGmsG}EE=pS7B zd}|PB;0#j+kljD;BeP#W-8i!$PCY&0*c9j`@X*RMP1dBY4z^T30K5Hss(y-CN3CPS|WaW8XEo!ZxeSRGrBU09KghfAEze`b8g<~NIV*Oi^3dF z!pWEVxF^lQaVEf#7|;tPue)Y#ylX`#wv~!((Xl3+Y}7QntnfGNdHt~m<5`?)a2Q-L z{xEEe1ZfE0s~5TMA^D2wj2$3PddQYa*F3>aS5oW%xsuvG=F-NBu}ZNi1OFvLI>5P* z)tI#AjP8ZYVM>5Dkeo5v8jSc&AI5-Tu_=L%uh`|F+gBi2MyrJ`xwD}Z;?w3{I>(8_ zDJCtic6O_LbVWCGrdO}j-Uvq1OoQv{R|`byIVG=rda^c$Px_&i1xd)UUO#eQ z<5%FEmBRhs1IS|F9)InknP9hLl4qc;**x?z5!Bzk3x+vs!GYTq3{q;|HIVPGH7BL< zvu%1L+7y%8q-vlflWJOI*^|l8ez{COdOXjM-65rErr)a8y7T3!I;HGkzg}4WyQDu) zDOLf^t9dRWM&ot@^_6ud#GW?MGcv||XBFs1 zT)6q`M@%{U66&l4k1I5&snTmkmo^x>g2?G9FvpqIA*sV*CB1C3Eo=$woHJ=Ja!y4h-6Rbi#!}v_2urb&P7xM->gg0a;4L2Df^uZj-1h(P!voX;VjV$HcU~e zBknX}b2%ARs=egn-sDVsv4rCqs>G@u_bndN$Mf2EBbX77Ba^o9ks(BFo}uSLm`tKR zd~;_Fn@KK>MYK;IEEI)>j~)#RW&>bYUf>Wub3Utoi%gTsGRQ(i8UVdVhY6S&y?5+C|8+L|!&c$Nq6(!O7iftASQ${- z5BKm!=;wz$Olwwa8us7A&-IwO>X~d`ja6KULV1eXT^=>!*4J1JoZmk1YA_6l zsmMIeot#=Y7VMweu-b9Zh3(?*58FdJM@~m4Fn$d58auVB|9HF^DXVG*} z${)zol^45wDZN~i^c6G@^7mjn-GsI=yP{`w_G09?_u|#+H;}_CEDq#$UMuF%6_%}V z>gwV0J%D`niv;G5(>&0iaNM;A*vok0ii&${fZLL#wy1*J%10YqfDI zU+Xc5ia$~&fef48?!oO58yBqj>~oAMvT(Tl@VG8%c7Sy5y;@ljqQU05!36jKg8kYsK7Dn@n&dyDCn4-5K_96PbgUQDVr z^jX&G2#L(j)(Ik`VWxE7lcB8OM`vuKA4s)kB#HKk2U#+X0E6_|=aJ1)^wAEEVo(lS z2XM$4hnnD!)H4sVz)^F`ZQGCrx)>z`w-5(ZX6@$%OW#>lL9uR~Ir9q4TiLSQd_*|T zXUgY7y4T*DO~YvDGQ)kR|0D!i&BAw4$nr}z>P1IPrJUJ@^HB)SZV=q{>E1c9tE#(} z5V%~w5veuTFgH+zdg~tlBEeeqt1@+6`e4;75P{dN4QCmWGH1YGD@7nzrz!bxb%LyS zk#_Kei`l-32p_h<3lF<)IP{in4D}^}BA;)On*dlbL(?pvFW2zO9a>{*pDDljAiD*t z$oR*rQXgM*uM4eE57BOr(a}sZId7q`Ta#CFb9)%m$2bay?nW<*2*=rSCc!U?_7;f; z_jBu&StUEPJ`wbgPn@Zb=`7qEJ>V+RoZlxod4FH2W_3;@Oj%sx$f0EEjwL6<8b?fd z8ZR~I7)Zf>-5v72DXKHH8#%wfUbP0+bK%7s(tv;Lto(Xd5yKLFR6qHIPG2OFnt_y^ zoTLo6k9!}I81QdU2E-q1?&8y7YPHr~tQsQhXO#vnB-uI|tchvAhdi28+R_*YNyQwC zZF-1tePfS;7SiK}kB?DAoEs5iTN>tP6mbwP?t%O3q~AW>X=!x%{_J!mDXW)pqtx+D z`j@SyKBydAbOR*+lJtj%()5G7i#LZ%=WeFEWAr7bo!9s^8uk=@1T4e7wZQvaRMj!@ z+e)d1_q}K~s2L_Jc=v-39&F#TLX&ZS;1?iha+Pjw(A`XYJQ?tpITA_jWsTx#W}A7- zrjs+%XYBgSYsD-vl$0(_LTpn{3Yc;YHwy^FJ@gL&?TK^~9Zc$isaA``T&Ya1b=(Z=YICJ$@B-FiXBuB$cA)Gr+HdNf-9l`Zym z&DT_9Cn*QLO(|{pHY;z@Sy^dwyx9Xvg*{)dymv#ycvam8TEyf9o~5n!-jC496M9X} z^C#>R;Y?2bShyUsoi}M4Gb(!8X4{ne*;hSGM)4sD((*@BezaPXsh(}Ok-5p(1&GKh zNXz?vaNd@q&pgb@l^+-z|9Scn)Y9D@GoRq2J*o3+zgg#CTD9-7#-00&qBH9l2;(N$u>*~ z90V-A=CO4y&64ZN4}=Q#w1>yPk1@8Z>K|LedQB@0vOKRq>*`Oj3~6P6)R}x%HWMqX zULmoDHnDl8vH5RN<$nUb7RQSc*VE_0s zqB($I!R^C)eY{53W+Sr;@bGl6p7=?3chUT;wwIh+*)}~^7puPqZObXM{ip}d{xTw6 zQwze4Gq$M;?!J3Z#L5WrH6q>q`)qxzj;tWT;!sJw{Ajqq1Jn}RpBK=pU2mT55Zubj zU32LEaHO~^aB3MwtnWxqG?S(r8AgUeb-Pm3nqTlK-K#sV8|2rT$2Mz{24rUU7uvy> zYgUhFh2IhXN1zQZ6YqR%bMu^kbk*30XZLqkl1Al7XPXw3N;xeP8OXYtyhGz@r>|CK zXKq3{Xen9zI)#OygQhBEG`WDC& zv1LO0E2sL z^0n!l=a_FTy}{W?qtn97(ToQiFSi^sG%j{r`e^E|H9=Yk?okZVMfW~oqVs|NK%*~SRs?BL%a!>D#y(s)oFpwj zn@@Tupd$A9gzAPU&-Paw0>rBHS0Jd^U32?vc9N;sI;pin8x}kr_BMG1M0j_n`%r1W zBR^O~PK?Z1 zS1-75>uioO+&9VN?>Ouex)QRkFMq^bTyJ7}vSj<^B6`xjdxILKnDp6t&?8tvgtjXi zl&~z{8=#p37e35xNZ(}7&Cl8ED>J_2wf7(JlRumBdRssN3FJ3zmcGYyU=RP`G&@x2`_va(B7Sd zo!<_JvW<>F>SbI+V%l;FzB?y=+FmDx((mvjwvaievl8eu9XeCr4_SFcHxncWzhP z%Uv?5@pq8*fke+p_C8(wfdAAnmu}u>Wd7cS!dzcuB~*C<=+!J4vrF>s1sFs| zLxzrlF!EH+KB|{-Uy!UE}B^_lsLB31>K)K{9hYZ^b*hGH`w`rt_4y zh1Xo%eQjHRZ66`fDyx;Hi~oX6xodj)nHTwXvqg^6QumtRijLAfq)$u4cLaFpa?EJG z<;vxJJOm#8R;X=IHNC${K=&e1KCJXYM|jDjf6Y(pO?J;6rL&;IyT4IjrnriS5E0OR zxn}5~F2BY5OVzBweggfqa5Gfq*ZcJrU~*+k_kkPC9T^xPlsp_4^L60JTE>36&7~i@ zI%D2OD%c{a`{rjX2z1nL&Ar%dzbta>(JwgAI({;7M6q?O3CY*wwynE1RKSq9YX66@ zi3bzV_zy{g)uaU-;a&S03;)Cp@+bI%JSx==`J#j)9OQT5AWw8?b3=yQh8;_7c*LE> zPlLoK(y~V@-ke(;V=mC=u+j;t?JvJg-`P}VbpNw_u=bKV$cPyhUt+J0oGms~p8HoTcBVe%YX&imM8;=(>UYj) z?LI@0mfpoGP+yeup2i4J5M!Gsx?PGRbw*QP6w)Q5Ty@)#%B+*Fmk(~c2_=p~Y8O2A zxfupoY>N{%&r~lL&Mva^c>jHBlI_BucFI-?hWKCM>GW2V-M!27a=WHlPxGy9rwlti zI-O<3jXlI->eZs#^+~#YgUrnnlGaT&4owJ6x|aN*4s?nBjcfwo-u0eatTWjeg%Xl)jgG#1MI5^F+6Bs zLs*8+(c&lXE@D|+9(0a22|UJ`NjT%Qgiw@Wiyxp2K!icgb_hys3RlZOEy1<1TXJ@P z1Vh$5y&vKhmNOe&*&ME=&jQSzl=4=~wwRYg@K zok$It^z8bYp`KTLSkxiWEdRVm)q0T&wv#1F*=Ov;024RXVT0?BOKm*F%4xN1RAO~m znp=k?FME}jY#Q%@>u39GWe<9_+f^M;FEnG-Z{JY5IZ|;pIeC`lh_h@(QAkp$?tXOA zcX}xH@!LBVUX@=tEeZj7qR>MnJGM$41i;zNrYVC?O4#X7P$tI53d|=#O6F53X+iU~ zR*!Zw0rZ1f57Ak#n(_&0Vhi3ei!h&PXlJ%!L8;f|ofXLLWn{w=v=i4vmg7%Hju<2; z)p>J5u&Td^5D53Gg!Sh73KtgEP6$HiWu~#Yu?3*+XIHM6zV`!KU-n0i{zMQs(&<{} zIy7UL+NjtM{xOmWL5`|`t|HHj-Eu?6^LKjfe$oPDUmmZudf9Ny2J}=}c6|jPk}K4q zIff7jx}Z}QFaOwGX=)y{A#jiSr=u$sk6XL5$Mhl;r1l0#XWh7+z1~GVO22TeO%q6d z>p|%^ch%+nswXF3YVW1te`^YL);p`*EtnQu4U&m@XPBC8s}UQea$(CE9;Ilr`=*7P z9v_a19?bwHp^JcVa@V9nkgkxfYGKEQq&f5=Y50LorCb5~G`b2gp`)8FwTIT&vWTM7 zl~O7hqSzNxJ)GniZOOPmCAu@qyuvLmK*LgHt>~ss5CZP;^;JSG<0(!PAj$Y2;tw`R zIGzIKA9`?X=nzStt7JuDjBLrf^T^sSH7G_X^1^HH>1jU~#9U4u-qIKVF)7>EtqjO? z@{3^^j-esT4d}bc2!gaK#nv>vejPX;2N8U@v_cxLaz~3O^h_JqN^L&P*9>64Yf>_D zyE`K<$Kvd>A|H&B-bx-N6ad=YJ*ICpH4#1lNkLW5SKgk8v#Z;A|Eg?b)y*pB&r5lr zrv1r^6Srvoh##@Peud@>}Y`&&&eLHu+<9py~KH)Rj-XY-m z*ZN2hUrtWC#qv6;3a*?^MA%H%{&eJ0v(o@$nESU2Ek?}5#QsJuwye+8ltn;;sMN5k>{$EBhR3x+pHH3;@m%`;G811Tz`+6SOtGxmbvL-BR?gZ$B0||F zf6Fsv^w3bUf*3UYFTg3G8+QE}8 zHt8zZL)Xbx8@yO9tZKwGvM+(_ebkF&)dyoNu`JocCERtj*<;C{r}#bJZx|thJP>_m z;ir;o4xs>7pD4kS*o=Re0O?F`D1%#LeSYl(=@X2#RdEVE8X`E~+V;i+9M=Ik$s*Z) zcA0ICI!N&9tgs7mLDjX+n~_iDP9XFW7bb$hc1z0=Z2gg)pEE~-Ds=Ji;^ zGgWcg)2;a*B*h`rcIWUb#4m1AF+s@+kj|YTWnNpw9Jj1BSyGHvyY$K{8ZQ55$Pq|z zUb`s6B1Eue%BR(WP5;OmW^^VVtqTNpr!w3|Pz+N4@R z>4*Ds40h(*LrYlBUKAOlD`pd77+!MTGKP`3z_t6G4N}6?0%sYr6I$2s8Gsky`35x5|_KK@mx$-KCI0 zZpbVAQA|qxWfu+QbSxo4*~YMFNZm#ReSuWG+uA=7Gob;#t85-Kdi-3(j-M^H53?xv zK?E{;MhEyoPLka2=sO|Ah63VM0Cq~1h9lWUb+B^B!V#Cn2& zgolzM7H)bigj*~gn1D~{3e^&SgMvA~D6o&uL;hzKR433OK9cfttwYLIjTW}%=C9Gk zMzM#qa8U+Sdt zx5rzG5ukjrGf$f*J0VPv zHfORr?$2q*I;)(i#=)x4*}aH`>4lT^s9q$vBL4_3@#CTxx@TrU9+lk3j_CIy6z)I) zJy{FWn=kh$X;>&U?jgH(Td+x796#2EW*fe3qy^isN#v3tlo9qdE%U7&JzRWoRWGBV zf~;laQ~AgnA8zfDMa~{bH;dKYH3GMGSu=n^uORib2{bcG{2NpbftN2mHj;PbsZ=`* zf9{cW5YKbIvW3qfgb=!&H9+5A12&9n;+!d|`+KKY5 z0jOIcPJAu*3Uc-$w;pc@K};COLj*zMc<8ZbEiyoDYmepVD=Dp*s$hYX}00$EQ$uW(zhai=WoCp%MJ|#YJ{5xQw6C@FQ8GJS6@ejMkjtG60Xi zrO(*W7Py70B&+u%@T`y%9XfIi5I=YO6o_7)zvc)|`k30-2UXuHk7l6qkKUQX*uF>2 zRYoNCK8W5vZ`iBGHd38t2bA^}n7kE3HyrI~%`Ds+ir5N4@3jJP@=mRC(wC0R&`czL zxYdg&8^^Pze$aMbQz~?q1W*a%Y){TCch-=H@k+?j*&~UQpzRubS9mn-GOn)t6J_{a zj*fBblPs~4W|yt*W2)la|73c7ZEBTRhDvNIU;%#jZ;Lh@KX^OBu4_qnAtA7(Ug?5S zQTMu$O`#uOfHk;bl|2&T@!A!ty|zyex{CAE6Cv;Y3W_fdUJUO3%W_zrg@)s?DM&&5 z4Y$ukq_+25qSX>Upt&!lN}=mCeT}r{^4lGvYZ@vqRggUTVr`mY9)vQbp5!n0Pql5j z89D`3Mnd_O7Q$9V=B>U>k*(x{2TBT&({xwptUgl5orhqvgQc3YdknyhJe(4b9c{p^ z%#!V{v1qy!n;xVwpwL*KK5(Y7QWV{%jL{O42M+@uetRF9`)~nP2$Btx?!9!k0I*c4 z0!@dv`dCR6`9O0P+i}eN}}P z*g-+hjvs9!*&w9-X>yLoF2uwkOORfKEtB0U}&zXDCad3&?&Quno4kTl8 ze%*`csUjj0F?Yqnoovb}zyZ@kxUcDQtkZYf55Lv3etxRTKB^rFBk4;+)kh?*8^F~~ zM^%BFr%^T2`U?2}Qtd-VU>>wHA;%+vU(@N&&Y zK3?~@>h`_|f~+=Q{xLuhcyZ$)0ly^*x}-rm(j6Al{IvyoJam>ZtQFXTCsc|Fk4*FX{m{}^@pDBG^_|#&=SVLhC98?HkE{_7{ zSMrD>oj($>5Wr~4bQ`aqYRVTAYV2(Q>FDyLMY(&sv4q?Ag|!iiFdDOV^y;Y2FcEx= zE&?uO_dZ~c#5PNR562iIlTJC`N+j2nFe3kP|KfnN0R^kmkaW1+MW2kM;mBHsLrg@U z8>JWe6H571X7}cs-~7DKGRn*Pmh=Ad2*Z@R2xUjevA&OyT@5J>rFdg5$JQQ5%&PYa z*0UA%tbW&4?kYC=PlD*~JC|HpEQ_@VPl@&)=M33<(aSF1pGP(S>ux8V$Pmkt;kWxr z_IkqgeOssU7d^F$KWx67|Co+D4L`DiOZSqgMr?hpV#d~`Y9+Z(e2t_Ng_B`ba4GGR z%PUV+qwDkEb-*LV{&ALPwGPw=l_6<&UyI;w(d@#?%USvXe}zW%e70Np*K4WhV=6n( ziImGNcOsVQiTT*W{P2t<0?}#ZvicK!i7EtXGlOwEzp)+$FX6Mslag9Voj^q*$!A`% zXp&hZ*Rbz_RMoI$B{OiY>D;seM(-i)szi*66%-D^?Q`G_j_tYhI9PxD3ZV>`<$fCGZ;#d?q}Iju>%WtBXR#91npYoOb-kp|dKvW{rhS zXn5dEv+iasT=YODTx70XlZXN!kQ=~q0AUFiz0r`50}J_>o?idvOkj)e9tBHDH^sE> z2TRG-zzoVDd_x`}{zETRd~QmRu{f03pb62h&Ln53o!P#pW)4uuz>{)Ie20>YF_P2f z2r~LoRG~g}oQMSI*3X0z!PwFlA$7Hl!@xtcFBneCZrthl$6aBs5J;r6_n))4C8rlF z8{Zd^unS81GNJ(v7!87$8cTe)|9LWHRcT$>pwB<+E zllJ2e)pc~$%97B%&6?6JUO!eHGx-2ikQ(*&ddB+JYuFtG&93f?i1?V<44jG@vCJnO zqM$(bB?R+{D-+z=Sr0;p-)?$ih0{*K%YmEv?KTR=Opd!q9Ugnpx4_x5a>4FW_7GBZ zUu?CtV1!Q!(9D2FN<0_!AXHX#C_k|5jy_x&+@9`Gd}0Oa4W3zXR;n8*JU!_S$6(?F z->pLh9H@8A@4XOUset~s$pU|VRR&Z3Nca>z@g($bxiqgsyPmqtg1lca z2b))L$}RSLkDda9tTnsq#w^0b>;MouKS-B<+sk|w(zuNGYJ}^&R2%9)%H*MJ(CS<1gyB0;U8}g~8JbPS(xIA_Ny+Bvx zO^wIuAl$JFaV z9yCX{(_?SO$>~`{X0R&4B92z8TL`V+adykq6Q8OZCh6|pkx{on%1xRSAPVHKAVcj< znDeZRGJpVG^`GKfu!64@v14xnFrG;EGuC^^esN|+BB<}6`^WzT-E$H8qzN%`y`M(Z`dW>yJK~B zHJD+gbkTCVPYc+VTECGgUZC}=5@@_hP~&_j4+)d*cxA8ihpVRejP*D=S|Jg;>g^sG z;(AgZu+bQX*DAexC_HX<-sj$Q(XHp87M!t<-ES8V79X8XE3owSy1pK+rehl3a?9lH zQHH-g_Sf$aCARq-6*<`;crvwWQdU33hUH|s>SGm+CL~^)DY~%tY80sXO+^VS0`Jkd zcDuua5l_aWd*Y2ql_a9L#c`l@h_AF>qY%$S=d=vTuDTQB+c;Cgr*+RyfSa`*5fL4} zMjB!xtrY{uiGE<@?GCrfPozmr61N?=4J!~@MjB*pN)20)GdHc-WH$O0d&ledp|s&( z0X~8SV2f>3IN5wTQ?axvI}cI-ptw62+&s-;s5&0xwNBA4C%^I|uj-r}315C4ZXxVB4;l-HB|eiJA-z(nP2>dV!Q|y4hLv@NC|t6IAIFQxTuH%;_|8Dv zGrQjwWInEgKkj;smmJBV+$9$CH;0a%Rs`X-;Uxm}_S-TPQl_^iSsb_cYLzjX)V$$! zRk*}fN?19UanU;qwG7Xm@mhz?G##K9Q9dl;`gvJ4!ds%3vc2}@A6K`a*9*3~wU*&1wpI&)?)~bIK{-o{Hd9O}07Xn8?{z zG$U!V=i*1*z4ELEz6IU}h^$3|Iz%G+00+kTWwO}~zAVTP%xYQ18``UB^pRiS4Dnru z^`}GD(>XH@IpqkH!!xi=gGU5bNR@8;l|=J~n1P`kO7~jU>PpHZjyG$cT8T7kP;K`)Q@QNJWs=PbfdypvazUZj;UQ+EL-!qXgSNIp??cmuOc=36s1=)8!r; zCu@AO8h@!yJ9vg~-xqwFP$gY}0z5Zqk>VyIDM6Hwz4OFZo2_&X`rk=^r;tog?dzG> z@gJ==oi!#RSpetR4ImZbL8uD-%C3ak4`zUfE}ep`(9^uLT*r(9AECY&@(4BP7eI{+ zi@v9JgUWter4%zzzzS*=UYkJtG5J2S#Pf7`*XaBHG2%@=ok=>;K?#lQcflXFa$631 zI1+aV>YMsIXjMpg?SM3@-TNS(#a{XLKzr%-HTq)3L>Te3$_fusFB&1rizS@hwL6r! zbd!!MvG|bAJ*1Yww^T|12K)?@BUF?m=vPH-EV{S*f~3EAdbFsnSd?`AGdn|nqs*@d zS=+e;L`&|qbR!4s;r&;mbRVlojh#z3XByn?KMj&1iExc9&jXitod;g*ceqj2`LJ=M z`WS4XaMkgSDJ8A65s5O3ZpP~FY4LZRVt!euD#T1sh#=zV3@2__aFjU`sZS`C+QXf4 z>!kMam;AX zK3#tR&6_r1XQ_>G-_q|R4}S!{M>t*03pCHnPVOe?LdnU|&WLLQnWiPKyt`_UB-LR_ z=BHv`1wGHK6In(lh!nyY*qHWySUdY(Ud}LR6p})2hM(z55Q=1ad2rKcgtm1rqk0Id zb(=Sj#VfBaOK$WCE*ScJOgKK4ITDE|>maS|o`Y~VO)aX%72*)dkdF}=b^|ZQE3}`N zT#6iZIT}p}y(~NwxO3@N3#SGsNR1Bm9Vveo(~;OX_BPt=YZR-beD=-ivZqJN^nxrd z#tB>y6 zjgU#XE&b3*>+tgHA|r4Fx79$T!0WUnKZM@u4P3X zB-ziE%Z|lby@(byDwDHt3s18{13J2o`T&IoxasU%`l)%gulZfn=Y5Mf3cdpLpiCdy z5gGvuWR6Uz{!N6eIR`J7W)&TMc-NCLVCdCUJBrpol)NA0Mu8Zlt+wP?xlQA-f@|^nHX!= zw77a^w0|}xyrLE&_-(Zr=pP=R0al+G&6z6UD~dT+N)d~^+bIC|BiYx;Jj<6;|wF=Dja>jEP-c= zK1?u?;4VLvSod&sbtq!8Fy#FoYa{LZy*83Js*SWkwh1q#%!)yAID8WeC#dAK^~Vl2PrD!rc41^3li%bS@zJ zat-6n_s0(=sbwq5zD`mAbC`B}`={`#X;e8$`ZoKSN0mo#Gjw*~+>}(9&q(gEPEt#~ zMsgcj52-tAEy@ZSz4t$31;I61zh(su?D=0!O%Sd0xOMh^ zM&#Pa1qExBL3aBTgYUWpN3=VMLXRc90qK3L;a0n$ED^-#pw!41DZFnx5450@?j^O~ zXhHkF(SpisdygrGz*R{1S)kyeVEtrtJ3^uSKV=1VA3c~PpWSl*VV_A~bORs4ZXptd zz~OK`Yq+_5XSMx>U=L=iyP@yT4@0(s*(|I3FUI@6o-;#Uj#(K|LYx-hUsQm9@qS}j zaQ2!nqjsVniH>QOO1$RLeL!cP0tWjvy!uf**LU?JzoD!9fhF;c0mgsi6BLicu8{R? zW*Iua5Qe({jv+7RDy%;q#*D&sw>?8XTHQM~TkqMWEAe2SLEjWOD%6SM;-dGI! zh$nja{hISvf%c@m-7-K@)Q7s!qGjw|aQJ=MN1zGyb0M!? zbY6ij?qSyFYv&d~iogVru5tXg0215K!N4un1^z4ewQk6e_)R%VDNjAi%0B1 zk*!tPaP?6X(Oo(UB5WQh%Wq^sB}m@W$Oo#MXMh#E49RHN2ChGjPf}uEfF51~zKt$q zN|p}o65BffiEQ(sPYIB6OWRR_lsSPfvlcXs6w`;%LJ8hQsC*6YEpp*8*`IPYB5R(= zK-uLbg?HF8bKwOt5a)FyAUkSO3O9-z-n^AZY@d+lHCEDqFCCMnXo0xrUGTG_S6QBK zM@u}uImX}K8@n95h06~iXTC#nX$X=rk0%5QuR@dMT6eI)AqA3Rcra@`xt$5_I<@+2~MIr2gC_@>G2B#~3_n58qLi-bG-G z*F%aRU8SpyNqv2{OTYfZIRc|wMTpW<5=c_9RC^GJLm4IWbdkd^fEyZ?kA@h_JfQ&ULbB+f8@aH-F*5QmD7&8Ay)FX<9YdyipScz*10!bdq z=ppjE#)bJ|Q|Wi7o#LZ!kP=rQVif{9$6bEn4~mC#G|cA+#-BRQrM?^AkLOY35nBah zECt@Truc_*ybH>7v6uZulc$7|iSuoUD8|JpmkX1vdNv$&hhny+4aj7yN+4rd+A0bE zdMQv$rgJ};jMc-nkK*H($UBLjR*Q-0=De20!W(2QD3^;HDH?WL10!RpfRLPR@LgJp zhjVli7%hmHne+o;r8D@3JzGbf%3TCqzrBZ-U~-KAJ)w-Ju*L7B7-oPsFIuO_Q|SSV z-`Afz^uJ$&4crV_%*?g^&JujXq_xPS{~AW$&lHeRmM$cur4^e#l$#P7Z zYahX9VB~|)YZGui|B_Q4wEF!gXZd7aMTSp63ux<1b z*lV4OznIMNeToJw;6<(LrZ1O$F%=*3u#Dzl)-{@&hJU76w;iiX{Ps(f2IpIU!yK_A zd`6zr3~!E|myri7N(q#04LX*Sy}bW?+Z%RlCcT_~avSzx+o)qJp^y`;8ToZ%e)KZ; z3pV!Qf{EKH=E{5vHui%HbIsq}?8P^k;&Zrm^6O*o@<~~?LkRz&LMd$Qtzqm#EjxG2 zXYAJ>#*F^%Zuy<~PP|FQ9E%vYg}I}K@_xH1w*IddF2a98?BVG7_F@VdO;DRfH58*2 zX!zGZwcw^CKH$2B+Yb_PSTA4r`-|Z_$&rq|>&jACeZ(by4$bFitH*Q?lL~Y%Q1s)H z5;kJ5L4i7TQQdrOnART59CBRcK4po2*=-lBVR^8-S9?@!#g8VgU*8rgx;8j&qrQOd ztFur4!Vg23IN3>=S?bhPX~~7+-*dg>+Yim`#GI7MNpEg^!=xF>M*lI4m~@rm8vH~2 zul`uB1ZUGV=v3ZbkOJziKYkhMJxa+}1ix;NBa<&m^!(O>ITl=)2DXhd%~B`~yK@S5 zv@rz}0#ky#Jmxc#F#V|5>RrKw1^Ac2azTB>Ah=QDT&hqP{s_hO3%`<KrJ(S2HmwW`l&>Qofb(o`56uW3r1v?`v zleZb;I}rFyfOiiJy^~}NMZ#jvp~px#n*`04P>?#>$N|k)@afDPR{I7~G~w6H3=_Z> zzMjJv{#~e|I;v{QPs1N>AhaJLDSTUebN+D$vpah!9J)1>9B>ZP`RwgwSQqbUZHyMe zkJlGLvY`-w;_;ZjODGH9DCYcoD<#CSW=*F1w|RX3U-)Ca1ZG+lA_#%Y-aOfe3NZe9 zn7(&j>mzn}w@UU);2RcrpS*`=VInIkozKi?iJ6nxRArUt@bB8fe*){}Vh)0?@2VnQ ziidMegc&-Kw>v1GA0%(bGN?VS|F{j0o6I$x{4cRCu79Sz(G@>lGaQ&Ba9NTdos)cu zh~E|X&*7W5>fu0UD;{KYl%Tl&`%Vj9J!?#Vj}RPkg>9 zGv|PuFY&;s%kx=c6<9Arh;{DxcP*48dttc?b8jcKd_Z-EezPc?BoIB3WlnE5Q+zNC z5s?6OZ4aP%$^{4K&+G6A#Jc#G!n4o#Aqi_H$5?Q4aaSrmmpFcq=Q0#CSjB!OpEy?v<~kD;lGUUY@im_#bt`|Zg>TA zX9qH{xsRO?(X9Gp`uhz3#~-7K*!l{+a=ZyY+59x*U8Dn&9|RB8wfKi~O++Ckmn>k^ zwi?Tzk|**t*-&(A63W`9H}BXtmq8sQ#Tzf#xiXJ`4S_`JS)AYG@lw*S^TDIBV+WTe z;l`kM*+ua6bSo>>aR0ex%kv#~XwDKMau;gRGZ#@fZWM!#|8+6vUbbbqmnhF+AujYi zfs3>}Q-Zzbb3UzHUp(tgD0}`YV>SNm8OtsbHaa~mS(rIFIvj89O>Imewx67!lC)7-xHkW&?ePWdJmr1dvs|6!}~f=Zs8p5 z_&(Kn3lqR33OsurOR@ZoXg5hL(u&$c%ik#c-Wop^bG=Y_1+t7HuKL}l@OBm~+~c%7 z_w4RPT8sB4bN|QY`Tj^9oBn-f;uPy%a1r{VnMGPn(`;#Tu6kVaavw;Hc`ei$o6e$y zG~Cg?Ete+f#+!=bjU>gCd~Xl@@d<6xZA*%k?;MW4$4!OMaVe8HFH6slZjhDS&wB80 z4-1x9e2OM8>NY_-b+rX6eyQR=hCdZ6&}G!6zFiORA?FgDSBBB@D@fA>(#Z5J|31h6 z@kcE>{Z~Cc(%}!iPcqnx9BBdtNlT38bGAO`MEBZ3abx_8oN^zceWP9Pq++nyi{jB- zCV2vFQaB66qWkm&eUCQ1(}8*;v3dEE(&z@sTi!!az5Rs)HAh_RgsPasA@e#?6VYWP ztn|7L-z0vCEeoCyq&LbFbS307=Y@*zL#JPzef%(fMy|=DFRIogbd-~v)#hU%sU~~Q zt@>@3P)#<4vHInBQB5{}AO3Q@a;YX8ccM~FHZ}rOlZ`tGzfisGUz!g5W}$l7_|cfd z>i+-I%bu(yl+h6&f__x9`~J84ta}?}Jav@f_kWT zHaF*phLD;=XGbHINJ1JK8V9GVNN7p)_mR4~Y#NB5b`xQUnpiBIZQB(iV`DihD=Ruu z&)2U|2hvCC84?$5?+^jW38IJ#YsX7-dN^l$nC64YxP&mL4 z={ViW7TH-DDt@mFxkyCt!B>z+%o^$>wbNBD)S6`w8^;r*wCJQ%7%Nf)5IBuSH>pCR+XrlNDky6d z*_Y<>%(|G&>*~JLb?BSa;?pTE+gsSAh^~Ow%W|^}m!!`tgRO)1?%Bsh75E6#nFa$4 z)F9HUvi_y0+fS1y!Hm8rY3EZHiq$QPt!_4&zynk7mFBa$%XXrx`#?`?G=5ayNTPl7 zgM}$`MP%u}*5JRbEnou(IJYu)47=%oyi}g?py6QM2jZ__(wm! zOVOG&fhs6OBcSv;6~7n4oYCWiD}o^H5@9*7EYW$iNt-15kK&h|@^@rKx4hX|em;x4 z7Xu%~#I5ixa>|uNckUt%LSnqB`us3M)GcQ0qg?u~-vQdg4dr?BnY17jo{vyD&q4uK zC4NW4%WD3~rg(%O0^CZ~(nT#mnfmr-dHMP>^mu zhU60FP3Zn@L6M3p`;Hn4sJTwg3!=S;8Ir4hcFg!y&x9Eg?d7?9FI|@UO|LLRf;H)U z+c}COci(qByk?q3XkK_YmY?YzxypcV(NY5}jiE)$&&*t;Gso(o9CQqSe!H6D!zMp4 z+N4HN3brW4=YH&nuzToH611_#6o0z$e+R_N3|P8t@sECdm$E^+m^)FXFl>nbtxH=_ z8|k)_P!;x+g)&$2>(^=pqD{KtZHwNk`OOB_d{6bLj97hokN=Ii=5Pwdu@fsRH7Gv) z{4{!WJ1@&MFxVV`-$0Z-!Zl9_Jtie7uk)oEZi+?xUxpjGIz_N)C@)|JWQb>4R?HTW zzK)HJnOj+n5Bm1>^pJ-1n{zY>9a9{$*yX6-W*s*N_*u@qfF3v2(#6dbXG*RQZ0?zI z(1P4nIR)1_5VuuY_im--_j)~HI}hK3hPD;68BI;h_>+d1>GlUw-Dp=Wn%-wRZs>Dx%1gkx#Om?kh_m*#_P z5C*FP#hdXesP~=vG>p^+J3wF=Dh7&0Rf&3)*?QXvBL~+xVwa(Pdj-XA`LW-_Ft@Yb z|HDiCC;44ra7Zh2vp^)r+|iLFJTV-qImNYf1j^v53JMCCNj`)!=FPJ|UNq-61Hsi~ zbn~kQ)V1J$W3V4=t%D$8q#IuQ*NSzL7XlSTv zY;4TasI9FvwjL)r5~E4o{K-S@LiqTVxc< zH)Wc?LfKvwqW)4_yF525VsO_Si-2ao$Zf678Rnpogh-7-5nYi@0AospJyEu0@2 z8prI644c-0nfV+9PPrxME>}rkai4gnH0D*e0mh>7qezZ=w?chD@G^!I*1ZGGTo)^=6?+rwbq! z#)!}X_hSp&6WarV#Rh!j#17cQ6_#;v8=b6WS~T%1cdoZDO=3WTX6dOjB3tlgv?&I5 z)4*b_bJ=#*HeWTJiEx{T<6tXXnkPUy_ zynDNL?aHx=Mer>v1S%tn9Hf~2xmHf@6c^f<@#MdLqHy08?j>e3kuxwGplPN~6L@Tb6F*{ejkfbFx_Y`auW;f^V{%0{7853$ zY58r%fPdf>G%x37X;vt9;E4BhM&lRHU=!v|-USFTlyBEAIR*v>=AHr+{&4M$ZT{TU*HWY>!ap(9Vt@@-C z3K(myp#xqO!rLMk#NoRSW)!6otyrj~IJ-|sWIpSp0R=ug4BOT5;2;gHF-$2yULO`} zHAUI0P3~K?Q72Rh9bY_0<^?m#V*B~5f*u~)$i0sBPKcI& z{r;zN6lC@}+7zgWdQMgT#jbeoKMWihgas5ykoL;9qyXuDJ#ipwgEnbXYaa!gtc)Fh z$xei_1o1^n@ZF|Zir*$0*5QY(=%Q!2W`yq>!MP9ZTnShz+kv#ZbA1~>+vsSIQnF#F zQ8<2ta;Z`H92)~SO4KNPPS5R!F`&YyKgI&Lb|{Z0Dt!9;-3Dn7DtwA}$9}n*sD^tU z4gl3~Qw=xbOH%V*zqBFb9rT=<_o6(dak0qvabu+By}pmdoPSXBUcWuJ2~@%YKHop5 zJNSu8SeSEczF8}(;hu+kLp9v%CCWt#oh=wM#6GnHxf+jCoj z$~430n!dR+|2oX6OtXIt$-hFc|6-ca@>40o=;ERpZmQu%luoD=VLT<}=eU4M5uV2` zq1JZ%-o2sLcKrU_UPG8xp z{{;+CVUzzF9dee43Y+{K+5Xb}QehJ+Y(mRV)iV08%|eArerY;>Vn0)hasDf3hOIAZ zG0y*s#W+OLhtz-#PUqJwcN)*JSTQ`d_0AUEu^FAD6)!mnSLZ1z^{oWyCsCTgm7DVE&!k%k#KVb574?;63 zY=+i%O(~xJo~0Cz=A!ycqqXBdr{_V32JST2y&`w>JoVDPaeaT%OEX`ON|gGob?Ta@ zI$hZJTNYCBksBgG0afv!1z6@ZPc6VJXwTAr(gLKA?9QFnjYVUaG)`wHAB86F)^(SKJ0)NW0ik3y|e zE~+{6bN!hV_MSvS+1q)lT#~a_KdD?w2x1bhn`i=!<|$40{gwqvA;87og#cI1QwT5( zD~P)ClMo>OVjQ~r^SOOd3oAdfb?B$it8hO0UF7nE5Fh?xnYql-mcd^t)15}&Q@}$t z+2E{DP4;ikBWJ3~o^ywN18Arw`}fO;YO?3@_HfV))nxy6uTf3*@An$jWdC*%{W7AO zY^uqo38Z4#a~l(9YWnfFAvQJr_`?aFJJ_bCA948SH$a`@h;pW;AAh^osOiVKcNlpW zQcd=M02$;*RFh3L*$cI(jFJB^CRE1A++Hy`YNC?-e&^C414SkI{nFdRN8bO(BtPfs zSDU|U0esukRFC_2%aiJH|K3%idfeak)0{37)#LvCGNO9ib1om;NkBE(RFnPlW$jds z_7DGw>T&;We^5PcYFQ0jeH2*n|F!qsQB7uDzX3s198p0~5pZmX^g)_59mh7JsHk)j zK|!Sry%W$;l&T^SrCDJR0qH%73Pd{60wSP9YG?rh1d?!1a7Lf!d*vhV`rhxZyY7mA zVU*{bv&(P)_CEXBImdaeW-;RS&rmqdYc;U@2M7;gaTQLF_L8>|oF47PToF46^?T7=}OUsA@*-QHx=e3$8BR>bSmo_5~WG@Xz9LQc;MjXgq+SfRc z&4KKH`Mzt;yb(x!gY#MqL>P;JF6XtHC3}82uhlGVMx57bzLmcg|AF%+^a^R90=<|MZ2(foY##FMomUhkLrCED&CZ`*Ll z>QCQirYl@lLT>zF<3sleu(9R+)(ayIUDEDlEk4nbcS#olU!AmchS?QhBDl1rtr%LE zLuyr5mj_F0VdF!?p_^TVtgcu)voIU;sTk}zpZ;1H)@dQ^ul~Va{N$p){C%eix?AUt za4WoBMcxPP(dyrIhwCgNanE){W9q@Uz;9Nt_z&NKrVY9!h5ZWyO*iNxtoG{{akHT{ zyz+w9Ot(*OgQ})jYGFr%@`#DvQG6=YGQPLSzz_Vbv)BZBw5_jpFFXm)gAx`c5TKh~ z>_IDh{?oHs#h^!n&1$VZ2tULR_g8PUptZP^FSgL5!N!N01uU+tZ%eQ-KGgkF3v`X| zrURFj_kxJpCMIN|M_UV<)oRJkgLt$T^naNT_8hf63rfTAqQY`x0@-o3)n6y|zIs!* z25NPMD=#88_$ODcz`Kx7_5BP##1HrPt=#RT0^QQ;wF}c@%Y^(l)is!in`}U}dLO+M~0U9i3gHZLc(Yh^`&(?Rs#V?3x zite-cVBDFF(9QnPWr6+zzD|Ap0C&u=uS&Dx!aN=B{R}D0R2iYU!_5@BEX(| z(|%smi(j}EI`%brF188iM!&u06dMXP$Yo#087uOlmha7xW=CtLUwuv4Ngg`S79aC< zM@()72j-fO|JGn!?4fTM#rh$5;Yq7>5mp(FKI}~)mb?R6!Ty6&h>1|FfKMUTWJhap zyqV}7h{l57YoXt<766-NzJVRBEuHnC`Rq@?#P{Rwe(9e)ao9^EU=mvAqd^PHLl`p z;M(_>60D(9l<|nKv!ivnFkB~wSN&KjP@v`FCNB7zbLhul=z+%)zwQW!sE)xc%lo$m z$2-929sbF}leh)_jcm6_KsO8ZNZ3xt7C7W#4XB9x@&AL7&#us;acDNozBn`+?hi0a z{Q6HEnhmoU7zX|gdK{Yl9po3oH4e@Gk>$YU_N`LIq1lW39EWBvE}Osc=-cH2hh{J8 zbR3!urG-Ca0srsOY&R{z{C{QveE;GP4&`1C>HzS`-{Mw$~Fw8VFKe+wilPp-%$1K z6$K8>hM5io$vHHeL$h_(`~L^O?3Y8c7pIaOn!UJez9JNdW<$Vv5oqGjY!1!lG?4ta zNWy6#`ESLuP&4N=ko=%!0M3&+ecDUrSX()L+Dp3{52sIiX(4g?v=`xf-`NhQPy2_r zy)e0P`m~pJHBO&4%w&EnFg&MEd#QFE4$c0t=|EW%hh}qV_6`K+bx3$-1@#afPM`Kt zK)avQr@eGtl+&mEJyTeWCv*C=mvlAG>yR*T{xNQI`m~q!HBO)Qk8KBn)qB zm!#{QsUvIvB&RnU;^vD~TR6ShO9CX29H(hysUi!fX=G_%<1~#dP1rcS*-PRPr#E|P zSKGRu)0@2{L*n#iFYRmp{|@&Xlh`oRmw;w^jSoqz#M2`QIMpYj$4J>CBcQSIOw z)wfjqXVFW#0WVW_XgqK3;`~uWufsm(5tyUmzK#t%%8T+#&C!HSIa?&(`J}UBZ2nJk zX7Tx{a2^!%EJYQ@V(Eno<8hvB@TXCQC-$>bRZ8S8dK|5j9>Mw|K%H}R_#h;l+`<^S z%V2{gWtw-E^q;N!A3er9{E75Si)20T<{`Ho&^_p`Uzh=RZiD}WrjC(cVY2w~fyYz> zx>n)nni{OBi|B|c9q8lM&L}SoC_1zUF=3P1bKu91fEOKq;`LLak2{yJG`v?PcRO^t z5bEC7F-0#B)z3!UL|{w(I8F!X@cL=c$0vps3`T0$0ropHu3xt&jhG=*r_~XE*i!(iaGi{(Vzu=T^I#eR~s;{HV_?g7cIK&mFDEDjV!NH>EX)OVN-a)MV zdH+1R_~tJfQHi={^WSvWiLVsQ3_N|)`Ki&oZt*5^{fkZsLKY@PR) z7#zJnP5uemS9k-mw#x&1XQ*IkEzhlN_qrez!)272xpfk(xg@U`a{a4{*OO&}4 z$Rn~>53-}cWvgPtKON6_-aQTcbJeM=ygvpM{AT{x zy87d^GeKQI@KPyiu<2O==S044^7#gTBWfOo7lv4iXtm|&r{q;7_vMpjSWcQ5WVv8v zxdctqe`W#v<1>b?0o}_0-WeHlVa}n0jo3i|6i)zkt*D_g9ILN zD_BeMq7M5VH(F$iurS1WqPRyg(wM@sWY+}$I+fKXu{ zDY=vx##1Lm@8m#Z26~=p@$OxEV`F2aa&K?%p5fD*E!*T*r#|DgvbLUZwX(80Y*c3o zUwQlAE2FqD%3e>6qS(R5)2Qvsk(J(lU2~n$NFv#Mx{#jJI8aKb7bA2@9p`uaBYKv5 z1w7{ELA`L{RyZdB9}^1oz3+<#I}rNR zde{iNMa#fMnC{Bv_{PZ8CBsKSn)d|?WF zb(Lj!0O{E@JQR1IhQAZG&VbmjicqT5PD)CWPKt|(Ny$EPCFBxLA^V;%CN8dq_~5~V zO_#KsVHk=E$w{_+1^@cco}>mNw_ht=sO!XyQf9 zp8n+~)Ffj}fmeB5XWKAJcn2Tf=~P-S;iz5vJ~zd_PuTy8zP=>XX#&n|0H*82w&@n~ zyYL6PB($MNX=+Cr?Pt}&AtPcp!`-FOAE6rwhG-8yhR-sEY5vgDS7_CND=Lu>Vs zw)DiU_QGD^R=6H->E%^eT!#7IQLRkfjx6p2-xGVE7^t8+EtUQu7wO{3zNe$t#HnBKj9~f%p*vX zlP=FSRaFhHgg0!g^1E<(r>ug8MohXA_*3cC3stZGzl*l(p8lyiOEsx+4#{kJ%aOoxiKG2c!i4i8wI-uD#Kv?(-tl+%%0n9`sb@i9tg4-@kn8;is|I^#wLs+Gg%rh{gdI3qL>Y!N-vYLIy3#HY@Q>H?pDUdd16%R;os9 z!f5L%?(54B-BjE}-EzGenUX;zpX`(3R#*sF_FS04dn#~@4q{>SX?7nz#C`qGLpO6a zQnxT_N8L>e!w!^3r59;CU=X^#q2seB2=R!gzzhHx{MYu+rGI!zq4W?l`ILXs40;=>WuSl_wI_K@vI!p?qpx>u9SN(fGk z{t#zjNGsb%5$u=zqFAZCa1`&*fo3EQ>sOu^y3Rk@<|^FdAF@J(5u1!9pk_zCaJONq z%@$XNU+?th#uS`SDkEfAIdKL4qf6rnTElnd)uSKkGPF`*JLQ2cgq;S|{LHetaJEmf zu7AUqjnsWd%y0>`lJdzx`Lv7#M@AU%9Mvu#XDrC%9uGyr0@V3)02nK!*fqT60e)|` zJT>pz-PdnzpRQOk8%!oE+t)Jz$0?~jJ(S}?<-z>=MjER0+*hoS(aUbg5CtLQRha@& zqf&kLLA#A^I@9GuN%`vbE9FUo7>0F?CMg<0uJ=S4P2H)=b7$mZhyz7I#V zj-=C`P9@p&=N`_(nmg;GO%PUIUi)0rE29zBFBFXbgbGTO6+pb^fnBkaCj^A;7Mwr{qhzIkqdR!sYdt5}Q;=#DM={pvJtkbjx+2>QPB#w#mjGu;78jnDHwoxG=fOm3;$lGKj_#M~>+0zdqqh{wB9!*V-G&iuO;+^qX4{F+26&ya%t^Csb@i?x zw{)e-n;Dp(^-Ge^=UyQ@q=;}~L>-D1k-N0GtS(&mnFm$*A`BYI_oFVd7|LVz?ePP* z=u`8$SAZfDTe{B6r#(%@C3l_`wTj!DWSH_d7M@{QW^s2hqu7gESLgR~Xu$*(v5>R8 zVt>V(D~%@$TP_fXl+#mjspdmj3oDw0y3Ve|yJ)y)1lp&AZ`W{{gr&K`EO2+oW`C8# zKbh?{n^v%ydf3Q1*J#QWU0jYuoF73o^tjDlUKA^<25FyK**mb>c0pqZvU72ZB3Z^L z@b4I7>&7Xsn`Y_6;#_8~SH^rI)6eEgXkvyPH8kHYZKcCR)QK$?07mjBE6` zFxi2*lKA^IF;m7P4jQ1&5OEqFa#)19)0W+k^K{i}(cHg~qYC87uV*SwNMw4YcFOgt zHj{I_iV_M===mEN8hVVcRIsxVwwa#TgJ=xDrwDWMFAEe=hTTYg7Ena(@xN(8@Mn;>{O1rT~g!iaY59$#aoFJHp;83j&m#6{W1t!_E*-j zF>Djz-$12xLr0ne#?`Cl3Rxnjb1yEzxDj*lOnP3BeYTF@@ZVlg_Z%8q}24(_^HMwgY@S1GS?<@$%nVG=>~{Izgi22 z>&2_^tDjtwfqI=vGRy1A*^aKKQOduH3>5O2B@t(GnFj``8B{k%+#uC_IFX!McV%;< zkpF{(gm4gMEu{O3RZ_icADuaXNc{6N>?Xv7#qPZN*an$h3YYVr4A0&)N@|bI#U2g`ccQ6(R*steG%=d9L~g zCcwaW~v& z2Xg9My4N}8hvAh9C%k2+nue)w_~l=^NN9Ow|L3b3qQ@SIf7xg?`u62};N0<3%?qy0 zs7|Rf3UxDnx}x}*|MA(A!;`*q!+Cwg@dzDS1kL8fb4h&DL1{a0J*qj9n!|(gx(&}w zcCqSzooCs#(CsUm-ip5+@~u~9*(f>BT*3g@hBUE~K*hd!qM7JpDuJBba3FfyOlEfW zeLmAO?{+qi6i?Lp28qI((Y zt1Dt90F!%>#dc`sIluk#-89#F*AL}+&F!_PCAv~NvQK)Rq^X6TK=v5Z@;eQ(^=F>1 zzTb>;v+h5bx0vRoR?mEDuVhdDsOSPi?Kh(FZ%g zHwdzIi=+~?U#m&68p~()bir^3sftv$!d$P^k8%=3f*V=7JnF6dsArvbcZ-QbXjxfV zQ^^2p)ec!#X!nQhdDg0N|IVtdUstuG|3#gpduf=N6tuXR0<(zj+u)nrGT^dJi`GMu znD?L$rZcZ@(em2s>QD)w@`R^}nGi(TF{fFPz<}*YuZHs9JXWhcx70v!aW;RvaT&nV6-KanRJdvSv)u~ zw+E4R#UYg+a-WaNVqNQv{>8p&4+exCnAWPMC#s*w$&O|r)Aj74P}%9oaQ>vT$3I7( zOp4H9^h~4Yr%6D?vW2R{DTwOCk{mh6wSGX&LY43-`?h>}mFw!v=?lH8HCJ9d_nkD6 z50{n@A)ZN#43DWj4XCGF?{jANfILWVDP$az>TODOsOlgPXE(B#5~`8!1n3w=a@ac{|#$0>8J@{19YQD_-ib3|>p! zYx1)0$&=-!rGJ7t?O`@<5ntK!Rvx%>K~=qfvmGgB@I;P90?Y0OC7yNI*%qYxn8t2z zZg5|P2X|1V6%mpoRrG`^>8S+caz>4_c`%~-W8O&c^YE^9mLg{BBUBk@Lrx6eiqsFZ z7zzk4t;`L!?0KPDo?8(|iE9immyn?ASadbH(3={&Hbw|W^qF?4OR5X-a$zR?hlHTw zG5m=InBBJpCC3F?^!4>a!Qn2m)d4{T4(0Zeie0Xb%*(LzwWD?yKAerYdd0`2J^R zww#Isqdw)Hb1vQ zpMHA*#5uPrTmwe4L7pKZ!^&0LbL|whnI!_mgqc#w7t7!`ZV;+FI0MPAV*VDED2HlK*@R>QJthsP448vAZKW5R5W@|ckR5^`Kggm z3X&eJ=vebphSPjPY16X2vdS;K88aW}ce;(v2h5m_@3+Ix~bQM6W6AJ$Ri0T5vBVk)^S5#DBFc^{rOvgPtC?xH3m(h||rk%LuLRkTKA16p%xhC-rD<>9pK zag3?+we*z=e4Rr4Mwb&OYP>CNr{gjC-J8}02WR}Ey+Qg2PFS%(vV2-o$-?vJUFC`0 z65(hqx06Fb)z(-&Q+3Y;;I%MSA)G@w?khw;PBXXs4wo%$`9cddya3 zSQ5I$Mm>(yf$u@=^4VG|6MwrEtHod7VzG0sBxYlkg{-CYIzf%BV8hx$BU%2!mlp}` zSs$FH3NgGE<%ACj^m|iEQK|aOJyXc0ETxN8@_q9G?b*{$&^|u&BIm|ilaaN)BVN{X znVoL~1^TvIgT|!~)z!N1`(X7so|e1794Bgya$$u2JoYnY)OWYNc*^gv6G6T4`?dC1 z(<-6Qfv4RRt2du;o=t6@HjX#YmMf36u_IgoXwhj;K2Du1$<7uUSg9a+GWOPVai10? zBi#3;8bduDeCFWsR@B1YUT#;p{<|Hb_X5wCTkg#Kx$3<~4a#Wm;GG)Pr~2a*~$BFj}kc>l{k|(?Cl?*l@<^n-U8Cpa9|5scekW@wlOD z`zWzCX%z<*!nLLhP5o$>GPVfPXa@WE+w#j=^BmCPQJzB?M=XhH9W?c@E$W*MkQ1?* z`A*|sZhL(B^xES!zxkaUjSTnEPR*?oaif~+yr+h0Y8glG1y{)xX<}(L4y8MzwPo80 zSdW>{f!%M0Tz9s=E&WZnmcoOXRG~n7F9N9YTM>;6@#jhSXGyQ0rB5QSjqSyZn0rBy z;JZ`93`p3z(Wjz}2(S2L8`-Qc(Mq*MDi8(h~hfGS`H6d9B=#YKNau{@{ z18+l5vx>av&APL962yH6*@(>hQ4D~QAWON5p)sllR1!ZLXrG)*&m-p~GVLt~NiiP= z+$}&AvfBFbU7>Bqa0ZiO*J-N>&l9^CX7n*-^oA~aEs^x3qOS}$TY-*C)esiYo*B;XEl@2LMADub z8mfs|=OV>|s{|eAk&L;S_X)E#YAp}K2Ke0xU34mvz!1>hEbmRNaqOPCt>!p%)Mr3` z-nn=fSuC3wn6J6XUmdvTP~A1T;5Moc`R?^LG=1u<=5Rw*ccv}6O`ci0Oh6mMhuS46 z+1;9939f}b+&4gt?A01@)!6d+M8-}i>wy-pA;uRFzynxjz%J|S!1(qibs1;i#%IPI z-y@5o=01cqwkBeoQtfnKB#j+k=dbQZ_b8t07!A`HEmm?>_Ir+~7VR9niFx=i=sKT7 z7-LSpG6A3II~V3brx3EHTr_7}NtEn?4oU$ZffScOBj*qB>8$PY`0~0n*GAEA;AVKK za-)369F`I4(UO%Gb`U+`V0o4HUPe&qu5UOY8aqbypw!VF-naQVn!d8O_MrqLgLI0A z1xUO^q=bHiKBYO`PdUxER+-`es8)CV}{gNoB}qoqo? z(L;`9dL8#hmBAGPXe*;NUOv-G5JYWuNZ$rCzyuJhXNx4=*y-|C!0gxhqS!ig^^a#= z1tSBv_$Wmq23oT*>tSWy;TK4Un=gL%n#w_Sj+ zGg?!YAFnAqC;w3}d`rSDWC25`^b!%Pli2NHnn5a{%vv*IJU-{h2hEMlA2#*w_=(c2 z$NW9ktG`iEJ4e;cRy4Q>=d;^yvQJ02Xi8^0KYl0(N3X(#bkT;pZb##~dnkHHYUNBQ za*pc3oJf!uox}5W2k?pC8g9?)B|m3HU|Y@-zc&jfl8g-WFV1MT&y`Jh_Wx}iK16XhiiN77S8%qF;nV+ z9gd8=C7s}SNprIPV1^AbtyM=$tjlNS6#XqJA+#f+h{Tsb(<5CgDYEo))E4&{3-B0m zB@%q+$5bhJgG@yA%*Bv0r`UmzvgwlUJ_|=Fi}u{)qjPhOpdye~{YG{mSqVM&T)r&Q zzs-Sl}ma?3{rR6Xr$ zu91DitE5vd*C;Jdj7TI~oBCFRUSb36c%EOj#t(GFEQ_W~opNi(={_!*TWe-K z+^|F5G8(rL)e(6$Tu_y_xO^RebSq(RG@EAhpX&*ei43JT~Iic-2~n42Xespj+IJ@&!r!%k;Smsy}9Z@CbjM|NgR{uGeX+ zhBVlO=1w$&!+3T$A!+%VyTqaazRrmeRdkvISK_y*{jn82{`*6u0A5B;?vjn01z5X z_IGxUW@YE!A{nc+`<4gQN$*u9ym|BM7Imi`Y5CnjM}Ll_OY=8}r)%o-)v3N^(UdgZ>Wk3(T@65*D+mi9OST!a}R9^8;KXRU* zbQ*Sc(9qO0WWY9#RpbLNMs(j4wZFwD?y)tkp!Z?^D0Z&9;kbNF9b?b{w@;uuBs@H! z<6r_B+*qujs z<7SWmJNULDs>8%I#wD|!ja4}b`)sO4- z$|mBci)TLeX^Zd)h*yUer-lcV5*9~*O{y@K@AfIdWfVTJHtw0UBEyTT9nT@cK8?|5k zi(-GIz~ASKnleZyw)fcVp3VVKXe&xg)z(Gy;scgt0IZ^Wm1llB9)+%mA6rimLC#vy z=jy5n6Y*FrCY78ZUNk*aD?b3zf118ULn}xD+a^n+ED{EkLuJeRBCvBu-WxOpsV8^r z#cnh}gR6zYTd=0S7I0%$y{|+u7s~t>Q&D{$Xz;C{em1&hi;Ml&a2J;g!d(^d)QF8n zT6&vGnu#xXU8={|+Tek5-EuQPP`Bv#X`W2b7K;!hW!Ox|x0ZOjkDMBk;=NEAfN_bv zCXR8&5x4ae8%D^&{u@ za@A%~_z9)xKRN@&+=j%(u%+;bg5m;qLY$ zq=zYTx5;Tma@esO@}=*e9wF_N_dF&Z_8>k!3|tp!$~aTXL)8^i0K~(9=sxhenbQDxbM!rVy&SL zsM?bI%v)D3CUD3}@qcjlpa_qoS1)Qa*oRyg7SjJ5m88QM@I>{zcIc9jnA1aoQ15M} zIaNyW_#7!nX^`+e<}*28yd7LW84&ukrwa^0eOXMytu#-gk%5vgN~E$?t08_FepXOx8#*;bW&=Eq<$$HUt9h9Iv;6#$W%(#8BoDedHS2W zvW5mH@mo?R!i2W#mooip+dzZ!_%b8ws7Vk)Z8|1p{!E8cDHGJJ?a7crG^@A7r`p;aNnY|=|q_+Ocd zBkAaQoSNI@AHo)G5=8UqVvn)*uApdacO+%n9W5o$G}Kw5!Cx{I)`y(;bsQ~0*8TcR zJE?wqpoQlpbx^+vEAgH#&#;v2zSI`$hvPxbM*b28jbVDA+pAjNXIX4K^i!w}K&%>d zF~I4SWqsN5xONpRxXwC0mqH{Dk1O8?VU=u?8%jQptU>5{&JW~+p0)}>0%;6nt5ZW2 za&w9DVR0JnErC75IL7Sfp=8DO@uZ?>o&(3^A|gm_f+pqTpqjt$LDzKr$S;bD!h$4H zMw3x(Uy>s~zx4~7^oup4+LWC?6`_b8n&k0eYl3xn%CQbb(EKg}`k2QJ(6CGkKMUG2 zjF8iB?H56B*in~@utHdz)<3HIfMlsI{qaYln<+BO&NOegOu1!3c$FJg#jhKwy`FGV4pfq5)FN)2OUxXrvJk#Tv-jIsP9S8Ss{Z|a zowGh6U-&Crq8eK>)O=nF>QEbe73VYz ztVx-Qpc!hI0w@2nfc#@e!#mhO@fDN8;A~#uX<-|`pOhca~&Mwb*Fs&beI^ca9g< z3fa6m0&?? zr%gdRAh1^L`S#SDHTb4{&-cg^BI~ffq@hP#9Y?Ppr!ePdJc`E#;~b|| zPxk29K6tlY-rGH#FqKSE^Kp^FP7Tx4#vTTDr(>PAxs7hDix+OZZD-W=rrXKX?>#tX z=>w1Q=k481Z=8g$8HGg-Ny#5KTH9Ng;#R8jQAZ+N!YD|8qRO$)!JAu`77u$l7GEd= z>~uQs-EwFt0fMM7JN06*O0Apmjo&SGKg&{8jlO{l!-p5uAbw`12Rk#5dO=U+@^82qsZk za-^ml-KAXA9g(LEa{Nk%y#%QC3`bd!gt4X#)*HEqf9{tDIP;X)>NWq5P6y}#cs^QR^HpIKj`K;Z3adm>fGp&+5w85sr@9u0^|a)k4N?cuV+GqestYHcNy9 z9Fop(sQXPErSA7aP$M_o+U8=oR|R%graGzZ<4NnCQ%Hq%1ij~yuU~%gZO;qs8BUl9 zD4~QQvD-5F-j=q0ej7N^$?5>92PJFfpa87WV~Av(kL=g_6FZUe(?X=o;#(9)b&y<` z*&Nq>aWb!diAP7z1(Af#RE*2?`Sg5_eECpIH<6lRXYUCbLX6%jLKkdd!TCO{dM@;( z1?Yc(O1wULzk2I?;-3wV4)o=QvU*G#l3Dpmc1dOHc>XxxBTh&hp-%&$KV7JJ{0J;P0nX zk~M|>J@-)KU~f?^1F*2#{}Nj-r56gZP`%^RKL&IKy}+|>e&<=-3RzhNb3m1CT`&=@ zcqs@H0avH(w%6G>5$f_nNIbN7NEGp3=P!jDh4*rIthD`ts7}r6EF96aV{5JkogcXW z^;q9}&%bLEd0r);=|F^dI*moi?Eoc@=T`W=x!LsJ9 z(R=%gzmlI1CMD+f(c!`5-9*3($Shv4AcRh5b12ZglH*meK=g(>_>c;-v!$Rm1qgb&HZ_a*rD=KR?VV6#&0I0Df1lja-;+ zE%@yc`3yLkS*LIel*E5u10n=~UmN$c7DRnezi{8&xxKcLRUe^}sZK>crbEw7Ss6t; z$SBMZhe5hk=Lt)<3WZuP13S8XSs#jn5HU3*c+m{VEFdHCHK*Ic34Cpaw+dW;a4H10n6982v zljTLWON$)83zQEvmY2Nzh7im_fDk@E^B9f0Y`gx78;I3wXTJW z^M|JgZ|MX3@z<|g`E>GOms=XEMwyCarJGvciRB_*1nNRXCKhZCz5oui?4*_?s0;bE z7d!;L1lfKp^qGdFhE<@J-P`+1bR-76G5fDh`@gVUn7CG9!+;A*hWp?$3}nf0EU^{V zwf$pU^~djL$#B15)@$&V;#YTIuqt1)&8&hrRk^*~HN~L~Q4M04K|>jO$Wo%J1H1xQ z$^0)Z{c!+dUq*;t5M{?^4=zBG+%Mn2{9l-J)K7RHssy&ssjM;mmc~f_c6SjVRt6jk z8LTxEye~+yv*z2CEEr7tmT3JeTL)_vQ_(X8k?84K_cDojio}s$*Z$vFb*LlHvZv9V z(KjG=t_Ox|@KnAIJ0S9nyAP-T*GdL3*W6KY z6VLZQ>8!=kgK_uxP@S_ac~J~8XzRT{e&0GkG$mEvs4QYWF!;O4N*b1%UHqq}myKgp z!I1~Qb1zvj|4mgqNanafIoi7l9UX{Te^VZIBEtmkypK**vmY^LP-YKI&?K4qiIk!tRy3JZfFk#8h?mSKsYg{ zSz%yuc5!s>%H+bBd6yfUKZCH^X<^~C$FDE1OMJfDZr;+i={G%E4G9Aka?ELzy}iAX zd6W%1QK*%BfiFgXr%gZdw4vH~MAkhW?5^YZi}MneBud>pO`ecC>S3U(t83d&Xusce z6mE@1z#3Jm;#|a_s`#-C0#YS`hE{t~|9gB%(;8@#2aOb@jC*2M;nyp0X@!GElq?6I z;Ij~LcWUV7S=Hw5CCk)(jH$St z>_G`etC>#>##l~|Xn|{|$sK34n!wL2^@jS>lo8 zq=Er&o8>4s>u}$Sd-9fT^OtyNHevgsHe@Be4!M-B-=0gTLQVzEICPHHbt|VAD7p=Q zh|^iOi~2nMPgQO0_+^PCP%}~x;4Z!`UpZ1Diz8j> z@Jh9_Uxj^!o%D|YwZjG0NH!Y{3iq3QS|(iU*>P6SUwy7AT81w|i+`8a8Y@lQN162z zmn_d9naoP2VFkCmM&9Txa{M&iqjMrHoRw*U`hKOyhsJo}x#`jHV7Wpyfj7^Hpam-{ z#Yc5V#O6ascLgMk>0XtbnKb+J%9+&00Znz)=3vS|{zj86NdaY>r9AYjYee2Lcek9d z>(dcEvqzKWJ-=bTU5e@6jYcz>Qp`0cMsH7=(S7fRF&N%cT`%5jV-%gCJG{f`Fd4GU zyogSb0qGLGAbB113~f8Z%$V*w*a!ZyVcty$tv5rfsza9Hejd=eiw(xfH)JH>==5{N z@(tcU`))u7&d?g`63V*7%IabVO3wJuSbz0nPENQ}CjP9G&_)aCXb8=poS}c7I6_hS zjpA%YnLc!NZsD)kG1}X{^vSj-GpeP1dI>tgXpNw{*s{6}$-@&#bqU(&S-KHjbAa`8 zS>2j4oZ#0_R-g8%-Oa=vwM)?PWy*Alus(gDZ6Gv%bB11^tbgSMj?=$q6 zGd_py=BAT8(v=yEh^bRLXwMFd;k|OH2`#(*n6gaY literal 0 HcmV?d00001 diff --git a/docs/images/AsyncapiComponent.png b/docs/images/AsyncapiComponent.png new file mode 100644 index 0000000000000000000000000000000000000000..ae5f31e06e59524c0cd70b848d601692cb107af7 GIT binary patch literal 236445 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

(JBnK>IL^W4gNoy z{^yYY)>Q3(nzAsnv;KS2f7|r`ZmR5HY%gSE1soK@`#%HrXXAh0_-8|IhWm5>w`=i_ z3;oAh;7aqNaWnjD)OgVZlMsi1fqZ2qEUN^31JmsOg>VCWy#2>Fung~!r1N~k9t7eC zi3B@Zy?b==PFJF*;eg?s#l6e1zAN)d34+_-4RgjUjg5hktk0*OoMd9J$@6F82 zgkBIB@`Kan# zmX=yV_&Ce|>970a%$jiyZmyTBGCVGKCD-tRKjZ)BXAAQAO13!DXr*Zektz?5jAT!@ zV|xBybO(nR=*_^xBi+^*?mw{p3Gu%e2#^ml<)WmdBpvyAM$3)Xi>Lp^gz?sGj*5wq z*HBP^NBu9l0l}jyG)E;Ss!WrJwI~0_Q|x{a<=|o1AjN|Y`>q?Skd-1edXcW}3`XO) zmLM5(I(b5{xMi>o_Jo(N-(22V(vi?xDRt_L89YgWEoQ2IEgF%jnO}In!#b-~uww?* z4Kz+7t5p!laz&E(jNNI5qq=RV0*sU|?bVCgqe8Q;B_uP9)5eFX8UrA*8+13JrxA&L zSGQElhFK5Zf?m=-42{vRX;cdjFm5LegCq9l>fE3vPf?$rAGBf`FSmc!Ic~$#ePd@= zqH{A4-PPY8+5Vj%U|>BjYAz~w0Ag=%pDrFop=|ASxYTwu=d|GB5%g{eb#tO9N!1kj zFJ=Wi(iSU-!t25&6xOF2ded4J`jnu6xA_B^{1DR{`4H++QIBtOYHvl5zJx|4(coWP z3_~`shF6MzW6!uv)W_%+Ta~Pkdy#W)n@9@Q%f4(Ak%UMEo}ZkL`eG?4&?32rn7bo| zM!p_S?_u=YX4NtXJ;hMU%bG47B|q{wlDe=PnJ`}u!Jc`i^2X4B9L%gBfvYPoA96(V z1iAsK-ZXk|B)^VpZ z^mnUo7kQM{8>X#>bsjs{l@PJjtR&APjNRJp!id*GU!7rJ!N)ge3jrAHwj<3x2*wAC zErrxgx0iYDSG!fIUYQ|VJT5%w1ng3mCpovG>LZyAq*PQhV;xU2wzS@cWM_ZCXIZni znekf1-v!$(H4yo*6Z74IiwaE>UDni%Rj~(E)XAxGBH}$S%_8Uu%Nyi8cww*!-Jaf< zGNX}9>Cm`13wXU+=(ah0brA363$u|-XvVg0sou>cjM=mwlY-x}%|9ablO;9|PT#59 z$p$^CXdvSiZCyccuT;%m?O|q-war{@g;dPZk6-P#HE@E)9i7|{-*V{U$^Gzpj_!wk zM((E}P10sE%dqS6M#yZ4OfmKshf10p!my!z7*U$}!Nm#c7(C3!SVyJMa=aI)}Jp)>SzzVf(#1SFMsDiEJsqUw3?w%)%B3JEvtu($E{AAk0h66 zZ#1KGBtVA6hf{=5RIPqwV1R2jGvgZUwv&Uzh+Nb{LqqEipJ&H;CV1WUCw;0)4vnGL z2KRizG8^t7;%_8^th@!6N7NNr;lTS z)@r5_eFNKlFTuXM%l>rA6y+r4<6pREm1G%sJ!U><&EW-?R`e6WlVQfPR# z95yc8@`w}9NXAr_r&0(Zm|65rkr>%>vRnXLhJfx7Ws*DtUsS%ajl|mUM7l+kaKv}f zVA=0|fs&Xa!9$-{qg{C36N1uaPR=DB2N>~CPpJr(yVqT2OHfyNcFSfk733f&+mekp!pgXBOG*62J5l40IWvbIHK&Fy#$7DKrJ4kO zf!|777+jrQrNG+()K0ux0y$o;3ISt-qe7pbMLd((+M=`fykoM5OkDOU8J_kbJYXIU z@bCtw=uV=>%gV}n#D8TI5b|8@uncF*r`h*7o_%dn00rKvYXi5J{qbW6}GRNdg zjy;X3TBt?Msuv9O!pflyS5-noBi7VmLfb3q_U6hB%2Q_2_p)X+QnR75KY>eJQ1GKF zW}?|lWrCLDR7Oi*#CVeDB|dKYsdDp?=gnpJVvA6EaWOyd%}JT}V)S!5jZPd{sfg^i zFc(!+MQiIqP8sdm9E%D1qpBuCt02RnR1s#w_9s=H;kZcfJjcCd%ogLcMGKuFlwBJ` zX$@eO2R$w-i5`+UE-0*OM^)Tq&CZN~kd7DTlZZh*R6-7x^otpRdkK#7!yuCntCCWN z^1hg}{K<7<5Yc7iARkg*fBn*L8|NJEn>uHp@6T{ua;rVk;S^}fdFmVK-T?mr`3!XG zp}5i35dm_FGJmgluvUkW*N|c0!2lj^cY8s}@OASx8Q5%}QB=`0Vl_u{B?c*2!Y)q1 zFGwXuceGl<2*2?-ux~;H4f`t;Z%y<3n^WVOz)$VQnxNtr!4Q^+V)z$B&iuFI` zYt<-J+APrf`S}g!sTTbx<+q%#S069XEE<<(pV=Ku`2^XURR=rnye%my!3}C*+nX#A zdQPiGGE-?4mY+`>5tG^g*`M#rFG6tnnAHuh2l@J)Tr#rr61JTo8AYEOoCDn+Z^?_w zW6-^=%hxat=G5>QA1pNvee&uZzea_*a-ogY%YRvK>3G|phxRQa$sv7AX4LJT&i|E~dNF85?T3w820tz@N_Z_H!RU*_ zsTXA{b3QbPz%nkKP>PDNDxWw%oQNCHnZ@|XQojMJB(Sb#B9UA7r)lpl)^DAqR*vMm zKKR6aI=QTq6hz3Cy&UuG>Gf&S-L)9+<%VIA?A7V+D&PSQw_HW<;whz~H!3!tFa`6R zX8*M|%jYkE*HcJzQ+P=i%TV&DPdWK3+MwLbsK6_eBRm~eUn|(zkUT-|Cv|~=yf4(> z()cq{2k>pZ%j;=RAZNFIDr)I>Ho3n{y%_8seYcXpo0ANdyis&9?*&sFhz!KMp5kV6 z_3J8JvY9Ycyp!w?devoa|BY;iLxv#-cJec{V|6{AI3wqhB&S?hWNl;d)lE|O^^!x2 zu(@|;;i*b4vc70GayE9;xnaO)^Qa!_Xwy#b6HZ3!Z(6mobAd(UD4oa;D0UwnrNzSz z;wVlB&x0TtlzQ%qm8SYj&nxtBO`Exxsh^t3Ce{rwcJ&6=iV0TzpF9+jZ97xCZdTT7 zgF=`gG)46aZ%9eC!&JADBi0k$WS-M&tyDxLm`#`GXnEb7+pBYEC2`C<3-JQoZXrvG z6n4=-kpm?e8ia$mkKPwa4=6nYr6CA(BS%%^e#IoFH|z+q8}n8O)<$_+pkBtFtgU(? zorJ-)BUiCEi56Tpi}srJGXW@#!{hGeEGId6Z}s$OR8dx3gpXyeBo!2G8+0)&$-v?x zzUrux`8!062m>`7&6MwWeIN>j*u8Tmm)8qg+@mPVLq~pj{FqJoS@rLNr>w{0nl?Rd z`wiD&>ka83PTFGQJ6}Yg@b0$AZtLwJ_M$CnI3>1u4A%QFobJ|l zvC5Vkv$A3|Bw%Dc+>vwlh1uhv1?8xnz{XV@aIFx|<-n1K+QcEB_fB)rsEN#?p7o@= zD%A;=wzf9=ArT;?5%8HHx^{p)XZ-Y_-e}fUBiR8(U-LzFMPBWPo?1=kEC!(BM5hob zg@1LGW5PF4@OcFu6#3$it%t6?wL?MCBGWp_QU(NW3xR(b1^@RR`LhlE3=mxmK!Y|tSxQQX(Gy#U9!pl49ChK zC`Wj_VE(nZuWV%Ya}P*SaTczb%_NAYp2EE@qq8Ku?6epb|G z_A9m+-Vk0Y6@mBa7K$s80$~}Z2D)W|C=ZH}THMZ_o~Ry%Cat66vN1bi;J3yj znSE=QfL#<*^N~B7cPr|aILWKpJzOpdYx#r{7YM$b9hvyiuaM62T=|*aT7gm#*gU@|J;>pGe^046!O`_x{RpIH0iYGFTg!Rv0$g70kB!DuvF zUMJx%B-2y55}eIVv)jSoSUV&4^Po;sVu>;paqvX|+T>u|5Y{U&bE}ntuL?iHuUJrM@Pd6nkUDv{6HnyNOUC2c5VV<+W~@X`%BJW)lRzbX6|X$<8tLTjLtEU@ zVdNRv>zpqy<6Z_3rCrJnY}{Cga!uLgK7BKjJu@cALO-WU{Lyt#Uj$3u+H!-Ehxie(@oJCDWy#OWwLpvz8jkkuf-k~qiS6QiS+@QZFh@#3oNFJ7 z_Dnt^=xNo_L!143s^u$hF1L%K1U_M$#@>gr7fS&Q^|iOd9z{BCF_!dz8-3ilg?;_y zYJm4jO2>86*hZTN2M>=@yUvj<#!O2ucw3I0M$8rzxIL0BPm1&O8Mh-(A)b!&JX8^m z^n%%LNm#wcK4T)2#bBpwV4nI)Bn3@PZ3*f5CPoJ_pCEnxfnbqMH47WMH|Iw3C!@XD z8WX3!ST;5|nW3Sf`90HtM61%Y4P=i%?OF&1Dk3!jNHNZETt!`7y;Q%o-8;!lK_PV7 z#*ig3&bn6o-lfybEP`I_^Y`?Ql7UQ4Hjd%j-4;B;GQ@(3j4Mq{v!va`=3T@*=2wy^ zWE0a%)9Oj`R0`~+*JgJ{vZ~^t9P1N zqqw<19Z8ht$$JycXwbazdEKKoEUCbT zy&sX9I>TgnbKnKh>Y>O_CMVoO=GnB|cA?ZBL^1fTZKp~M zebGRdYWE&{zSh-bYcz+N-8{0*baMA~c29njO%)K0l;(>m;$6z@d;jfY$-Q$_F4w382-g?$p#_ z2W8R+alYf~By^gkzuK!Ss^a5OjJvrP1)pMpTL2z_W=%)IcnR8~rcyc9-2iHnq_1I3 zo&kghEg*g2tZK2Z9fq#DIy-46WH~nYbL#dk>$)Zt^nH`tO9kG^%ge958WW9>zSJ6> zumHp{&9*|CBjJ;XT-C9NZ3TQZA=c>-8QxRSWzPtD7oC{ZAee z@_?_-W(=@J&W4zem4qQ#HcjroL zGMYOmsWb;;I^?A8kw`bEqYhmuU>d%xPH@W4J6s$^n;587lF*2f2tOKGX8EMJtMZE& zG3~6VezaKnM-YCIhSAjqJBx6G61mTz_-C|1Dh1CFO%WpABc!qZ2Xhc|QSe}bj@78( zkR=0X6*=1`1MKc1#I(Z1`MfWx1J@V>xX0Dl#%N{V}R-J0=UY zHE|~$s?>>IfgCzt3mMN=+s)U4y+utMsTB4z>NdX;SpNWkPN&j7KpDLGu?RmfLpJ0l z#=?slFU|R%_C+&A^#D2#e=sXEVv#=pN9LUlef1)|4d8cWqwsXyyYd!Xx9O;De{(T7 zr&u!njHJ^<2yy|$n=#-@;X0K6F$2Rv(bGFwfPe&4;DizGk(^-sRJC2&qf+}h80YC$ zUQx90E6c9ASX8l!FvYC@UVg5Y4KZ_KHhNK7J<) zB_{j^J7`rDHvN**r<7~$oQcrTc)6A5-G_*x5TSj3Jm4_aNPHR#07r_u^NyRpan&I> zzmc2s8xE8a!*=+@?=%-)|0U&oRkZ%{-A1Y1-If0Y7UO4cd8?+b5G&8?i+~)SxvGHC2H@KZL#| z;{c8}y~$-YbL&Pi29LU*rpk&*^jKR-e~k$>z_U#g)Rr0ypdQ_W4C8Y>;h}Dj`u_8~ zwEmU~flT^oQTvComT-yg+`gmXL*g-axqP38bgf(lzis5#PZ;3$#+o%PnqsEz=WB5` z4VM?|NtBd{&Z&S(ZfT*y(}tu3zF>Nj9E?F$vymDw>ej}!kUt)y4*42gs_5z22;dLm zQdgMyPz&c2bx&>o6Gisz&wE8>`6nAgLdJ9#(iA|5XO(I(QFzphaCfjZ23-B-drfCQ zYuACCpNT*jNqaG7Q3r^|RUo2agIN^fXO(7T*S))-OpyO&>}zKgfX850mdOnpRb0(4 z>woeg&x|}Cz+-Gi!|7cns$iVHrdwG0qk8A7U9+RTy8YNw04v4?61B8Y8YAd!Ekz4G z^3Lh=1e689E0s<|y~e|*PIPM_IcOWPiv@X~Bp@VeA|pV?Abn@R4S;ae-dosVhhj-r zu3A7?S{;S;-e&pF=$3jqej*d0xS#J19=gv2o05nz^X_(pj47+e>~32~nbNwhCpdMV zJgvD{i(BzVz(Dg@JU+hd#$oq7(>7$zH{nF4k;4jwZel=kVX*%S^w_j5)Y20nmgt*op#!>s4JP3=%Iylam8 zxr~xLP7lZJSX$uFo#tRpn+r`%>RNJgBt=cPwZKey!k`$SS(G}A)O>x`bQb}T&9QA} zqfR{l`ES>|LV;$C6WUG%Pw<(^^eS=`v%1d~1`emYk()P?5qVByrS1i1ckQtkn|g-U zf-Srr@{<=N0P6mpo}M1P`<=+6FdjhMnN|Rp(3$BBAyxL4*E5MLg=2);^`;;;kDBlS z2S7l<_%UN$R}gRb7TsaJKa5H-(^;F#ap&oesb4^d4&je^{LSCrKN1LSMY>G{hdr`n z@3f59U4}HRCW}dxp7!GEG?d0HZi}6{?N+FggTY|Eh{fcJ5K`IDp)@g+lSdV)e9NwY z|1%oTSBJ}scj%w8KkA}H0mwYCg0yPZK5rtwOtRsqyXSB0ls?XH6K`=MKGEq8VR191 zK>xnM*9_F2t;A`+f3j+MVwXwLO=RG;rzplmqhb)2r)VfwD9s5JD0v)IWF*Uhxlb(% zJb5+wnxw!Ks{xl}Lhj~zS5x(my}f0t#49jFwR>r!|-qg3{bk2 zrkfC1gNiMv_dCb@TNFZwUJZH>K8xt^2uuBGR~V)EKq61ytxesoV;HPWQ_Un(K24PR zv6OX8WCFe(U>E>u#>bYZ34f`goMQ#*6~WVf#aQ|Ivombm(WsfeqAU@}I7zzztgs7E zg%)eA9;lQc(V6;-HO-^jtNpmSElURQvb2c0el9@a0t_+8L7D9L@#&OJlh0QDBz~Yg z&RMLH_ao!FI1Zagi=sLF^o$~M4{2o%=|paI0POBSM|>E-APVPL7So{Vd8MKnr~P># zL_sVf+6wGvKL#R{ZdKhr47Jr>mVqB5GF)`Y1*vHGdejOj=np0|efWKf5%el~xYd^? ziXt{Bq_2rjBhdS81qgCSUsJA?@w4qKV!Z_?x3X^VQUnPhWo1L5Am3Pj`%>~ULp(ER zD`6(lp3oL1PKL;)f}h#+`}E200=_XDUC43KJX`wFH`^vWBxRF)g1Gjn9T`{ID7xvg zXl3@~Z4;^*PiiD>-tKIcT;Qx?!gSM2zGqZ-?x~pOmMkCJsGuxo-^8)sEE302LGgIB zaDk&`=W|i>Q!>yDV`q*KTd z7ZQ?Eni%+Kvh_aB0rJD8=3~?m3CoT)>Nqgon<>*IIoupT^!7!0;Jw zjZ)S_X&zH_D(ti2;o-%d-9ahP2$j;ZrjeTiiM<*uXRC*1?f?-)0)%>pTfckLv$FE| zBRCqA@4>|%Nwo=!TjQqFsQ8MU?e}NAhHoc(sl3UApqNlSv3cIIrA?aumhX zn|P;AXb8v@ltEJ3uN)2rj)SMs>b&dg<5_Ph&biu% z0V3t8+H%qdj5#XFfhra%7l>lH)#(?<4XN35X@*38Dm)v+`)l2H!lSo`C~+H(IKO`H z8!n4ms)lU|i`Yh!V2sI&I2ZvuJ%dzK{Ac!v1&pOr=eAPV+Ff!kl{opJ{IVQzP_#IntCwrJ`JMSjtSsde(=Iz#pm{NmQruqJM_mXXZgN-+owAIj zLv7%WOXSom%m+O%l++f0Pu>2wH1O<>KOc3Vj6zof7);*l>!$#~@XHOLyVv?~q`XA~ zp3~Js6Fp8jV>lf$Rc%HxzoTin%#PkuOPA&E32?;s7)r~&i(F@+zMi}0WVlDE-4=RA zezyXz7aA6}3g~M{UuHcJY-ZRjH0s1*6xZCGa!DNoSOal?uvD~du)59+DEd#g#xygG z31Hr!z?W>@dD}5S-upgVQFRA^b_w@-*P^CSanrgQAiGSNQm5{fA_*8u6)3!1VsWc=^uO z8x2&~m$!eP6k*Vzy}3Gz`urKO=mubBp<=`yqj}qwLO@bcj-QyY`Y71zTIe2I!w7&l z8$W6y+2mwEH@Hf-$#bpU*f?tQG%L|nqVeXmuC&h{P+Hx;eTj(%Rg^_^_b+Rm6sJHm z6QX_(iCphyUG0Cu+cf~*23gJIa9k-P20ZeVhohiY5b`yh^d-^3GfeGPz^%qgxgC)< z8OD0G_310RCcEU!48=XPwH8-1*56VPzu1%6oUMs@88BTrAM)tUPz#0Q9WU;+0p3O} zLFt|af~?YqK#ji7so9Izb7e~71zn+$zVkFgbWWZxUi5=h(;320JZptwq2?(|p5dQP zM+`^5pnYQ!5O9^t)L(xc&6}x?sivL>^~g=aPns58tKGHlX}QO?yX|=WOeGi(1jEHy zXqHo@%0LASo~?5*_fauqWAJsdw5o!l;;KJQ;gb&xahqiCK%!1Nvo&F_9C}NJ^VL~k z#@Anf>|nk(3>Yyz+-id|bE%};nr@Y&)T(-qt5f^?l;y8q!eN|iew2xFaB!0KtFG-x z%^Md$x1jAKKcWz+i;Fb&=p=`?- zU(`Z2Y1iW&g34_c1T-onn1d>&WVHbyC=f*Cp~DXv2X;&c$ld(;oRn?kbHWX18?K=- zkW#=VoJ`$a@N|paw(e#!q>myE<{s|dHuO9h>ga7exp07usdf#f2=y`F)C6E?Xad}@ zs}dsm9^rGCk+XSq|=lBLPhrT_jTLe_#X3H;wVi(Iwx$kGNq_1Oa?r3 zlCvS8J8=05xP_j`-cz^=h$ES&*XYdt;sC<7r*xFKgC)wVyK(+$1dHy^30#Ef~I_#<;_ zL0qeh!nMP7pW<9(UpKf5vB6o)Ms%-Y^L30k%GpLq9w=cpkhaU*HJfY)@BDRElj-+> z^(d(b7f!zSBWs7$Lf?b#hF-I?D+Uoo_JNi$TkV!lf_nmGt8(mO?o!=DBO+g;a1hZ( z?KoI{@A!%KpoNWiTz_|abp*tmE`-ySR(bGjM8{h#EG+``X`0$DN%y>AG~fC>o?L?;$FMu7XTPD6#JK+$}+=R!dF3oV#M0vd)vJ?KM3k05D< zpm%Z$VHCIZmIb=IF9$2tHuhuS+T?$pP$3kYmb(dXybvG?D9ELsF9mX;-3XZ1t$<0* zz0cLgFd4Sz>czU-BrN80DFf3!!rZMFyeN*stIQgK{tL~C4@wAfIPT*>L1fbYGnS1c zxIJ2J%3Ca`>#o=a;UpxGI}h{K`QcDHPZL zhzdypVW%|sIG`V-O&FBU%z318~Hy+Dc`h`iDs0CGz%&#);aD2oGMzBfH8`y%^1Ex?{SC{>aRn>jkkpr1SksU~8-Hbv(y_z-+bo&iwi3F*y zJkRy-y_^fI^p6xM;QMNS8q&-Z0ph^EhmIovBho&szr9qig`todsEbpEqj3W2N{#_( z+htL7LrFp^&5z=>THK1khOgR#xD8hQ_O z5S|cuoM1)#&hk)>)5m|n#{go`i_=E~srf@eK7Nu!chA84j-UjQRHdiBL9gsu2*9C2 zDDfM$iOM(Hivd9^gRfs*mMArpH0ig3#kue9(x;dxqsMDqJJn%+>2%H#wNTkm1*q@4 zq##Y;u&?%f97em_yDO%7ZrFMM7eo;f4Nsd|^P zsvwM5PJl$MWTyokP0t2;?wPUG{emthH<_FSME*G$gh5A#k>t)Z) z@q##jrU6PZ6afB3T7%#Ee+{RJIl;bM2c!%6V!&;4-<~hS`OqwP1V;fGNTidCb-p{Q z1<$L52^D!zFh>0loS?1;EW*gh$khWDh++F~EjrB@$SzXQNHzbYrUnZIV31vIqy?wT z&9Ub0Jj>v1+L)`0y5MBDDJ+{tkpb8F_m?hZma6kYWwR3iviU7~qc)s*FhRZ3@$k;eWj~Yl<`~gzQ>=oZ#J?b|q1uS=* z9!^zXY@};GSg%7GytvUtd6&bBBJXsPtEU0@NA9!PCgt(yidE*OjifoicdnH7&>u55 zRZDO17XlhksPOAlK!mw6zf`1Q4Z#FoO`?GyM|A6q%453w*>Q4^7a{C@+3Lo-ZBt`F34A zY~FP2V)6u;PwOzVzV2FCd}mfPb;+PjRV($Q-e~r-gdk_8*3l`blyp_LIMUkrXw%PY zcyY}pWtn}C#K0Z9N}Y!vR2cL|qDJ!uQrKDeb|xm7=@}W~Kxr8n6I01gh7}ZI4G9VV zm9;g0jA*}rfX6yoRy?GnLihDdE-o(S1O@5Raa$~fN_9g|xi)(7fUFD-;V&F4EVI*s z;5zm&jIU}iAZujT>q-EgkyP$b!n?}p6VP>8RZbm{ z=9q&{EGUD-y;KW|dwY8D2=i0DJi(oLA_2lUA2L6cQpZ6S!!VM80rLgl8PaT z#LEr?y=W*P)V)?^&hjDyiU-Lm)fGeDL-800OHyv97O@FC^#wVl8kCS+R*ZLlKwv(K zKflQjpKL7O2<0XTntlYzcsZ`C-@(F@a4iUFU^kvQZ+aC^%@u z6iVa7M;c@z+vm19%DMw9hVh~LYEy)qlk_Y)QtnJ)PtNchBXcywbBk83S7)SzoB zC5SvPByhtHEk<{1y<9)Lv6g{gAlZ%qr}NEz zs8@HX<2s73QxN7d2pHWr0DWP74({m&#JXi^;q|IrH%JOVE;{aq>nJ+R7F|sRt(7eVi<(ldJ=; z*S-Jsub#CTgx{|}E(8M0sn&PLy(}5Zc`EnZ`IO8DlkZv%02d8HwE)W?qYnaMqL%{o zfk4K?hC2>;#6Ysi^QQhUYfYcNy2v<1;n|KiarRz{$Ymy?*EfB!FbesC8=w5K4P4S|PQ?t|y>uMNpQkDh`? znmtLLp!{py|K?KuKX)dP^9DupW19cP{CSWJ{&NGm6wn9qDT4mH|E3ooc*JHzS2>~o z|L5?p79aG0K3I#1QCt72#O3cM5b84$5XIo9mk(>>zdcQU1RUTl_PODI@esxN=e7H* zuK1HdaEv}gqYnpv|M$m%{(XdBMgx7I@1Xp&{cn1KM?&>}bdvn_LG1ST8wQ&Z-GRv6 z&qNx4yaf%#vIwl^g|C{V2B zuc}ubGz5Qc;1_z9%?errFunD+Wn;ja7ZaeqvipSvW0pva+WHdleJ=%G%hzoKGqQEM z0I?dwDUW!9hy^I-sM}-e_~|p+z#m1gz2%u^9#Ah+gg4G(l6K8IYv>tXH|AqIzpKJm z$YW9rgU;_V@xS`JXA+?#fTblQDSh;ZhAzUqzA(^EW?@6j#a;yGOZXb2?!1I6Y}H=w z)%kN)JpYGzuh1rK-v4v`yM4gQ?!NT71n)ccZA?A>n~PiL%U=Pu#d>T(|%qAQ!=Haop53g5^QG?Nw=(1PuU=>e%dc6pSmYrC=Cqwh zEf?}CLcf4cP;Ti#U$=j37w^QZ_j66OU+52D7796uj>>kq;BEMewGnCg`p`qQm+K!t zgAyS&tKk8jX#jIwegTfL9%C8mI>j=;!*F<2oG&pqz-3xxTqtx)WWO%x5eb}bZGT#0 z;y(PD=->DcpQg$`E-bP8f%O|D^Y+a!Y{f{4&t9{Q8sF~#n1Z3!RLHF`%+l+)-h0;; zULqfo*-KNpZ1c*hW1+-QY-B#mO;s_|bdPbBp^1)V^(Z1wdaB0CLXpB|&bk{w>(Tc6 z^KLPvidU7H`MW|ME~AcGUgMX}h}~Sla=ZsgU}&zo3s7I=Ly(iY2CuiZ1&-(3eq2^% zHB%LH)T!^qV!SZ8HvL6k7C8Sw(FR-p(z->wzH~iyzFD zp92{|Se50JK{o)TK|z5(YIIad5tCzN;99*X1{TL=Zq%(KB=dOEGdn{2 zrv6!B2j-o}^ecrK3?8W|tHmK@qNSfU3rszRZ+4Ca7KHk9OPe$|xX(Q{gtxLF{npzl zx4g8SJg-jm>9n9!p-jlM6)UlTDHD4_tRO+TwOA zEsS-eq9tBn_LGJm(+BpIq5aJ*45OCQFz2&z;Id1~1IoN(Gl6?J#(r}+BU4IToXHpf zU{rHLKuKGS6^Gjg;C}=B<9`86m1a-@Wf&F!jO88-KRi4=uIWBC1%EjJOc2}qJp`$V zf=c3z+TEw1WirS8(#HPaIpsE&&qqF9LgxmAaEvgwOe~P02T<>`aJ(}xUF+89a8;By zfnx1er#bbMyE5JK$I6ZfHtu#<`>=*<`OCL^0SJsJ|lN5DzjSu(8{y#X#LtY z=zpV}b|ied;T0T#l%BvRF!C6HTP9Gsi=gk+^LT-?#tYM}W6X-`G^nCL zV>%Fv_bwsWOSi87B-mzpG(7JbcFSWa>T_<=C*|fSQ%S{PQx-!DuC%b(TIj97QZ*Fy zb@Wv!Q^3W9uF6l*M;2A$Q)Ay?>Ffo4CvT%K3#OBl*cq6Z3js3>+|E{6R$&=iO-}~C zbAy&R`R7}DRag}jbo6n|8+|QyEa2Ju_TJ66$HJz%tz7JC8~d61`gg9MbBDu`{XKJ7 zBQS?uuI)-MPyG-x*OL^l=wZ(Ns=M1v&uy!!T4h1%1hKce=jdji1QN86qiu_XsyL%^ zjJt{gq(?lj2=%&gy{@ghmxFj(pat?5{cfj0HLXGKhVwbDwu_`T-{AWa+bMmoR8==! z---0yDzOdm;N>;iNUBvvQWQk0NKh;^rT3}=A_4-^rHd5l)r1lPA|hR-cj>+Nnjli7MS3R` z>5$MufP^r||9j`1S+i#DoiFf#1xXI){Pt7!es*yYX37eq;fElFYRs#&HpkB$5(%gM z8oD*M$3BGC;T+92UGCJSer!x+xI~RYCKTkhEBnKO%L2`RsV~_}^PE zz#Gbe7Py8!Nmm7=M@?O4a)r5VCveXv6s(~l*3?qX%4!j#CK;{WzhRH}Lq^pYR+!uB zme)G9{Qm`St5BNHp#%l~p&Dn-{P!O~bX) zLiy*1E>2eHME$0$LYp4w2Ar-Y=FjWS&Vt!9WyE8xjsS&O-2vuF8A*Q9@nC;uHH&8I!?)$7RieNDio=I?+P-E<$kuZLYE zzeo;EdzdQiu~eF<>4-C*Xwc-u<6b70GY!ea%wus@A(Z1J?CCY^uM5}bFBG6trQhmp zGkEbkD~fb4s5PJqF{l&|MAeGMwD;nEzS9QXP)=3`n2qhY*&|swxMKV4*t^1YF6t%& zgVWkX3VIT#4^QPWrZB^1M54IkL{dKSd>7xSLyQy@j@rRzT-On{Z9-X5o@K$u)m$) zSW!#pjuShw(tF!r6rk@iy7_r|$p?YtJGi>Bb_9&Z6O=~7-^YTfB ztdX*_98b&onhy${==%-Igd-e)(cny1`1dNGROnNe+4`vImrzQ?*u+XcyNlS0Qz5BP z!+bz0n?)gT)!P;Jz!s%6I2o@V08B9p8ox~e`lg=U0%vc(&heOOIgWS>bjhiysoBbU zGm)&M%`ZO1PU(_c{=m8gblBLC3jO+ZOcM+k!_pV6hXVrJ{3P8zVn^FTQ&4b;teqrU zyFzIarp14u5fjPrPQ-OI6o^51ks_)2t#yQ>`mUmihp77M6euwQKeAUY1_rfkdvBOG zG%Gs2&ok3JUQL^q`R_+3lqPUJZ&IOix@wD)asiUH#ALx_vu2W{dZ-f3&fkxLQCgq-t-ij~%?1=_V8GFER(JekJd@qMe{~Dy`krgm(tamZvGLcnL7J8<0+~=-<(e;zZ4BLV+35;c%>VYo&BbU zD5##8T76q`GH#c^_CmsG&S@)Mrd~2n);;_j+-|l8Cx6ppAn}TiwI;E43oW}i%?P9WTK&&)J$9*w6ILo8*kA*^URl{QVTX(=f3i6yo{lea5#-h z@_m*vSXcvAY)Q}kxrerAtK6sNtHVkiMv4v?RJ0t+=$0Ebjl`{+i*(2B-vM0=(F!Wm zWF)e7k15ajET1*`+P;t8-0$<$O06!O%BZmL-)|~{6T8`ok3Jem#hjfXP!x!*0cIGUA)7)Y8t+rS`L7tnF)> zyW4|i?~KRW(`vSLXSXZA_Yy%Dld3VPn#8Y87Vu2iQCEI|8z;W`PIf|a^Be?tvOvJo z?jCe&wqX|Gk?3v>n3cA@r>CdhGDlNWMm6#*-3mQ!x4@G^^TTFb3Y2&JM#0k{$V(~Tl2Lu3ys$2*%g{_ z=%;k&zGqasWD_)X%jHUw@OlvXBrUW>z^wbz@$PJ@nY3gBYR(i7&gi$?5XsNyo?VIR zU9fMipYFL#YP+IONRmg7LWf3qYi_n@ zF1AzZvc=&8G|V&3LFi)r5{*gM_A1mNvae4Bdq|Ls1EX$GgA8qED}p!slLwu<)=r!UrzEj=8PYZtgLF7$q{k z0ziO8U{l2mA-pdP9ImmAm(1p^cyaq+b?vSo31x7-`o z+!>`fHko$`Ayt(UUnh^5I|Haa80ZCfPaJ0d-*vhFQ;oY~0%)j}o5w$y=5gl7QzS{i zc>X7>r{Df6EENkt=LFHYR5bBY)Lh zjTXV`CSDrPopipt>N^~1o?Xwl;-8z;v^IxId+r>Y!Bcz*wQga?;y+-jn+cC%HK0(B zYTgzvv{RoP%r*%?Cc})JuA&LKwrHV#lY51N;9}nU@`G_|L|Lw9&t^0vnx-Wfkn@{$ zN!ZJ&Fhxnud*FX*)kCCmvpK**OLA9 zjElIQPN#tn>zR^GZI*rfskVw4G_|;x;)h1cmqdO#Y1XXI{+x9cDQW&Jn;5oM)`0Rzr7iLTW%)0GfzdhJ)Rpe( z7N1YmjH(vb1M<`#1levxA| zV1jKusk*W8XPgg_mfvEKI5MUsKfNG4t>>`6m^T05DfWsad8A+a`}NRSSGP?UQ3E>T@i`Nz?@bMIDsRnvU@C5EuR-|>;!|)AB<_`n~zei z|KAwLTs+9tf4?}l|ADmC9*=SRsom-3Eaz&V(s9C%5hq?fB)sV~WTY`S>eejA>D|ar z^PYc^kfnEEPS@TcR__E}6tS1Mkmj~Tp5Lz3a0WG}!>+HUnO)47hc;0(+3Gf&<9&6n zDf}dwpS*2`%KPjP?`qzywWfVHUs) zL`Uhah||Z)qRQsRNjeT0FQIMRrZwgWEdpzV-&LA#?7y{qHaXT=#$wt$sbW$;g_;Bm zZ4onu8_u8Zu~gExn!C+A_t<=JPgaYT8zIh*I zL$O9XbwXn0qo+IgnmhOs6}EBScbW)~o%bzzcZ}JTf~{qt+M)9g9fnK4^2&mYS|+#A zGG6$S&BJepZlppT$q{qj%OX9^=X!?BjDJ!EP_6jSys}>PVB0W^!oZk`SOZ4#Ql=}7 zZQGj!$*8&tPrqyO$gyC2ayK<7tp|OEul%6o@I@0Sy#iy0Llg*F(ECVZamRBq-8D?* zq*`hloh0@?jgw!`xoWa+#LMIJd?p$Tacma1f@9yOZ)^Z89y@daXlHl78Ag@>mXP`L zMM={yOfg5T75e%c1Ae{uVqP0pzA>Z$m%TvOP8Pi&b*jHHXKs0e_yS*leEu6~iI_cN zmvBmg!v?9>cP6N@t)Ay*J}4+Ic^c@B%FOp-YfnRdsdkWEangOW;+966uQH@1IP~mtS{78M@# zG24yUH$ZLk^G4nEK)LepRAz2Boi|~)2h-jmJG&xSQg_XKH}mpo#cycTv045&Cjq?w zLr;1#%TlGnn7;?V?s(HvlE`s)i&8g(ECsC_Br8A3)X6NBiIIGh5(6~JC7Et zy^i6dJO6Of%zMF|cl~SiMF8dV)c2bAL}9U|MwQQwWot9vuK#)7vH|_`JD}%R zTVr6HJRmrKQMyL8&3*Vo9hnSN1=hrlyHX51kQKB-2s%1MA#vpgOkE)pxe%n--7ryl zlf_DuR#_P=>}@gUUVk(#d(N~rwfgn`@wJFkk0fLBoo$D{El@kq+Y=}tjy=IldJdem z$<#^O7}$Q|P3@kQrCBQyblCbezf_;wI5o!3T`ywu%F}QCAfDeK$@g&Wkw$WQtn&-r zs`GgchWYn0wGH5x0jq6vn(%Ew_|$R5sdi$B&NdjrY;IW8y@7pM z3a|3-2cs9vDHGRW>@GkDHA>*m`07)k21-W5n!6lv~Faqpv_t|Rj)FPIu%f3El$eZ z$j8N+1*OITbic4e$=PO?lFfBj(}(am7SN9vSOm_x1Y+vh60Xf%+}5QFND@Bu9387u zH`J|nwZnYe&RADSCsw_~%=a&Jw89kG+1}lB{8u$Nv01tp;8O~nlI>r^i;e-aWzCxU zMno|js;Vquz*eS`A* zMVh~Pbk{HWpk@%N>9d`VOBK00uK-g#=TJG+9$p_KHH#DZD>Z^D!c7T#r=V&Mzr!AV%I0+Lt>_1rTA3Xa- zjEqNPhs$LYz?4@KPqV?U_~yF&WJ}ZT8-QdWZ+fvf(pK&sB#3^=IG8FaX*Ta+*o+O{ zj<0JO5Kc}$#x}LYJ~IP~1}N)opu2Uc8XJ1sD=}*ohuTHS;xTaebeX4TMTw{9?xFUl z3(O`LY_0oMRnc{>oSkj$M727dQt13Dama&>Dd6nXt_F%bv%eShmZp`5OnBnsx3#;RsGk{`vh`&m zv!_^DJXrfeNlOxI<5-{S0gRmj$Fi>ID~Y5t!5X4Gf(?n=U?+n0F ztBns`@(DGZX{t)nn7PwMvREJ+2naK>Eg2#X{4RR8nNa@Q_5&K`Tw5fmRXyoB+I{R( zZftF$W$&;(m^$U_d2yf&%O6&T`PDo-hQ@q7-#Juy6JcQ60;E!j+BC8Oat253^TPG? zZ6Fapy@^%`jmzpElRer|%XbVVy{kE$69vt*byh;6K^~uVcW!DqZ2t z4XI{eYpNh-)*E^d#2sDP@vKc~QV$Z+}``J~{4f zgf;II1lUHanv#RN#fgVCH4d9&0?&R0o0gQ6v`7(q_fXe7gNI-8LcsZ(jQYD+r+29K zCNGyc!|3S?uds-y5__!K%o=ccXxy++z}rwFiEOt7{=WZ=8z~z=TbdhR1FT74F_?sv ze^c&Cpu3&HxJ~1_*|>>*5C@Sxwo!2H2JlN7)1LYH>ww8(gY84MY)6tL9Z1yvTQuMe z^lWLE@t}QX-AD!eoJa<;LT3bDOdhG?2ocB>eSpQ(IZmcDw~XfD$-eTpDGL&l)4@A6 z;AKxR`bO1PTb=7BgU8E%SX#_7FQWH^$u;D;nnQVOMt9ST*}JA>5o@XdZ%BB~{+G>Q z+H1bLmRl5p)F%p(^vyGgZM;3V>@aV)(Ii{wfmY{ji5fy)rev~6-tF$VQ1AM$-Yg)` zFGaA!POW^ow_nNxPX`yiiazK&b{zY;5ag*JZ3crMODu17NiIli&wF**{B<-NLGini zj%e1JLd(>sxtZk}K>C*Heij#>FeQ5?U|gMBt$C@oLajd9eXGC9cWb05mUn$9-L>z= zvs>1ExypXrrn*I4O3w1nGQ7S``&G0#byI;Cw9*ce-eHp7in8lT{(R+UTv*aM1o6Iz zEJ=iT&$^oUCQKiFG;tNm!)GIl^^dQ0V4!;e-YwUR&~jUN8hDm@C}}Xi?ytUTupaa; zv%&6&BC&#XNXhc;BSE60t(NSn#^l=|sYwWI~dAL@N)~AoQ(FE9^s?dQ10V&M#mwMLn(Ah?s zz+^}jG~+#+<$|%}U9Ai3AJ2S8Acul?eqWZeA${uw%jQ!m zD#NP(m+Qkamslo&|B|ZQ_VmRv0`T0no4eLK9KGjSejXR1qMCSFT)I)$j5i$6ejbJT zax@eDUK^u8GB-?hbi%}(XY@wK=Bp;1Uh|hsUI1h6Gr#(4GGmA4U;lDH*NP3sgC=g< zr}vi%i z?Mzo7HF9&5V2);NC)UlPl2hdE=V?86_piJW;o+K_ascAilouHxa_E}wnBPgZO~#E= z+CK0(r`COM@0^J|(coPRqI!DiPL|5p)_#p15J^8Xc^D-SQ^MIFmpEGkx2UBF3=}Xa^fP&G~3XX z+c;*v9&%qICj#Fh(#VLrTmtt(Qmfp5f1dE@b<%G83i5>Ah>itRP182RnK zF58Y>!&;G5z|2}-DX?f88N;+TNAYU49eL}%7|X=Vv&vopZL3=Xk*&6)G%NyQtAIo7 z()WM}xnx)lm<6>!j)J_Pgv*@$7I?v@fHxQ(v(lcqtibJzTF6iZCfbpJQPqT(`yG!y z>?b9^oCGk8{-hTabU@K^=NvGobcxrz2v}mPY0aWQFe+b@SfLgtS(|l*UzHjHP#DPo zOaVVsdSOS2nA^Gd;Em|`s6#cGQ*E|;a_UiIZ%BbigAl50VSq8DYZ4RtveshC1u&N| zFnhR={xnjsasHnM8FYjtaGG_jczUyt9InkCQ#Aob$*7imf0;ucfbNn-#z>MxU(%Q= zT3TD_rPY{->%~yO2P8{q0a=~b>@sUZ`r-)1QS06ad@$P#7|&WdO}s=`^y9A%V=X{p z`$GkPuIM*O3Q`%b!{pi9OUe<>Ocp1k`87)D+ zF%+f4FH0C9VmKfBI>qObOZ8n|n=eV%IzzQoM>?MdiSpIR(0wIlK4ZT@2aPSEky2Gv zEh#M}=PS8w;_Zx5qquyzaQZOw6}u==J9y+%$*&v%L+vqp2mhd+uQGI5B%;1zG}UB= zsq7RL4ETu>qa{RnG3e$>Cjk-V zro~9MoK2#u_=<=g%_1RxvU70YQM~8Ii=gG`!M}ttSqjkwB~)xP?8%{}0${^N)IvaN zb58zKp^FMd0|r-vKnD>AvK>_l0 z7I?$ja!1EF(xKkafS`sKz^4UHzrGPYY9U?KLrRbZlVzZ)b(CxgQYKx~*5LVBNp0BgB=Sjbx(=R%?hirUz1Fh@kBq*7# z7kYfY%s=s%rh3;#A?Z<5IX;#`ruq0S>Csl;+wcklr~UXO-sm+pQ8rY!^j#qK6Ni} zM<^5(#3|(jhQ`wo0ps%_laTXFtrCsL4YDUfC5OK?g~dA*OHZQ9!Mh7;M?ch9ZafkY zcmN38nfAv)53_r&-h6u08S?OoxYrdEvTJk^-}e?RL0X53kVFV1AS`?t^_7f$@lu*j zoW9%~F9L{z$>w3%5_|Yg@OA5#A9i#8{5p`Q?rL)+8X6i8;}4E5sz?kx^#k`CO6bKR zB37`i-Q*gfntDfsJd@9$YZOUqLUd)zywpMlUma4s+RN25UYlrZ7m|^E&~tLC?dzSY zxW>3%=&~zY^5qMComJ=M@phD? zi|77k}pYjj42n2lIK%j#^U!HQvF#YVhb7ODMfYcUfVFeyzk#$1(aXAwzj@Sm~*1O z*zFPgeC%*T*=u{POqnuMGT45*-t?NVLYffW*YQd3%}EO%v(4cgN+yafF9<_ebad9< z&YZk*L_hfYRoW$Q?(cD#iW22#VLxQMrNhcmKN_z}rB603Gk`2qvCHejf{Iq;q`Pk* z98*n$+FzvCZTm9kB;pIlZ|vElaY_S<5VuAkowFz+tlKYXclOjrPBJkw)ho~RoK?#0 zw$2}m8r!S;dy8W~_G*Q#eq5sNp;3;bi(y;y{>I?vPBzrLyxlmvKg+I2?T>*SRa`*@n^vWlaShVSI;N#yk0*!4t_E2nNkye8HJrQxaxdp~TT?ANuL7cxQ#jMC5o_Jt-<;viv*x z=RgOXe~|RV9(<`4i-N{}*@%&_EMMAWQ!4UB)*gYu9A!?Bi-ol8zY#-BebT&{@qDT3 zYio?(zGncEyvw;2)*j%+n5VA!2Pg9r;(lN|=c7}4kLmyCwA)f%1VWRzrsIGN>OA&w zb}{=e;hz^>rMzv0D9%z*dUJP5;j8%6i!Yax$q0{7C_?_4*iClr6Nz}}rhW{=BfcUo z8JK}<_LCrqY@A{bDgixQVjwP9RdS&{Fn6@S}i5CDXS z_`f&?(m5GIq={x~NHv_rQO3efy#VzcO^9R$x zx=C~Or7x}@S|!>WvdnWMMB81n{eO3^kzOW~+#tD0@`TjiO)ng-{Q-QyDr$be4k9LCT#2tWiw;Ln2j_zpb~!hN_nvD97WE-@qca2a#{I-s zVrJ?bVzbHoj$b`FKa=DVDOZs^!Zf?06vhj*IE()rA{DtQ#3yeiJ8t-H7w41<=>!(h z#J{$(r4#ZyuC#e&bP)Xb#-*#4K3Y{zr|*y%rd(l;ccBp~)JYudmY^kPq!F5BGm#ul7}MWu_yyIdEB5?)&~{0OtiXbH6UrE(0@*EfIWufgP} zofIHK^SS+asD&{AU(2g}E`J&x+Tts!AP)?V|Cs)^I`R3}&rG>9hU`=c=X=xMy5m#6EM(zF4)z1msWV@ zU1vAei;ANCPOuO0ZhIDw+cO`7$@^fCrFL|(%q=;^1<1C3cuK&iM)uWR(#tC%5)#pU zt^y!S=AAbYvo)D^F_$+Q+Ija^h4RyH%KI|fxDIm#+3WfS?&onviPOo~sW4i~-5IOh z2MQtjb$V)Q!G~Zaz5awpV?*hFdQW_^wlZc^HZypEeIMl`Bh8K(R_7#-E} zI)f+l>L59t(euEN%UW0jnZKGE)%}n+Y!8Jj%R5AA(X-kb9YiL4{(*--SL>nU|>OrTa3mTb5B+k$aSp>#P&&c26mN|2+{g4uJQ1+Sab(k)eL zlbUJ^>^+8Gw=n7jscQ?4r0&ZDV{JUtaGDXHY(!@`C99UrI1^@mw4bAG&TOLwKyyRD*(^{Jdzg z;T%T%ex4m$u%J1Hy0Lbruc}#ql#Z}4CHYKwkARRvob(ONsOd9?_^Z|$3YxoK82#LK zi(8Y|ROGv=b;YE?jsYViryG?n7kr}0uXyJslaYqlZwRV7;07E{b!FuY*>WHe-h)wz z3;}9mIZzu%fj|o#S0OZlQwo7`K4OVG+XpiBugjl%1;hj;CNLJJ6A6b}&8DqMnK=M} zb6UpZFj|c8l@`oFt*Bk&B~msJF2l;)*Q}8OFf<<*F&zUTutj&*2|fF+NrvJk z`aNTRAvwE8Qp4X5iE$zk-_^^2@jil_=l(QLyXiOQGt8*QcjXG%hrrvn|IN2OIu*;F zXpSu)RZZ{Y{dl>VYV6V@J%EeY^N(7F*F8s{(i#>J1c};B`{C3;PV{U5r5i?N$Ho;4ne|wfr zIM3&cTy2A~FSYm_=ssrBvnBAB#UEqB@Yj%6j-s#B=fI67T4lcR2 zVsBE2*OCqVzSEOh;y@3Q$`LAoKuSog8*08=>hdB?eT8Yvvog_z6_D?8q3IMB=(dj( zlt}3?iq@3Zq-#sKhVNnKI>31~sHBxHho4Z1`*ZC0j3I<%vQx0?_Ks>y+EUTy%Tbg= zJY!pO%4e{f&d=q%SiV?UUFUo7AVm%yC!?-6d2ALZkXGSJ1TLk14v$&!rn}2fZIOa= z9S5kNOoGP#AHI!*hEvc&^#gtW6kp_^vZ??ADjMJgTff6-Y1=Ly6@H{oYCA%es7vfD zBO#ajPGYS;Yz0KOj4j+%AzcHai@LPT1w)>aG8lJ}Z|*N%qhM|Qf(VvmyiUI`MJ;3> zQvopKPLo@Kq1@CItR(=0$7z#1zDRjNx|Y3-*&kC;-%kpCzViq)2)xX)KEa$4&T_UM zMi#T?t0=~g(9_%V>{xmg81ys^{*MR{I_@5N^u3FsWpl)WA}PalPHR;x9-!*>*B&$K`zCP(?h}c9U`Owq<56D7H zzp{ZU2&HAqu6MHX5jk&@X@9r6x>^L}LQVW^1Hiij;E4!4K21gCRm!mb^Vo1`dQcrS z_`?oc#Maz|Q~{g?-P!M3tK?rF?%^G;iFuWGzptL4&Xm;i=}#K3nciN>AtNn9T+Ay9 z+p^`s0i?d)chv-zLrCXNN9kkkFf~z~O!6R3&X!z;=B6)kFj^{{ohU6+(%oDp~ZLH95X}P_A`M@R>ha?%U0#pGrvCEmsPOze@fdwqaqI~ z$nCkx`na?TH>&&2k4@n!7_c&(iS1Cx%TbJ%9r!^YP}y(@GHffsX#1ee&@S?x24%U5Y> zZxj0~;J0P==hT$hw=dn&Zr5*}B-W=?BSbY-C@StsOE*2!(dM;ePD#srxaR$~d$8fv zCAqA}qNBY#;vJCf;b8Hn-cg32H%90QLbTBexR@d$sni?@!TNijHgCj1&~C&vc7aX(^IIVlp-b z9CJRBQ!*|XL2?LdFWISMoCcN5lWd*MS+2~(71gKp^S0*NV@EhAaJ%Y;@_xsKIswDN zKC3+>@i~vi3pn)ieD_D@9)2eSMTraCY$1dpt3J4t9Jg9r5t2h7$ivH0Fn*+$>!gz_ z9@gC;vP(MM_C4JwQbsBUJxY;0iXp$HT@HsRk*?L_d@S^skoa-L?S;_J70o~^AC7Z_ zmjU!tZf?zkpH@F)@cLUcd5%EGeqQMuy)-lXn-OwSOrrbxb>D8}=iAgV+*5Sl+bVC7 zKY`@(^YiE2`z*;1XnE*}=agDJdy#?XLOhI~w|N2@nJgCq@XijtZ|^DgB;&7haA-c! zjuh_ctf6ru6L?NZ{ls4mN5UN!u?JYdy3ALu+=X-dHZoe44s`<4YPzxBCCX={DqPyF z+*hdH&@oyN2B`U*W0uYxUpe{p89K{daPrKl`=33?h*1maVL-`5_t;pe-QQ0_Qn2}b zj){!AGXqRl45(J$XMf`_Wd-6YX@Jx^&n8rVV$FyJK#^Go1h{Z5{xxgYUre5DFl4JJ zdMGy6ZmIbn2i?lP-rYDj-G!9h+hABoV1nP}!1Jb$x(QoJ+Uq=6xpAvwC16o1Ad{XQ z^=-sNo|LXc%IFcxCgG7qLtq{!eQl@;`@kqL(E5td7tbH|^s!?1-uJI@KXGc|V=uMs z5v`dr@t9z3p}&YvXwAe@Zy?Ey1}eAAIO#2}-#5p;31i+k?)&*ZlRE|);{wpjr!Db{#_jo^50(mXU%gF6^4*R`78Z6^2Jm% zZ}DL_atOp*_8XV40HG13Ucs(sEn6WpEL`D*@KZDDlHmQnXYu6ly~Nvpk7u~L^)+&9 zWMig-^x+S1SiZNd^dEMCHO%2k!5+?9Y&8!r?T>d!VE5S)C!!CA`_FmQ@IkIO)r=Lc zoD%Yw4j1&E6h!L>QI(^z_%k4S6wrNACJXH1LngTmDOgFdD9oBre%7!EEI%7H^#^8- zm|AnkTps^LHvU?Z&7n8X1JhmrNpGJqqXl$2JTrjo9|P&dE&82Zm8>L?{4u_bQ3|WO z@kimds~DgRhyTF2_aaRpclu+!F$?L-`|@UzU&=Ujy1|1${%acK@K+8ctA*lR7})^B zkJpTr14_|8fNF3HPz})gO9Hi3m#CFVKS@4(@#Nko80lOfAQ0P-T?$u3cNa+C`VdaZ zTjB)NCpKQkRvv^=XHn5BE9kTH_8rce>S}#Aw?b+vDudi47QHf=dUgHeWW0FC7&&#S z*;v*nhFD#cSwF4UU&!aZ>Q<;e`Epon64A+WtF*SUs-NW_!Jy|3NUDkxG4(UJj0dsT zt_BG8Zy_xLVPv$njJk_=sD;WKA~!Ft$Rn27_=-GTEUgoXeW{{j+g z^dIH#zY4jkx z$LIn{@z;5SoaUSLySlqU-%5qI5q?g-oMOlNq5q5>jQcngzsgMhjfw;Slh8D*rmT?%+Tq2?L;SV_U)vQ-jEb~yOUhQ zO=zX7j%T&hmZmZqKK*7rLf0ajK+N#(>NKsWA&^iwo4Y9thg-V1_Jx&h#((Qgur(~R zywx8*mCf@|%7C&`MJLtjx)IwL^UnkhrR=GiA8Op`%BvM8?)QfUQOy|}g$fH{W_z(X~+fDZm*1j`sD5%ClT>BbcWk?S$Bd0o*y%>?B z?L9{Y_kL^7Rlbwo7ao=~pJ`Y*#bZUfH$SeZYWsV5IA%wAlU?IMQ7`zu25PI2f;NcJ z>ee-Lo&O~*XkY4pNGDYg`905qNIn^N_D*Q z)e7@Z56$SqGSg|THbuC)KsGY&@`+cxZMKA}sTEOQqj|*vw3f}MsO&5+bB)(ICd#yY zGjY%r3~O_R@Uc6Z$fbDGx0(DycqHo@cx+q)=Ll9JB(Z_`UDwx8~sy z;Y}+XoJ#B@4=-MZ7I^HPIeP|5+Ea|mn*Lh~ z9UiFa;J`ONnnjM${amzOYe|ZMEqx`)cxhQgy0q6z8o~;339@5`xF{y$my2W<_ zNDfRCWm0FA02GKE9UB93eHm0>mQ4rT- z86kDH6Y5tK-rM*zn~F_7to~i9ve?RFf#E5k0JMB%CJKHj zW{}fayxUQ2(|YkSlrJvA|E}smfHx3k%{ZQawF1vN*&FI@4P=nTxd3CN$}!Swtc>r% z$n5Ube~=v6^6JVi`8*G|qZwunBQQ+V2lc3&u1hm6h${ryha3kfDZXdk_uo0Q$Z*|# z`66%cv;Eqk=cz*DS%C$Q>GX*_5}^}A&&koVDP6rZgy^Kc7V0^d6$&hL%vX;TgknlK zxg!yt)EMq%E^;2z!_AjtwyhYsjpg|%Fzf!_rOqs0=9RwNpU5pk+|N!-2pOd&S|Ha> z*?3PVGZMk}t86irM%ed3oG^ ziq`a1I;dpEFXa4vCIZn1ZD?8^Je?v_zz(ux$hkV__@>m1gwDdf(jX$2;Xe!gCz4!W zGBdS6_m5nEoq-Fm+s2=UBfEf|JlR0f!IKVP^@<_T1ukobPqh$KHf$dbImWIen7HUP zEco)9ZFB!q=@&k&Ehw}_g|1XipZcNZ3Iq$b%zYE#?1CAi=_i%+#A_ZuLQ+jr4m&*4 z!!R>J@bz@}M=@2$WyZwSkactx#BOX_;PhsMyVF9h)1<|Kw>dPHTH5thu;DoUN_qLS z&4b^r@bmhcKp#4=s%ZF*+Rc&$CB9;A5>W2#3L5F0kC%v`TP!T9O*GUeetVy;vVT@Q zp5pk(IrBfW0Ib8Ff~Y(czc@aL7b>Okx!qe*`noRs+tJo|1W#PBm&Oq}YSlZ&;EXh{ zC0W$iC7H}IUCuXMe3hs^eQ9>mH9OA^ov%rO+ga#78#=(;i9=0TaTjdV&zVh z1k5)1gl_+S>XIj<5FO`Zj~>gFE_kJ_#EZB!8pauT6Oap}a?XiEN<4^xG#EM4G+^m# znGJmyjLHM#jy+3iYX7<6)5CRLM#hJ?StBTQK1u@MX5Jwxo}BLIb4Mn+TvZs#|4@_q zuRO$JF(Bx3`+3Z0iqxiDk5QhQ}NS z1C@8>n$Jh-|0Ejz6%-BVe>0f_O|dW4v}AY1DDFnDwE}V4Izj`b>@Kfwl zuiyY6Rz)GcfPZ@K{j9TBS>`{cn=gBcAO1)J6upuO;5cEsdg_!5KBeO|Zoc0_Qd3`8 zC4M%FHmD{_sspPofPHdXL6jhEzy&H?cxpZ7=n~3Jw8$axTn>BqdzXsdlMvyVQE;0F z0W2lBLHC5iNFanVI`|XSRbi#h8mf=izAiWo|NeC8L5%RD*R|iz7D?A;N(xd^?Zf`A ziZvTC?y^2MglV@U!3UwE3vDtCs1kkFVM#@!mt)s|Fx#8drN0D9Ppwz=qE!HWLCY!m z@mq2_A;ev&FQfpyr|-O>QE5db4F9Nk=Tk`K>a412`xERU_;zWvRi6S!O4*I^;<6cJAxo?w!;!@z8E?^Kb&>V2E&KYE9(~Q z0r%*AzmRc$WSzfz$6UVjlcYc+?uEQmEQS16S6s%t*C}=+?@G0Dkg7FwFH}VnkRxB^ zINl#=quuCf!65JY4qaldtYy!CCA?7YGW&Et%gTvOQF5JRzaSch%DHnZ%1;Wp0rAH_xbGI zH%BV?5FRpavQP~1`~(D0U+~xs(0gtJ7x4YYPn=YcjfFc0hct0!hcfy)=2eWe3A4S z8*_b03B*=k{{Z5ZuzyBL$1}d#Jy7ErQ0n(f&50C-#`}~cENb)9Gt**So6auks2}}UHpRAO79^?owMbS^m6P< zY*XN68S)q)Y=`gqnC`xIV2~=Ak!>Is?XjZv$D-0d(MoqNfh-p{DNe7O8};HncN_;- zx#YJxJg+@e`EIs%#q+Q50$I8Gf&Lu((N2R_(GC$C)^dcnLH4^5nRS66m(tU#v^)UT zj6PN2YHK+dTw35kBptq9YMU?Ec7b8ZnPn}P?)E`IKQU3~TU&LCZfDGx>)tm(?EFz! zo)`N8L&xO&BDk%Q@DU1D3{xK;WZ8hZYL(vZHWKN!GU2vkEXoVjqcst^(;W)!Ey6b`~~^`;7Z@K5uCu-yhzUQn)9U zbn=Bh-%4lqGhOtePZO9s5#NvF=WXpDZWYvGmkRkGl)ZISl>Zv;O^<*ubjkpt(t=7e zl$3&WDlH%=rQ}cph;)fG(%p!34vln&bPo+f4b6G@?S0O9*SpSp_J03ysY_hXEamxr z@9X|t*LCKNVfvB`c?lc^abH{p#n7r2{`YBLQXs$+)u+3zhLn^?mt|?6a*|7yU1_44 zFAMVS**Fw23`h2L$v$JWIzY)mTUUs{&xeW65nsvn7VNRaUR> zKciA^rhPrkbD+&GJ|cyA|LDyvZyIA4fL)|_f6OH*wdoDZT>sh@HuQ(LiDoEfp&Am? zvrlQH*RwCy6Lvzh9~Wl*X`MC+Qo}sUfeQ$Vdqq{!Bl!RM^td`A84BA3T4aMnoR|El z3*MINR*lV$?#@&f`e1|9f87`?kE%#yTX`LA`)%N@11)}V4i%km!<5#a&+c|mC(eB6 zQ_RB79AWyBbdFAgE3x5ji{B4Uy?C}?HH@Bp_vou}YG0{8bU7LcwEO!odIOC(bcta{ z?=ZtpuamqE5{`m&{PhK15V<>ls>9RLQP#vve3Sd4DTd%}^Gc10m0AIFXL79);N{d} zP4#$=yFITg;<9J0Ji>MYQ4b3626`eR)B%GNNr#KWpCj*=Db&za5|o(OqetHkSL%fd zI?&>OsD0$2tL98RShY;59)b(?E?;r0L^ZXM31i*D=arI-gXjf7YR`=N%`_3RYgGb`dLWcD&U}=U@OD2K;i4 z)MRZ4f8*xYe6}JW4CBU_oI*?g^Yor>iKA)ZR%005IsO@&7Bp$GiF8 zn?dCrz;RT{)DR9+y`JI3*>h^MMqHoL%bx#aT&vH#qeS2?yDw|*XdlL1p$EsWbiDJQ za%-I`4ruteUTRg^jvfA;)KW$7g<%;0q8!l1^4)DYh}9CZMZoLC5T<5la56^i&o4t^ zJey{w?F|%srbUw&^Xpal;YxgqsWFzT~wPV88;qQGpCnvzwFOU?-3BqiiHbRoWrK?!nj_z@Q4vq8ES$Mi9AnyEDr8-7Oqgv@WzLhgeIik4oGguxv% z!sV0pTj|#cQbv4yqUI9J^e5u{!#a4P4eLs` zniOJJG^4bO`JwgoT;3+*PLUqwhwdMPVI^NAh8BFIxsl;?{J|p$ZKE$>SI67Ebm#+& z7wK(J6cEOnR2jDd08wG^;>SfJ>rb)A#`==!c|G?q?1b1xC@9!|+S8?|rR5u%e{*^D zA!LjPaVho~st#?w`gt(*+dQOaKs@c3Kh3mD6F1%M#=JPysSt;;*ttN~s!;Q-Y~}j7 z?B!&%k)vNclg;G`s^26LM2%jHoTOGd@7OC+T{|Vy+GEo+4}WjN`eBm75lic{Wc(+_ z-b-P0_UHQ(n=B`Ap`|s_vB>W-DX$LNkws?nh68AjJUd%}4#hOPk*n0>QIDLZVJLWX zBs}9lC#OjoKq5ZN32W~Myt2#ThZu{$$Bm!OV~B4505zWKtwEeVw=w=GZ%(Qq&%OYD zZ*ASdEC9RLL2W&+!dGIYmmy_h-F+3S5kSgV9@A_0g>Eae zW7?V64LiiRuco;T51QKi@)f1+nSy(5HUlHPFSr{t#`9EGhANAM(av;`ym-dtk+`sb z>d{U(!7}0R-$DLB4>|ls?m=wi22Kxf7Mm|mY(H43>2Gt)O8qE*3-T1V)&#~k91g{ zA_cv9`A}3%#NCNL15tdDu#v(r6X?9}^=w$Vae$f5a+Res1OQc@t_&1m_%2XW zh1NOmDl~HPL-{DFP%x|UA78Y_8^YPGUwtx+cfBVs!s3N%*Q;r1d2ifhD>Pe1&v`@s z_&g-^BJjuqYv9%9c8xodVV)XT8pH*E&ESSM-xrBM+7v=|F!4@kOOGlHu|VNLFQ5zh z;=do`_FaZ^N1Ib0!YTKev8+3f8kW?qCSJhiLY_g_(;#&al+=9+IR6I=sRptm|JiRF*nHaH z)x-CaXj+*_&^+eZ?g@IDFcV@aBjjZ#-`JHpxR7u}aPHn+*TGc^p|SLEc}8aFPVI%5 zjoM86?q_G9JQfRk5&Vhwoq=Z7j-Y-q7TQ*0yk#0)6!0NGt?7!Pu!SREOBHxyw*`Q8 zwkJz(a^{dd0-i1yCj;XMKs?mEpOsRS zG$6Kr++8662)qPVvjS{QfLjG|cU>ExEZFM*^GglE@OzZFG)&Bz|9OWdNs>qJBRCI} zo`bD~QM^qxZnVuRu3zGoM&n?EDF6_&UJE3BeTUD2^wiNYcV{eOPn+L*BeDcTLrXR7 zfsRoYmcw&REm-t#G1U7^S2*S&(RKaaOts3%=4e2$5l}WmC*sIfV4qH8P^!2@mEaYI z)dy@9%t*;5&B~43!m&OK)FiV36fve|6y1|~q7ctt?K-C2g9naSin)Oje;i&9iI&rD znwtLo@dVoZrgr@zk)yHpuE1CShkHm@pgWb?4b|KwInjMH!UQ%xtI>CLZ}v{_4M$x% z)MJOiX~GT0s1fUG9(?oznl1i04A91JI1aTfQla03p)7H2jEo&r@}4IcD?E_xc?-pq zUG*6{lEt_ey5A-kb`t+^h7-<~i6z@#H?G-bn3!!&tuv>!8i3HZ9aRnXzhGXL4zf*6-HT+vO2+6oz=B)_P7 z*IGTdlf3gE&{91IZP(7QD))2x4Rs);Ns0)%k#E2t8(H*?6!=KKAcmLhdr&xOmXXC2?ZK`}ev$8I}&>zuFuB z#oS!_2&Q5hvR(Bx4+5IB9u^p0pcfhzMbWV#KKZaXZ^*txw=>qEbK6E2IXEn@aEoMhVtdtLy=j(I>@;cJ;^#8_Wp zjosXRIR~oaUoBO6_44pX_DC;KbC=erJRP3XEE0-70{x%PtLh%LOYBd(5AKs#nnv&@ z*Q0JqZ>Ox-lmFN84-9Q;q}=a5d+lB*DT#9QxGvlrvGR~Da2AUWE3m*VsL+I)a zDNcV+q$^Aka912x!nt~kS~`F=+(hw=+7&+X$N}S-VUoAJLoH*9)5O~`x4y~o1y5Oz zTev*A((6FxceY5+>mIEuc-r71Ir~*eX)GBqH}a_UnZBz zZ%)xG;2(6oz*OM@E>|rrofu=$p(iY}Q`9(k@+5YIyD}BO0?~wCMaxdc$f{k6`9=wZ zgaZ9%B9xDmiHuk>@aVKIK+TaLzw4jx%rf$!G*T4X;`$+RF-KQKMa!Pjm%Z^3Hr?C$ znmD5yujtnz_$SJRd?P{@56&#-Yuf2iY9>khhbv)3N|N{1RO-(NGoIO8kX~OnTb-%D z-^EF4xfIz0Jf>nC%Rmt{bMQ3=wE2M`%7j2gnf`UOd%gi3Pq-B9SME> z&aB&>q=MY~K?bzAXu!LtrF(cVdHOYcY^KjNV+9lFE?n+*h2uczK+FxdVQR?t%4gO2 z>D&Bqc79&R!}9F3t9T+#TQUuM!U_^Y&VMd}6@5(WCE7yl-k)U265JGHwn*o%^3;Du zccv>tGJv*e=?b9HP=*k?gRw%l zo5^r#bf7Yra_nl}Ul_=>h3;uH6>CY61C#Ch62SbB=nQcyJh;OdRwi{yYT28|_5zxO zCvXRy($%l&ewuq~6a{R*T)5yD=oT4oi?uCMcZmIHsL#i20XVZXb>LqtO_Hal#zZyV zE~=NR@bvCg6bAP^*DAS=)27P*5&Tjs3!l3DP%+YeYUhz2br$=i3{FSkil|E7oM!c; zZf^0tW`4i4+8KX((hQ6je&2!HO>AJ7FE@n_Kvl3R?DD??`$&ozl6>YsTihE6!Mbk> zI5imN5pUvHGh$zj5rwS300>}FWocWtQ+;^^#yYA?jb$-W2Th0R3 zWnf3}!v2xoR3RutB-0QUS$Tg6^TSdXqgq|Mv_Gj|vuc=XW;b@|du+dVYB03J+4x;NkiKa>oYpq%f9A?y!zOqCb7)}Y4g9IO)y=JHX{Fh z6YEA@Z?|CBb1(;%fW?sBIWJBMj9H%HC^aMp>}_#Om;cNVkhp#{yhFJ_!d+_IKUFan z-j2jA^BZgQvUwz)t*4TK3RlSZ>3pNa#}&;z`Gi zxUSRl{7eYqvbJX4-bPN?gYERmko0)vM9}E5$n}$ntZyKiq6N@Vxg2jRdz3R)gd<6o zpP$)1Z#j8+jo90tCltelB{fvCV~U;~*Z}*xK0xTM@m&hkf78)=Mode4 z$>#axnbpg-AKW8hv<@O2^+y;-?ed~*^E2cJLh9@3<2T9hqkw3~tyNMPFF{uTrOx8- zz$rX&RRASL4*Z*ICWh?{e^~K1PX_hxB6Q8DW$=jhkUZ}9$NWt=SxN!u&4M2-CCqtI37OImJO)T^c6h{!BRmm z0uO;)YOi*^W&BC?%Aj~8I`Fv77ABd`W~Mm3hF8oBMQFyn7{Clh*GKv5E1f@uxCsyY zivyOB?SHNeo2duaUBe#{YJ6x!!}tBm4Lc`+{e4q~sgWL*xCcs`oV~7dDz9EKHBAq| zuEo|AmUX6Jj5|p%O4MZNt`r~{9K2Fe%FZZqg93NDL;HDfn*(7A;xi)%j7u{+*w%W6 zi5tuK9fEc`*kFX|HU&Js2TSuog0lj0$#vmE0Bd0!34xe+W9PAUP{ZuKu}CjMZcG?g zUz6gU7<}oVjHawfd!Rx=_1rk9O~cJ@#d9vV?FWd<-y1YfW0Y>vFh~qGmF@JFgoo>$ zPKb?-{kA`i|2~n-?U!Y7(8N7<@I5g(L3VSe^T2mj+7>e zi-W+#d=#@3E8l;1?bCBORezk0)au&@Ul1=M{huKZ-DD&GeKjDaX@=;w+RP4qElM8y zS+OdVVd@W&<$ErWvLR@7*4VOckkEeH^mBoA@th&{Bd-KdU+{9%d4FE%IR4a{IoDm` zAu1O#c!IRBAh|scc9Ib^e|}T;I=?+m>&Vj)DD!Q1|3?vUo@GuIt=kw^qj1_8g3H)w z%}NA3+dqJF@`WPJE!iX_eDQFeHJv`+vxr8`QhQSyVJ>OfI(^p3s1;7KMO}ddC0w=y zWdLU$=AG4BZN(}%Z4qy}@1#DN5%W6%(cwEB*j85Ji=)Q{2gRtuX1*|5FCMgU&h3>e|o zSRB?}8L*drl>UFUiToo7G)oX;Uh6gNrAyt$#>dC!3E0i+oAOmTTcoek1dTK*9 z)pI#_1jZzA12B*`nEc1AS2wLG+V_uHub!L8)2267QP%MD-xo3{hP6fuH+pDOTFrz9 z`h^}llW5%9+Ybwqqx?QW?yK3m6o=iDR|Yrbu2hHNC#$D!)dmbje6CfqXo2QwI*|M4T@o6S^1H zTz00UJTxi15cNRAeUM-(z*(S9uyX(oaSWKVMOI}nJ1N1y@!!!#jx01zuD6%H(-Mx$ zfKz|(!>hR^A~EoG$=Z;rnzt}T)H(&04^Kt+)Bpp1CoT+-DR@Ev`2;L))J;c6tAihIXs?R!<^<`8AteRMWsd_V-7;(8AVCt!72LNqi+q zkA~lV3@uyGcw69mwY7BDy=^h^8;iT(6>GU-l0Ap ze-f_qk0qEjk92pi`JoLDmhtgYjHZlJV<)vR@IBtV;ft9WgBTCEE<1dZe=Vbzfk|oY zqbl1@YE%)ypZ%jwOzvt?+?tt>&HIwla)@z~Qq_a7|3@vnc~mjbWQl+3m-Y5j51l7J zMH;LQ^r9s=LQy`r?=3ae%*0slIX(=k#wy`NhNl;?GfX`c=n;;#mjDx?`M>pY@>ulF z8Ntg^2!g{u5N6l9h7N}Dl;LU@R-T1)eP6-T&|+t2chWvbT)t%yeB$3Fn;gW2^RjI( zv9L6KOjZ_3%xpaVG&@<5eRFfOz4UBTKJK#$;9}XsLg+1c_|_ewXQ>0L2o{~#`VNLD z%yhM7y(VcA{nk$k5b3BuM`ES4cM?5Bz1^3Euvw>uLlJ^~H`HUmI0~FircMw5|NG+W zud1!=N>$hX`+mqOU`gTtDAG4@I0OaM3W~(XI2``fo#O?uCPu$=&)oI^@x$FDVNpt!oM z>iQdTDDrEzweUM=b4_!08ivCqzx6qK#_7tv=qh2-1_kWDCYRQ)k^=(j8wWUYIZD}d z&ShOc8BG{g3cBa^a1W@Phd=B;Qhdyg*f4Bd&d|$?9q#5}uB!}=c%x~f_p7ru_Y|-M z!6h6gBM1Sth6w)}mb%L3qCP@5$a8LunE{PJYmKj2zpF0@-85K9Njt_Cfozuq!6Awr z`o(nIO-a%SPu9bgoAApg&_-|hn;r#-%2aBGAsYr?3@H9?nos=dEQP|=tp1hBIE5t1 zOg=n1+9ZP*4@GDfzf%)RY4etL7H~hn5N89SetrM)*E~**qDNXprJ~jia6yfiA`YAI zSE#Ss98}F857uvC2=pVIyA{XQek37+s$QAtgCG1cVM}UY<}L?@(foB(%vd6FbI-FO zf=2j;Kw%*r%{zcZ(jJj?03bGI#6FQq(gE*plTA)dGZV~+r~!tv>(*0)OE&03zEDeB zOg+nwqys{-ohXOZ8|!&QfUJya9fxU?u+7!`?7HZq$5kc|&}N^-Sd+i7XYV^62gx*w zVMeUmOMJ^t4t}4Kig_uh8YgnPABwvR=(f`Y9KyJo?>qk z2e={vXq3m^#`GFmL-SYIf>GsmGekh)5OzZw(K0Ra=bA{c^Q|$H1Xy0~@RC)YGNS7T z)~Pr7!f)IddXhiq)+Svfx4kY#B-}2C4$Eb^P=$uOTn0eWpS5Kh3Z)ke&-fjB!no~$ zF&{#={}^lOyd%waCCnoajAlOo@;<6O&g}`d77!8{4H?a}34qK%NX3=*@D6~@sPS5E zL^V6Wt}0)PCKN84WH%BCJPpN5LtKjnX#AOGFb`y=d(ggbm85Kl4t=%D|2)nC{Wp@r zOlZ0!sLBl!N@q3u)+Qi}{J-ENEgq(ERxQ$x<5KIV0bY9HxNyKxq8$bid$)NAcdG+R ziE7&~|IhBU9On1}Y|WnBQk6$;lcSq5NU`zAjbX7fcgQoRBx1>%?5~K_tVc)a7?B_9 zswU68N*Nt+y^I+6LlK3uD2W^KcMRfF2HMq2F-Bh5Sd5KrHqeI;s8zJmsf`G#q&`Yt zmjGj-#{UD6jO-E+&}@Wo+D9z{`dBUv&7Loa>QDJ%{o2*}5j(@GAroQ*h{z<6*sT~1 ze8>nG$$>^>$9zt_P0;;}Wp~JG0ITvUiqQ4JsxK&!S=wLq1}Nhs=T9a62?Fv7OfV_c zylJIPfnWp}2Qat0zAi`&NDD0eO34Q3{AZmQQd*1ewRK5x;~_ZxJJg0xI0$&5>U5tV zkOwXkCBXSer>qo1fMt}ou;4_u#)miVcXV?5JNUVlu729-?j)tLbKy?weJ#zD(gJJ_ ztye(oL|CwP@$yW80Jliqw|Fy321u^!R}(2Em0iGl^%z*99|4a7$Oeons>Us_t|lo8 zV_j7$@SU!}(mv^gPrwNLOb83OR2fCf#fGNCDT$h87jf*Y=3UkKig=R2G zEL*`?yc{(tWce#W@zhOby~l);W*Y90`ao{Zfpa$&6unE?+HiXbm~?^NkK2^P0(yt4 zFn_ z!*ocpDs;Z{7l|$K@$^2Z4r!=BUsJ@EwGqV`y39FL3x^Pb!$d9r^uup(g9m%whjh8R zLYv6Q$n+1*Km3-Rh)G=kB?vnB_3!{leI8UFt~<>f$Nu^dU?HMY%K(nEr13;9!ywev z(VIx7u;GU~feJDHqphOlz~*NwLExRS$TpW>*?LGMqeD&EQ*&*Rpoj>w-X89-rJ8;< z*`;fUYog_L%e+;Cy4(s*66ps@Fw9%ndGSj$chzSn{2iMDnXQ9nI3xh{kummv#(}QchN;k?S$J4h+GQY04 z)|ZC2!66}RSAX9QlGp%$nbI?Gez|zkCko>daX)*n@^F4XubVaSatC%OI8DHq%4jkh z&-!b2#<6R`?F_$)K^=+L>yME=1HIY_!n7QU<#L9qiJ3d&YaF^7-XCda)UzKs4^bFT z=Tkj<%>jL+?uX;|t^fq%o4icVRn`}})l?XWj(p zyCvQ^Q;a)PWxk2!7K4zC4MB=hg&qzzXo*OarTwB|2BTNK&&D6qOOm-b0J7(Pci?bx zDt0v+HS!f{@dhhkUm1D5lh^H{*7QyL%HvHaBe1ilSlX_ua6l?^ELWEru}(AlOor{l z*A6hnL{(v(@ICqWWTlKVE=P6ab+SSo@-kl#EuWiDGYNvH^%*?m|@e zKD#o_AP;idNz5P6%l>u7%jbf{&%EoNXR%0BYkfF$)3=7%28VrkKsJ-BUbmnyLqh9@XdWD=(CxzK;b(AevO5kl21*9%UDUU}K7=F4DXHZ>UfH{3NL=?1W&#QyG3ww< z=8YJT+wcf5Z?6iD?syimZ*&cwU$?WbD6=#%IpC@V_@>hP`noQV(D$x%Q#D`aq)CQH zgd<(Gd*(E8g*T%ST3wMc)wXA08y8O7LE%jY(iu`M(3GIE&scXudcx0!5B+om930C? zDNmyUM%EPAL$$VNg~1`qNK13rC#=fxgHA$FgUZ_M^xu1esKgdQk%KGGIlZHuI!V!( zXpk3pkHMHbF_^SBU*1S>0XjOOyp!kqT>bv5*Lo3Cn%AhrO6ZF*K#-U12C7jsqo1%Q zrwlCUAKMM9NL*LcZDfROaSfzi)#akwO~ zd(gA8kCSXYR7CgUd6yXzS{4}QD2-Ix7n0=->LPzc$2jzymx~O`Mko*O{Z>D#Pd#)Q z46tBig13aolkW1tAjopsh3a_GhXXgEqK&?F=9>-*d^2X|uFLY(%1M(Zr{`}0B0EpOSLJAXo5j_yFEY7cyAp`O>f_fj2zWa2k1RUP>B{QTh1a0)y`on-4hH5K5pd(yo8tBr+xJo(GjnXs9v2jZ1QR_Yd2!9O zF}leCuWnT`<*^`jyp<)tatRk^7@XC;**SSeqm6^L;A$y7oCCuY%nq8h)8*tA$ zN)^BQIs;f;pn%l`5Y%}3ko_xQ7A4@bBJfE!f>nTYBU%@6EvAJ3Mi{{)!kp{Ii+FG|nx7{kYOBH5R&2mMlgRH; z+{$*%sDs4ukn~m%Yl^BtoueAUjoofnrSXP|iGUX}R9=K(8b2>;SqsK3XC((jGp4Cm zmN-`FT+Oz=VG=A4Ieu_Ew_?8m!b5ic^kv7Yq@0Ki6TklTt@~P$$AmBe-^MQcOdu#o z2B~}&yirN`c8L9jg#_yLa1t0|_>~Cr#<&eTRJfrgNeOEESMBw=Nzyo@eM%nV62(+Y>B0}sa;SbH8Gj>x(a8jPG|3=?z!FzXmot5+xk_L*`%!9 z=!B-4laG($^>+5n@-V_qf&<}XZ=Zb9*O1I_&e*UI4-R0B8{(aq@;DooXM6CIw!Q7Q z5Nrqt)QcHGt{&F(4Gyx13;17x71K6pizpj3EPbd}?p2Q0C7 z+UgQJb6F^LM(bAX)K?>iqwW4^43eFk08`@v2c%H@R^crku@KeUp!ZibIG^t0fQ{g5 zvcX?L@w56>f86qr)JnhgMS)vV^RGX_ZfV{4Eo$GSr7ZfV$2A9{tx8z8Hdi?zY?B38 zZ{#|~d%m7(>*xRpOq#DMvTEYl_>9swMNC>{2o}mM1c$FLUj#K>5fIWO&$`j0Q0dMY zgt4~FZh+Y-?;(#0U_2@uZ;{5Bc+A$^@VSdtvpu%a`q}yI{8=ol9P2)uHS|T{$vY+F zeogti!N?ya!Yk+6)sh>J zRLuC7)+44pP_IP8cXg-jmi?&rD`%bxvZRR80{cS@AQAD>#JaaCx~YOG&eH5rM17u& z0M3s%4Y{SCw^x3aZg>%0@scI zn4j`phS+O+cC8)Ays*eZJ2B$n#sjw5)Zh`L<82U^7?IGv+OnQAG@NaoaaoKJt(@PK z+{S+M&Cohwr*{E%eaV?Td7XINiF??xGH^{UoT?Tyi33oLZb&EJN522f8iNk=TI>#h z(R}?nXlt@Gb!#|NJ`9b^$pGX(`P?LANoUL5Yu1(4KAZGt~*foS8@M*$NIX?Du zcrEhkWvmMH{0C8V(^m;}KKdpCVR5?k?iNjELFpBj%6p>H!^qgSP-^J9NxYmq%*Fb; zj}&%jK1;+Xu3v0~FjPtw(YlNM6+fAdbMq|t6OF%6tzG)T)xZN}H=Kc+{S8S;Gv+5x zO;h0;Kqa&+iAqS|vcm-nEtq`z>*&~9QZ--Njzg335*OkJ`SHu&3h?wSQV>;#$t~R$BWq* z*dOeD{{&f@BFW@W5lDMAIYkl7BQo9<-L|9|6BCnlwftEmTH}Zylh0g0Nmfov%L=9C z%$*EaN^lDf4(?G>Lb6+>AHF`v?Qz$hz7M5S#3(64rvEELa)3GB%Dhidjt-D2Z~`N_L`A_bi!iJ5Gx zx8wwdZ--@hMynK8zK(c3J2B?6}(zm8I%M6SfutM!(u9#IGh&*FQ><7Ka;|2>1 zE@jz6mwVTYm7o;;ufBg@?q7q&7s>VpjtCDMMI*TJ+x#fGxa4I~`xqfZfEPT&-b=45 zHip|L{V^a-aUWPYK@w-K$6+ZT`M-Z(9$s(>m@KTR8J12gh$sI(4qSGvsr<@ssB&g6 z>?eIj8|#V?K8F$P)Ab;_*55y^MoX)xo>e6@>>VpBJcJvN=xH;Ype))mAG~h>A_&aN zg1b%`X4n*!2QbZw<60j+hyI@RSmBNq=ZT=qTile5g5-WaXvUANXBOhO*xPa2mNrv= zxZ*Tl8%3hYb3zHGxQkj;*?KKSuDtBz_S(&5*{<=(BqNC1vs_Z&7)Cc;cf!Nb1yBY+ zO3ndbChig?{f8rWg1C(*ybH<|>p&0hy2GyJG?C6I$MYQ}RuBGUs7EfXH zm7mU-&06nz4ge%Yz&tQJJ{NxfeJf0kz%%=m(`Pv|uI)x&W+@84^C^fdhPGZO2i(~J z5Q)Kk)w?Xgm+`(tWrbrjO-2>@4N1$QSvh38m#Ch}sxJ)cow+-x@eZ%e zx(gcHC0zS??|4G_f?-G@MCD)>D`XqUxy#7mi(#cHUsilar^oS{4{Dy6$~w1%7r`1> z9Sj=z$$lyuwu_I4=!$=4nukA?dRb>DBjF9|k%mdD-TQVa3Rt?&-A6wWOrK2d%M{vA zl3$x@hzzG=!#vE)S4kLCn=j9l>VF3^junaxGvG0jL0)fm1Fm)&W^s6{?s0XVi2ifNsJq~M12!bYrky_q23sCxrImo%wOc;bIAX%QI&CAn6)RndqzpNP^GFpRJIl9@sz#pB21?wt+bLhlo7 zul1;Y;*6I#oN z$xN4k3*Ok>TA*fOGq&{@o1*5ypT*Pt8Qzd(`4nf4;pHTwKs=lSczQ-w=-Ib+nheq} zR~|8y79bS&^aI7?t~JG=*ysSV-7i4Mb7qFC7Z|JxGcs{{08DGo_ke;8;w@@u^CB9r z>3{^u+bL_pjK~d+Fo!OoWM(SWg+ci(ttkK+I(PHkm_-G!ez=5lw=*~&der^!KU4pA@6=mf zoad8eNjTGcpVR9M5%em+f9Ze zSb(v`+M26_MQk+)u-Uy?T8B#;dS0IHQl$R)@sjV+w>5sIYU1GituvrZEk>sJH1aGFmrD1L126(khAZl121)Lx{Q0SK%f(an-NZ_k3@O$!!|8~~7K-@SM41gS? z8tEL@Z_(%L>ceC+jSOvlhn+%nW3< zc<0>9B-Gtf;HmRY(=zFuw!!<~8h%Mmss@GeDH$=Wxmc`|{)i4-0mGoerGcxh^}f@* zbO9FZ+INe1Di0tUK!6VjPOj9!H~1J&>5vwW2~2+_Laz1T|KC_0kp1sdM+!vy*M0d| zpgKpg3}jwq;sFU)2TH&4r~unnU`vVK_IKcRhc^PM=B zgtQd!tdTA)MVICS(Qo8kKG@blC+X)48tzpL#vSoLK2?4G7-Ic;3Dx}~$a%YuO47+{ z^}KogWY3jfiHBK!0%Cvh@vZSmQw*7O@p>ab zsH|066_O1ZEIV9%X4SH@1eB(X{Ua-^Wi+cX`F;Sl&i6hC*Jg`V`W2JUQMdZ9|S3XGF$BO3zQ84JeVU=7^I1xT^8JV{7f69 z90nK+c)i54dAQh^-s$(n@@76{2~v3ujj^6>rwX{$9i)n7A8EzEetZ~RMzL`7qc<=S*}W%d zn0YW#8b`7V>E2d$V_u;r>!Se)?$uUxgB|)jc5pb4&I<=@U(wY^Bilr~xh7z*PvHI)AG~}rlXURe&09F> zXlPcY5X!apll{!*%O2sZI2Lg9ABDg- zf}cuFUr#TM!Z3*nXvCEb-#=N?2*bq$UD`*va}%}4jRO6_LxpZ8IqGlAn#ZS2S61~A|L$``Na zNWr650n~)1U57X1Dep+^29VrfsH&~!`OmhSv}uy|QZ^)VG1Ms}zk2~*A8m;U&zC7| zh0U++eo(yqVsl>mVSB(jcz-MyjjkvDd{yQ-b@(ReMdGr1`1-lx8*Cu^UoCpvsoMmJ z#L11Cj7gRl%zOyHT9VJ`IyUZQ*Ag(44}Pw|4uuA#N<1$=J7;;y72g_C>7D{V-kD9b z)Q0FCs0Fv7X&`1ItX-;Cv7W9nAcpZsOWSAr`=BIGYE;vm&B9)yUBnWef~vgTJLGp1 z1CkfsGPt~oa3Uh$>F9v&&ki3GMW{^>+nk^C6x&HGhd506zWS_+gQ7Ht8qT;d%6cfT z6K6NW}jB1ly> zohuhU7gMTN3}G|4Bo1{@csRIE9MtFX>VC!gFqPw56sBp;F?(?H^7gV zVaSg=x_G)rNCZY-*a%sLt(q!(8MSb`TH7n~b+Zyci$d#fE%wDRGC9h{LlMl6B=bh< zj|;HWWu)4_J}eNmn}_gga~BBea)_CcQB;&i}h}`hWKju~lHnp27>e=5OuLpDuSF z?eBlKQ8~Ra)a2qnxB=R+FFuC5EZD3O%o`cX!R@1LMQZJDucmRU$o;&pJ*RHMExqC{ z7k$BwHqMM60G!Zi${uuzo+e8;zkgZpQe*H7p}04LoGUf&M4`wZMQ>CjM3U@Mo0HD;%1p`lR)Qm`1yMm21-H9_}}x4 zH=<~`61q^UP`j%4ZB^}w&{|fM(>03DJ3&;!LQpbZ{*l+gV1JlXWD|II^{*4!DL_Dk zV+7+({!wF^T(QK-$l4C5so3R2p3!nYrEI~H{v$??;yRJUFrIPW-&2-cNR@upZkk}j zFLmG{2ZWK(xyo1AytOC4F#51{1jly`ot0T^B3v-mJ0dw*#AGp#666~i!Pw5vLD;8K zPiiW)rY=XsVSmpWZ2SLKMNRHY&nP!kp;jYP;Cz{figkE~70ZfpXKO?0ZOXPB(Wt|i z!dG(H)cEz5<8h%qJR?2)k5V;u6MMocT_0^-9!#ejoE$_@p={f$F#5zSB=T2Q9%Gme zIG5O8ir*)0-Vy#Kt7C&1??8_pTKYMSgJ;}SGfa52&WGV(z`8GYrHgCa*M`Nb{b|hO zx7BV){v7NRCJm=Sq7f!dJ*iMN@bm0XUCA0?y{9#mUJ+avNBx5H$Y$WHp4R=jy!t2= zqkHw{hbb>u&+g#MIT(pVI^OPHpg|zxiT)dP)~=@*E4UJgE@3tpo$~?CT#+~W1jNl( z0&5F(!7B{jAKm}5IJ2o$u1B)nLZ$~>78mqnoeth|QEczVm)kra*&bN0PPIBElqYPO z;(^#S5Os-QXw<@0<|ql9r+AdP&)!SXSlJ-jD%VMQCg*&?ZV2iyG)CVUCShx&{{y=L zfoHjs$=rhP+wbj)&11$RZS&0PDYUF0k@_xbHr{^!-`^vWX+s1g-s}~*;wr?mH{#al zOx*z=j5kkQK4Uyl8F-1qSxLZq&fr}}xY~@l|GET-nI3Pfqz6sd%@(z-tiuF_ZflMV z7?e3z#9S+75@%C3_5U8uM=?wmACakME5cMfpfxjAKeLk3kCHVe-PJ!AzpHedvZZ*X zc$BhgNhxjb?)&RnN=NVq>c^FxoHJ8VG&a|+6CboobSwJY z$qrJ~`yDm72e&hACQIhSQvcdWR6`hVd+WV5VGZd^8DuFo4Cwe#Dt z7@Wo1v^>gCRDUi!&MfLu#1d2-=YA#>aT@fvzs$LoocTRozvR%8AuHmQ#j_r%<8=T? zn30Aqr{Wd#q3gG!4)X%`c@XvU_Z^jUse5Ah=V&o^#~Ppz-cze2!o{~x_-91%pnetN z+W!<1FZ_0D(O@E1RrO*eRb^aHniHVUU?>1h%vhMVE?+(dG1}Z)BKfDh0R<}a+O8W`uU98 zZ!3pwlP;9ypoXJ{Mas_H*^k(BoZUxp=h!TL;bvm|eJ?RH8&lDu&WvMa8dPq#;#Vt~ zwU`dFBE}HZp?Ihxg4{;jq3U{I8=Y>$YB&Q!eMgt$7_TCa0m^2!#W&z&Vc?jBb}26O z_T!msL6aGdVM7m(tbx6pmwo4;)%ja<$}{_IYe>+A_|*|o#|=lm(Tg!vWZ}}KM18ZT zHalqZaNU}-fA{iW(PSTa(9Fm*YdFis>GhjG$SVU!rAx9nD65=XD?_Fl_YcK(z8pqUt zZn!aL;DtQhDRR#=HDJg6&1jAx(>MqDG!lOX@k)=-W9q7mpn2+I=g1e=L@okS9JS*R zv0Gg!FdzHE!iuM65zAm6i$efm!&6=CI(6Yt-?X^qa3L%PJ6|**1Yn76ErGu^AMyu& zf10MT(df;wtoPd8pMDaTufnmQ%3Zs7v`TmU_q6TY zj;Ec~->e*ByQ?{R!^*#xhND^jXornzoB9363e;!?=4j=k2^ZsPw3xX~j>>4_JaW-D zyK#ZDVq-*p(kj)(!Ob91KI6tc50r|*vu<5ax9MbYq-WJaZMBQm5wPAJV3Gqw~mW)-NJ?k1Qpo`f`Cd&h@yl+N(rJgh;*Zf z(%r2nDo9F52q+-k4BbkD(m8~5HzPUkn!V57;(6b*&pzMp`)_{p%skKi+_B~usgk(mrTKieav4&pZ&+gbB;9I-{J`#YkfVIi~UvumO*j47mvz+ zy@D8jI(<1(J!kog&iiK>9G^0rCc5pyJNNb7|4#Mu;x?8FcRq94dgozWYW~c@L%NJw zKj*>lNFHtRGI5FY7n6NP9s4)?4Wd;`x;d3;>Li9U-{MQU+G2+Hcom*6Cp95X>GGGQ zcZ`UT6#hr4=-ahtuYanq;hVFI9{% z%2Ofi({lS7XyftRl!2tjLfbu$RJ0_7t<~zIM%r6gf(D81$t~Hp&Xf(-UpIH{j`y2> zc%lDCi)QEb*tmB}Og6kW#UJ0vzclTO4`+9h8nnsJ(7u_=Vm;l%XybsY6xxw+iFIC+ zGz%~gNYN>IU+!XLGTqG@5aFXOU!B2z`un39j~6q2&yJO|AO^39U%MRIX9=Cp@*Q?s z-f^>j=n?q7_(Inv?=`Ql4qZZho>Nl*j8TV}dC=k87+HySLI&Go`K6wqvm8iTDkOSv zDyyRFp35iM9u@QaFz6mC*Na?b^JwShvndm-?s>uJRvDR>d1ah=0QSfBf(BvLP{%aV zQ+<&?zh`U2zg{EiV9kVMZY@L8NjSjcJ(rlz*PCcpvnXyOitGc4V-F^;K7Nf}pUEqv z>ycd^UJ|q#+N$-heen<#){y?WYckTswwtC6{a)gIaB$>D+28Fo8(R_r&OE-s%&E=Y zZ%DE%GXcj27o~%J0o$3l!AgwColQ!DD(c1`$(BlD9OAwg9(!vC@7HjM+m-G46~^l3 ztZ@+!`{a-kmDAcFQ?~bohJF;Iz2Cg{SP_b)lUqAL>6SIQ)a<|B)M55XC6}6I=gt^c z{&q>3;jwV<;*VUDR>nedJ=2?8d{2N%%FkLv>L-{|J@wVdB-Y~D<;p%Z)h=~V=jOnk z%IfDA54CaXdQ39hXur-*h?KyS!P^I+M@j(~m-WikNa@Gwt>R zE&gne!psNg9=n01kwrIlROLvTL7s(=Lm9UqbKX<0!D7W}-JI^5!>r6wGb_W2!|1`> zL`7TP*+6tc*vFf_^D9&3?^TO~hrgzfopXupjY6)nk}>1E>2^J5aJ))mKk>ek#Wv?ax)xkg6_ks}{I^Q-zMh?qad@BElqtOHHfy9x+_jo$QrO8|^wf7>RN=_-SsOg^r$JXshA=$C z*{!Mqjk`|U)+0xUUGG&y-qq1|xVJ>%d)^a)d;I_1Dq94HRD!=qA>hJnva)Am86E$+ zyGiNtz*5=)Myzn#RA$stZrLWgKrKosA$cq5)BA}xQcY324@_P1bI7yTEzntg`yyl) zWWEu#MqFjod$#3(`u@dt-m%nUz%X|=ZE@Ls3;if+IO&apuqf13w|$EeK3zt~?NP)% z2n9K{Mo}vy=J;cEnh3)kzu21AV2*J%L?=>qFd6ySg9Q2f<7PJ5L!LY0;1`t`MVk-c za?&*K-SfH0y^x-PqE{)gHKJixNsmC<-|ELtVf!uQ2nPC68W2FUYCztLFBPqM?8T`pJL+kxJxEg z%*+m+9O0ZY9sHW&!$xVeJ21~NpY8-ML{Gj`Lg{Hv-E@H~i0gY9KDPVymk~Ax1?ai0 zk3>}wzq?*?8aQV-AK!di=1w}g zw$E_wJEG<5@H2q{AA+icx0z{aZ~}-1rtA=Pzwh^h-R17{I=Gx$zK?EVf{;_D>sXTl zfo)gQt=zvEu8R{vO5s_Y7*8Xm^t;JG*)5kt@}D*^?CjGQad0{D=WOd*tJNy1*N#3H zg2vS?XOxO&b7(DCm1Sy3QUvBSaoQiLL~+K3g(aosPTXH1 z+NmCV)oqziYwv0=K;fOk@=7DF3Rjf75^PUu(=r;>6(=N%_tDZmSMFf}>98v)X{?&a zbR_q14_)S)9>$>^Qnxa&Z|L^0E1IUw(=%ZAC_~$)XTTL%R=`~;TR7jCdDDb#=0Ppe zb;a(|5U){S7yzuf{*q79m9#z;e8j)7JnSM^WqF|o0rJ`X^5^XFle7JlJ?>tM$9hd>ivaFAV!(wjOWL zbsRgFkRb7cS@{U(+WMV?kl4YsSj=uqrEp;zcDoe@t8;+oO1UhyEV%^sdPJJrflgst z+U*>@YTTH7yLpu;=2WDsQx@r6$Q`lWp6gCCq1r3Hlp6Z@%G(i~h$ralm0{NdZWC4Q zRfeFMB0s((=FNT`?{n?)XX=4zWx4*!uY?T?BjwtZsHl5qWlBE2Bfs3#vz%PpZTvpj zEM4cpzD*e992brE^3k)88xnRL7Rqn~2kQ`0o^>InG< zHUkxNa{M_WrxriCvGZAfPSdiR$VRWXZ!s1ptF~X}%gYVVxSM)QDm+>}=j&9O>X$S> zJ8Q9Jo0t1KoNVi8ZzQdzM^TT!+FS`?p>`ePe-`#wEkHu(HCib=Fme@=D&x~)1znIx z=`ct1DU1GGai7KIdL;1{dgKH->r65*ri})3A4!`nE?bQuAH)7_%{#$4#!X#TJ2vIp z?RXQXJ@e~}W|LFSRq$4Vo0ObDtL?w`Qr93~GMM8|8Zz8aoF?{W^8f3Fr3 zVr-aZ*;Zh~iKz9NOyW&B2wq6rVc@CS_R*bKf9Ce$c<<|SS>Fu-kfaALXJ)NF@48Nz z?!N1VwFFVh1rl)hY;KiLOjcPY;^E+{-X4MDRgOF=Fx1~pEN;2q6GvRo87U504By`? zEPlAZ9KSDA=dSyxvMOI6m-7Ohx-_EBCU@QkA!E=>Wb-%56g$6x;kaW<&GLN+ncht8 z^^VI+y@JjgGoEgrj}T)BpU&6n*7B`4%u~5L(X9z>RIV+Qma{ ztG#-B5zg2*<{mLE2d@uP`Zy6siL6zN&s#3O;>kDd&-IL{tA$%2ev7UB5xs<|%ZruX zbD7B^-F3G?a;*zZ>;`HRI`vzl@aMn)*e@d-Iw$rYl>eVr!D(|Z06SNFY|QmmJ$(D< zY|W^9kM;U!6Lt)2{tm1(k!d+-ImBn)q^jSnCepQMn|Nd*ylhIP<*=ufYjR7YROko# zn=bR#{*F+r81Djq13$9T>po&>h9Hc5oTam8CfR~*rPAZXBr)Hx9R|2WVi zoX?|tKHf!mJ;7U>BR-(;d}SD`cGRopLe*||c8rxj4=uhUUER3)r60QnI1x`h5~%fW z;DQ#${w!&faAjG)TDX4I(Ob)5)lucdfzV{Po$AUYujt?Sq*!2@fs!6UR!nZg;3?vb zi?tGPIZwSu7>d!0d7{sU) zWP=DTQR3!bqI1X^(&pLiT^b_)2HeBCauTjy**FoOg>U%(on!Z3ZXyy#e;i=K0b+=T9fH5jYXJuGV}v{>wD|&1n9A8i)wCk#qpX==k`zzj@eyoiS1^PlU|VSP^?V znCbs{KK}T}#Ti^lC{+V4%q`(&YP!EMQU2e?_n+sFKClWGPmlD+M9%zwIjMhh9}#_$ z6$nTK^l6>(4}W<3mkA)%8QrEOCp$R9i})X2mYxMhW&Pnx*)M|RCt?``--a zuQ&Tc8HrS!_<_qw9MJ!fiq_Vy)fI)q{o>c3ki4rh6YH7rlh;zXmJ8h<|A$4nNDsq2 z(eP@5^YA*xjS|AP|1llG`0G?0{>?9Q1Q)!%!JR})IVpa5`pcVOURpUw^_~CcbJxHE z|JlZCHT>mqUPFM`H)hZ`{}&y7NP~-f!2U(R#)p`$rvgkwy55}D6-Bxc&p_n3c+yS43B{@K(eKw#}9)lK{K z%ixkxT{o0z>Cx;{QBuhCsj(mC)%o+-(rdseX>ZD*{^yTnDiMh%tV$o5QFgr)rlIr| zRoALnfXZ!$NKf*;hcuZ=Ij-;D4<79AmS$*{n+?9`=;+WYFz(iRbB=3>?qKDZYKkIr z)P#vV|11-a$AN2a%6%3d$n_ohaeKaaE;Vf^TfbJT*m`mZX{Mw6evkLX6V&>{kq`ZM zZWYsh;Ij|A_2(`-@ey9X#<7Rb@Xwd|^U8ldN+j^M^_Kv@ceX2Z-`~kr)nEPoMZ3~{ ze+b&8QE|%OA`qa?LdfJV;Xqy9qbHg+N$w^rocMEYNP6LTec##0w)yv^_|FR!=!5&5 z9coat@=wZ0O19e%`qK=U4;S4V#JUoi1=iwb>vLb8o>82fgx((xE?Wy$RNSVPBOaJ? z%>v_4i@ayYi0z^5=|_vAI6PW^2gHR>OBG}!j|K53onKy8u|M|bMt!LXuV&?9+;{b# z&ql*TujC_~(1zLpGFw@+Z!}LB><6__S>QxauxS+a=RMxF7Zemk?Jrt**kqNhz4o6U zD$aZH!1TpaQb%40%tn_)d6X4kN5Z4J^>ZYuFp^bg!#c z0Cw0?{7>k@*)*r1`rWuxDC^`vz7bjbHK(hcYoR)Jp$v`UcAKU4hAN)@71BQQUCBvi zC^D1DFH>&w`6oE5Z~gX8AJSPfW!_y|nrZ)-2@w#Dvvm|L>?`!mnOemiKzbhz<U*UdGMbXaR-Deda&ie7qZaqtB72)|kmV#;>H`x_xZVt${dU5Ydpn+js@yMNcP z0xzrHBXVPU!ck0{_^v;-)%C}1w$RAI28yFPi2FMCI3IYr4grD7!eHT7B3UmFN(Ieue8JY1PX%oIq~sZoOHAsZCb^PC>U$5cJ@mPpTAZES4Jl#Ail$hiHK zqDK%&$4gM=Ap4fCNweKTU%RAT7&LzV%F|jo?aNVN3EuY#UFf4qCHmsgr-b>h{aV!0 zRM?0*e=LXig^S1}BmBG#*~?Z$wRJ?PTO+wTNxA`wH@J$P7RL0K?{5tb#D;_ql}I~E zi}C`_y<*lQj9}b#9<9Q07=OcKe6f+|zM(vHeLz7z%SIo_xydN%#nplBoBJD`1;*ci z?Cm)&t<}`0y4^bvvh^gO_#H%^VshE zoZbl?Ff5jc)Q|irmVeqm|LGG`l86${8NMzFQO=;25M9$(q@F=iETq&q-+YyHf{a;u z)b-+_X19j;mpbXHcre&Bt|o%y;CBX@Blq-_Vt>M;<}h;*MBJrW1)KfH35JKP>S;2e z@%0kafN_Ai&5{d-mC$2Y9~8-xEJi9c1jX-opQvg$ zK$`TnL1;ki8TrF{e>({McQ$cD7q~PPm7uCR2o=~lC+sqjwi^kI-5yX#ZV|-S#$K}{hCOoLusMt^^TC(b zC6Uq`2p;BTGiXiPc<3?w;z8I$U+fPA4!U%%o>Qe)*pBwzYeG0V1y?0D+LL%=( zkpb7D<3+Qfd~qHZ-u;(gmo0VLch(UNP;jVg3`&v9eM3qpo-#{Q%}6&(*S+%cJkE=h z`=3g{*eum`-~J*9J7S<|EAocX_k?RNmHM*VaEYsN&P34;HMx?p$k~E%Zx7PE~vI!=k~jQiob?!^{PDHQiXq-Nx<0U3@zr6M?ly>KZvV+mDi!ka8{YWdvi zi2Dtkh#~5%7-51U2?Z&cy;3-8s%euAMbS#FjdLYI^GdkN9fDhZ50`@O(zd(n{4_V# zuv>GODi8mk3+0#cURwBi6M-t}YVnxb&?U|j`l!+BY4c9{}#%0 zw{Teu3+Pc03fw;D8T9R$H@%{wBJf;}9qC~{f~){_W%4Cdqre!y#Rka4rI46VEh$b+ zP;1zht>3RF5$@s4Lgas zlI6~uTFb-bSmmN^ZM}9iD!)oBnX?wU01ZLv|JViD$cdgT-K=SY>ZkZ}sYwQuo&*I# z{Y6UFL9f~Q2&yE$P!KFju;84fcgGLK;P-u2s*rnkBb|Xsmy#U`tz9r*& z4a!6FkEvAGCPwO#8f)Ykz6r61ieB6Uy?1O-0+_w^B~VRU86V*&XX;kEpYtX-d1c%1 z!(XB)Vm0p-0;3H5a%1!LVcGeGZGU?mLZKPrlI) zDF0LcATSX3DnV64kk5(g&(c4{w>Wf;a4K3E3>8^rx^AzX5-jJ^8Xbe`3s#Dfx8L6| z(GF!*zTue*nH8=?Rr%(qfyNLc=HodJ>rW2Gcygy9WZ)nSMf2I*gx~fb{YOgaw2D^* zz8>B;VLUQ0aol!^XNplJt%MIwOK!0in~vn%ujkNRRL)FMZ3eDUS%hlF?e|Pqv{xT| z$!ELYMAhSUrc8}QtcDn>uJ}8?0rL!MY!uA5fAqO&J@N7;DE|V|yY>Dwn?~8zHjzy3c+CdEB{(KebxSZiy)~~3pKJXT5?60|5pHAO&D#w<%fbfr9 z8K3Dhx*x3YTEM9YR>&Oc8dNkE7n_?hlUh1M{5@L9JIC^kz$10ht6)kN^glUtu9+12 zj&OnrY!3`cYp58=${Ncz-4>IkzkKEtWpXz)2L}cLg%G8l9^nMHuwywwJ%-xpjJG$2 zn1+8MN|v@o;gcNAh^6}m03F1SkpIkyf38fQgmdQB+o(}uI-v#Qp7gVnNzcKa9SaA; z!g%uy=MCsjyfV+sPNRvz}NF8o>Qv(ArO|vl5!Xy3edr<+`AC{__T6~3OgWOaZ z83HJD%BS}o2Xr2L?RH?O={cJp1s3!AC*l1@H?VMVN?CcPB#%D=fw7ZdoD#>NZSK!g zity`GNmi%^1GB5qDd;sv&*W4|j-A@&TZua5&a-wG$FT-zZ-ypMlnn5i{-te67`rxTC^Eu0Mf8 zI>t{hH3CWsCxoC1&yw>$Swa6MESbtgT8?n8Ubtr0BZW$oEhRR-=`qP}=Aly}KB%%; z#!B894n3n~rB_o!_u|FOVstKuQ}r&U-_eox(|LIIbMn29FI0w}43`yy%cfIBD@8J{ zi`fZR(eJPHs8o5n8hgGJAs)`IJ%lw>q2=sM*cJ8fl~4K(?$Wt+VYMf}_Rg{2&X8~} zYg&{~npf`I6G=TkQ6&@2+io}4B^l1Q-g14jE(Lm;dD`8+Ng|C_*i}H9sux0WActY6 z>0;3DJv_d6UJ0yUcQ)tkhMrUE%v?c)M2#1$v+z7^jpn$k@c?0a($CrKN{Bm2>XvtR5;goV_n+~Y4NSlTl5T~VWR- zN63H~88c)M8XWw6*nQWGXw4O>)GxuzSwhP0+Tte<#GN~LT*~YZ3}_Yy3T&|0!!@}Q z$&d>vrAl5w>*o)^&ES{S`A}|dP!5%Tljb`=1%!A8+bVWr4cw&>%t7JFfHPNX?3RbM zcb)!1YDiwjVCU73R&bzy+GATl(0)OU}GrE||q-SQ@X`7vCR|8xe6dDxibFDjfrs^&a9b~EHh*qk; zj`Cgs?!sB?-LWuYKAV?8@wl9TfwmtL`r+{@M|@JBNYU(iQ8O!ov9}HOTvG3|=v~9s zNTbaT2JteV2Y6YR9o78r^>8R#$_s59^d{e9bX)n{|2THh9a=HQXt#x94w`C7CtPw( z#aQiL%t3|X^pUa2p|DH$FX&OEtn9!~XN&&Sw0b2NPuII4`++`J8!8%wC^&S6JScX4 z3f7;L}bVr z*QfJjl8MW1sBD4kr5y|oF3qV)=_}99a8&&GPznyZs|&-Jub5BSYi`mP*{PhMrmdlL zRvfnCg4?==Cqo#{8TDe*Y2c}EnblW*0*?ucuq;7VtJN4Tr}amLLUYuR-`VT7_lj>N zo1;pc83Tu^7*X*1C9HF_A5`(VL$Hfm*J+X*-CKFU)y0Iyin{=zorXr)ht)ub22fzk&Wjsaph=p|D;h?7@nI9TTFShNgt?Zv?C~Yq+eRh1x34 zV$p|@tKBbb8909WF~y`8TW}&wGK=fpoV|W$pQ(&vgokP3e2n)L^B!Gh2uUNrfAcyn zi(D+#&qtR)w>zlnx)oUDoz2KnalRNwb)kENkVEbWokBw5kTL#0oef;g{ZA+H;H=w7LEAQjWhl~w5 z;xAX?34YeBXjWqxX`d+lDn=}r;B}IU!)#@ZwBf7dW1KVFCmm}DSe|^l9R`NrS8dRr z0qWht2dl&^#5#c_!LD>U^9*q2pK@GVhB;YIkV^Gn8HoXdQOIG?tdPb=hC3EdZK8RK2Jaimvj& zFs*EU^*Fd5$C{iG{%h>#aA4q1^zrxaBu;}TiA7iQ3}snD6~PmkEPclk>^t=@XsA2N z9cxEv-!`8Lj!I(srpHs%&}qQzy;fMcFB=;yV9-DkQwXIVm+I*}Hq2PNc3jD>JF^47 z-7VL8yzUL^gShV=%cDUK9&*9GmD&obmI*_KV)fZ_^l&GM|3b(RlYzXYD^AWnLZnG{owCY$N35_P44M%(xr_`R9 zFysU0dAtD8l2JIE+HDAWWqRUObq}~*L;Lf(n2!0DI(4c=J4P?o;!CCg2bk~gY$Ex~ zy_S=r%&oDS-bKQPQr}<-PE)nToG4);$)P@H5WVBg6u6AxsHO(@m8j zae=N`p${vTO6G4wa1bK`*?AF+x0uumE7PK{Z<|kG1f?o?q*pE#J$S7|5YQaS}cH>!;_uGAcK6EBZasCbXm@aeVKc)v4<6j!Es zf5R;Uxn;d%#FbyT|7w^>rl8qLepc|4n_v|4k_N%623b|>>*08G6H`?4OgC&+MsJm0 zl`wB>%91lz2pRPo8e){s4yEe+FgsCqLtP%6vKVix38TiPb~d%_D)>rTjDru= zD-obN74nHfIFMqXvP5p4|F2y`xeTs&0pGjmFBNg zLr;nOoD0F&tqHir+0c-drncx|~&}c=@8#%i5Zwq^|>w84geY>CPpTB-pN%%i-QA9J2OR(R*v@=j}GJ8gb+j zo@=6_n6+3B7UCz4;Q8CWRpJgk5ewSb%9`d4HJ@VInCak@a(L*wwVMdWcs2qHNfu(g zK%WN|JTm-F@AJHK}sv z;b*@wZEzZOFku??cbQktd!3jSeQvTR#!6bmJD;BCI)CD1pv0qK&@|mV+N^dGb`pHt z1g)60W{wIY(kJ2Be%=-dAt!tlSFd)k7wY8FVD`gD1MmbBSYLavbh8K_{CG%X2UT!O ziG}yR@$`Fa4;|GrY>S@FEc$*TV~3F{aP*B5Uyht9;E<^}7gAiUAqUVz0g1Yz^D)}hdyD=eG&XQ%Bh5w(SVDu`u z&`LTwvkBw%p;+6&D+94U#d5zp=|QW;fZVQG2=ZZ4Mmy4&JWEmBcvXo;C)dCic{hNz z2f5f7T2P*xSh(ju!ZW|3n`xBDc1Y!e@)vO@JY9!q0SDw$sN81_)=CNdGxHNk7${tB zL{4#*$9#yF207dF-gT`}E|o>>uoro?7~k<^WG6X zlaexwRvD2|-}qe9?12FT1!J7e;25GPo&X^e{t`g$&vEBC?S%)3BMkep^)+zr_IMm@ zPnSZ?=$WJ~FmnAB$)}-MwiU6!if1VR!lFm@nBo|f?8+e| zba};uV2F=|6HQ0v=>*<3YCfwnGwp`EC!zemcA`-xKIEOG!q*nNK+9i3i! zx^XRj3su+87it-#*(treHD7jm6FD+8yxFqYoH(}M@{<4Py>60KiQKj#vQz0uH zJp|#Dj1Z=mOw(fg7-KQ$9Fbc(_JYdRb)|XrMAZ*n9>rM+*59@rfO2C0@oqrRJ#79# zh{7qFKfU+=;_y-8vP4^oRvD*&mw3u~l#atKk<9qUs<}esfr}N*d*0r(m0*<*FHh15 zeP{ES3GAg6jLZ}yGIruwvb7i!G;-)Ymu20eYY~U*$MWU!;b%@1ia?T|XtF~->ETH{TCwW7M(u?RXGV{2xqx5p!7YtE4>2C>o}XhYC}>$Fvm`s3|@txaj> zH`B2mIzHIa+C;Y+s<1(N9;Y>faBvd=a+?OK?u6zYX9faKm^+CtL02Ev&Fs*+ZQOIH zr*XhbznSKx<|Lkr$)!{Ia%YEbtxk&6Dh8!7;XRUAM%E-VuN=0j5rY&zp3HE}M2@u-&jEyt-H7Y@8y8STLks+jYds{{grAI8oGOu&*CL{vwYBQ4Ze(Gqs& z|EW0Uz&l=L5YNg}Dp6=Pe#dMwC9gv^Vya*~oMqNh@p;`q=I}k8!HEZt3W(5(NpDpN zk`(9UViF&I8OayScvToJFso964Mkk$k!}B#7wmLNAp)0kO5FCCYI_eTJe3OT{wAxUBg zW_tz7&%kM<<-GG1Q-*15A7OqUB^Ci~z3tSgf^Lq$Xslonbn?82a@E+FzOMub#9-XYR{ z=b=oc>7tT}*_#%Q*<-;Xd()r2P9ENW|FfQfPySP&ujCqoYZEKY>rbQ0vt zua2Xb!?iw4%Y!+`f4mpl6i!mFssxJ2JW|IIn+g&6f(6A0)g)GKJ*BKh0lj{1XKOL- z<4wD{2`oBM2)GL<13@0Q9b3vd{p0HR09y@Q#enPOV5TaJn>qCJ3a5-|TQ{u!3`;y;{k z6cSLrxL-t<#IR=Zp<U>s zg4+h(zCBGdh5zUB{Op!L|Z8d(6w z2f=ZMK5wuuP;NjQ;r}t0mSwDbD#~yXLQ7getGKc8U_1faD+ER3Ff=CI)JrFcVA4Vu z0=9f^3M(Qqm*qWnLPB0M$3Nw+ATr$e+yS-(td)~?AqJUH`S|PmC4h!I+5xuPdLC-v zjagGv{{+*|ubaRDtExzp1OaQDw4ka6sJFdLMG3Sd@J@P@WT{xrlc$_xBsWP_$(YlW za|YRhC(lH!47p@H59@xz61HNdA&y{!4Ww>`U%G$i@=9 z`)97-nljkuCyOBDgYZ>942aRkE5lxTt0%!?*1fN}Z7Yj4xV};~!*-6>oLE;Ct{78c=q+JQh ziPH8oIy2AcjUA`5FjKjOAH|{t0IT%oNdjv%798RfosN8?`z*vRf%FZqrBGO4rZ-*v zI+4cbCTZksCFa^txr;+@rH2P9%oGE~pluXs#QFJzu>>0N*QeX{omO>)usB+ww^|qn zn%46Cf%SV()vO`;gp{5^udvjbNJ)^jmSu2N`B`8Y%;C1HE=S)Qm-8P>kpYmA?N`-fx;LL3S zL5s(* z`1(5QKFJ&p1?)awCk6Rpr=vyl>`xZo0jYUsjghRrZZFwFLZA6<5*|yfh z38`;D{-1puJ%)uX7pH#}BmWUodszS^M>XGEp4G5}R5C&~l}IiF#PU!bS&LaDMq&bx#U zK1%LE+0T?1UL}T`)(TfKkc%j)wFfNGmByc}s zO@ne>Z*^wtf1@=L6GSFVV*(W+Dt39 zSZD{_Aeg&655HPflz$Fn9IJ+KoHUbyI4gPPf2e5Q-$0Bd15YZ3qr5d zOfMTjC}oGY-=}_|eUqr9#PCW_GyjLveT5dW?3Z|UC0OJ?gtnP?@GqCG+ZNq^Mfz`i z-{*I+=VNWouL+&8y*^zE=m$Rmn}nknYmGr~;~rL&4OY07zEEd+8}#<=ThxQAQS6m? zfh%uJ??2^u)b#dMe~DN|gD~PDxmLoOFCHsIM!H37PQMzKd`^)69FMEi4au&F>{ZtYaA;R$AKEN5S!Z>u7pqLw~%xPTS3Zjiq5lo2R4n6H!Ms#;?Ux9}P7_*sHVX~M)bOtXOz z)awQT=aO#7u`hDooSR&y&F1?>()_!;KQz$W^~Hv^J!aj51jtKQut<$JmX&jhF3ocmn=@LpLbG0Kx=T1>0GR zemi^Zw!;QEZ|&S{Y_ec$c6lD*wVeq(nWa^(GWfi?>@_>loKnx&IpuPsL=Xdi^!xXj zi%{UGK+tm36A9Kt$5zRFW@i}X;m1q3!k}JxoaDnj{O#Wk>O?L!n?R@(|0;s&hM__r-ONXWx@kv3+<5@Pq<02Wu2ViKwMJ2x&G%#`Eyma0 zE!&DyJ!@E*7ArfEVAOo$=HY;zs`h~HyvKTx2Zh#? zQmSQ+R;rcmZoR;Q?2Ws1#0-KmbD$(bqh!e=A7w%FF&@)C&VLa=kghkE{zzjeEQ#bY zDZxgO7VIH~b)MG!hknd35IC@o3|`Aky(&bZaW`u(7=#Y+yq%;*JCKAPM3 z>`y`W@(s*#A8#(jKcAZhDwrFm@yIL_+0O_WXXg?Z0DZZR=XhWaOv|CX>VkRMYMtry z!=uvxk0ikQa;wMhiA6i*VAUzNE^3*;CG!! z=3ZI}vR&j0RL3zK5#o56`*7NvW+Y#S+-$x#H7-MGDR8OlzI-><%^aB8m;|D}9IFS= z1T-kwB6D;LQT9>ueK{XZ+CMxG5ouYQY({mZ+(%)}SKx$E<3u!sk_jR@GqrE>0539Q z<3aCBYC-rm3uo%D{I(BR*yqi;=D&ZP!&gPzLEO9&)xbRmqUCFQaQhXq*`uUvi1pQa zx>5ijb%?VdvS|+Wm6o6;$!{)2q-B7*S+yTEugNU(l#|#%$P{&oA}&P#HvXqR^6JB; z2fkr6`MD4N_9%j;@G66Whlr`B$mBS!8>$uYkub-5f zP19zffDiydBomiGyT?YFA8r$veFAN226rtGgocLsZw|#j*r0rXu1Rl zZO`OKry%2N@Xi(DkYO?ZJ1_$vf@-O~84bs}#I$g%|B4HNPJrwQS}e-TV>2bA3Iq-; z#LLoc!Z2&VSA3GG1#*QLv3U&=6wUVUL6c!wG_#u*=R+U1NFog3kd?SL1~a1?Sz;GJ zZ|9*5i_WI1W-S5ra(SX8+vHkT8L;25^s){~s0ZS3A|3T5VAUT0(0mpg%0Pvsr zplG`u^|q1gKX~(~geKqK9~vsQ!AA8_hjSTz2wSJ_W$_a^y#bCM?1FNFH9GDmN z=}5>~GT&aC#G(t3=0NL|j(X;{&}Sv3E4 zeVgO*{$IN329;4y2*Ii?ndc#8Sl6V(#klqoy<+A8Y<0zvt}*vo0Va0_R4 zK|1s~r~R^E^7vi$9ul zmV^vtbyU83<%(W4VajVp6qfF3rousb#tFhQc0kCO7G44Xr_Ffl$|rStQBiTy;RsGB zgyW7u_~9u7Noy3O@*N(>6}=IGp8JL7+Jz6koNxdjx#Zr*JN-{|zXV~az@eA!V+kpB zkeKlafH-Wl7EPD9uQ;1v(wk`xgfM=scv0xLt-^*Syt9NFCzuQ(GeTH-6=^PZ$gzIY zvaH5GJKcIyH@6MUKcdwiS&V>Dh+el&&n@e_0TEa+4VBQlxKhAdLSj-G<^o`)+Dt$% zMSDA?6Y>aYOao+BgiX7c`=a|)Va*){Al!=(9iZh5-eCJv9VlGHn)$CgTW%ei{lC@{ zyJA)xdis&(!_1hM%wE9S8ASFHqqj>S%xStG zu5JJB#S@MEC-M5=P44g#oNA=(0};Y^)*@!FW76+>n zKrWrwV?d~OQLq4JzJ`PLGvBI#lC2(K0wP_`Uz0!OL}#IeZpKr_+IaBeb+JUa>xM1g zs_LPjtv0a3hhV;jumlluYcOlEwVmur(pfs%a5+1gR$t6B88F>{!p?kFbbI}JOx^e zp|R{M4|-~xKNf|6l^(7C_KNy7`K@8$35Iye;@Ddn#l51meRFi)K{SEeX72?0&#P!W z!C$!b`6xa5Sfe1l6Y~k=NBwSOM|R> z?wSIqXYABoYV9-Om;|%X)b9Mn-n1z2vU|T_4WWUiH<%7`$xHEzHgt}mN)>y?=_k>Z zIeExW1yABK_7rdNn|N%0NxQ)~=DSb=Zp;qrjOjprBc*7Ad9gw#8_D@jCbf0&~ne ztQBL?fdXnim6Q)5A+UUW>KCAJE@r&(Ri0KJfazV@ZVNf}LyQ3e!67Kazfxx7L?HeA zQsAf1XTKH~JQ3}=XJrF9jKw=t_r1i%JpXX`8Xn{97OE{>fBER~EegVl2DeLVu|vHK zUQqyQv!K-!j2Oe_(l0CG5a=~-7D3#A#mn?;m`lNgFkwwYNs$mE`J=-s>H`@pRZJ9n z0f-Y8j5^jZAfmaVk>7BK?<`mdWFwYWoJsi*_pu@annphAgUo=-_i6}Hx5ppgL_iu> zNwLlJ3%3#p^CO%zH|=d9%SOPEa`#kzeaLA#W(n}Oo-r&s0d&XhB=xVL zhfg<|#eCKMbUOxFSE?Fx_nQ&s&7TAsCG7%(wW zpaZg=DK1WY_vJuJ4rm}Q@Vb(6-mepZ1yj!$!4>St)F@~woCQ*4F$Tg7JBcb4D@jR7 zJFq~I3yEF0PtUM?ic$bx%oO`nSdp%f4aBeQ-cM#+{xcng%zmGHY@<`&A%sO9S^W}9 zGd9>2>s3F^ZiYUFgOIN+^=X#p2eYknxocJOH&o6-n` z=oEivKyZiH3WvT6tEc%%yu6U+`T9y=IOIM=deSTXE2SjArpce?ChpeY z(Yo3j2kQLq;$Cj& z4LHZuw7>n;!+yTUDV~E*!pYfB>040t&v2AN1Xgb*<+bMgsyAO<21v&0D~*dkb{{KP z;;k`&%YBBR5|VD^m)Gg{6fHBuYb=>ap9US92)lTXA&yiAnq2swIt0G#0pdi)XoVq> z(Rrb3;NY-4oZ%t}u^O{*4&BTQW$&Qe$PVr9WiB)6x0!K^jVxT9NHqCl}XGZbzO9*M*ES1c62UG)E;K#;CgthhWKw2MqQ;Wu>sHhF}o9f4)`pArXw zyUhek_2QfLdYQnR4*P;SUz zFlT_bYQpJRh{FCK%Dy`g>o$7-A%rNBLS{wTd(RRjtE}ujlVtDJpkeP-WM*e)uVfQK zvMM`!Z+_>K-d^wf{>JzBUxep*KKFf}`<&}s*LB{$A&&W;6e4G>rX1N1_h-iKH;*V= zxcf9mMYhI>G(P{**dsUFNmfAf)%cot#U(r9uRb1}D;~*C%**gLXlb(d#v@I5eA+b~ z)GD&eg})GW5!d&So5zN@tu9bHPtj~ZIX(UMw_2sf!#aB#_A6a@`)O>z^CJ)zf&hT& zyx9<#OE~oO{(5rML9kOVb@l7({8h64+G<|4uv1eOU%U8|BVSXyW9Uj;rT?+c=;X70B878-zUe&~GY`X>hj*13oWk@$%3a{U(3ADL zh?_B@*B)Z`S2&^S1IX1K(;YEf;Zg>~bg^?YpVLBi;Mj8CJYD`8Z0-U3p0S@FoCX=V z&}HSjnIR}CP(%$ON)e^^zjS4>7!JW96}R|{cA*s~a=TX9W!~8ZAQ>+gRbuNhoYi&#=29!2Xy2zM>?4upS!eCm4_LkXONq6=$ z3@A>dLp0I#3bd#Xb~l&UUA}%;!mj@CwSVMts3nT$kCI#r4K8!VYPl;ukN zBRrShIVNE08hV`PzBgt+_cht|bS%Oe;ffCisl~-T=vdD^05Ffj{jca5Lnqv?Y?>QI z`|jfRc&IBj;3S))#*iipYx&}%5Z2edz#?y4g+EpTYO)y~Bgd{Jsd>1tdT|*6zH9a_eI()~@zU%O8%X?Oqs7D*K&%XYKV@WNMZ5HmxVk=8y*{MFs5z z&Ux%EHOxP5)eXwL4BYmQ(zLN2K)vpoNmBR4a7tH7OQ-{=!x}J(?&?p4ecBnL7u@(M zK`-!Xe76E93rI7U3?tYeltBziXFKa5DP)X5A9P}mwA`-X!M%c8r#3(s z!T9(u1fdC@FP`BOOH5aI4_}i`cH4>No0&BZxgRXsKXg#SVsD%p%Rk9GvxCL4A+pc< ztp(+~Kdf_%O?^+I>RW+ki7%_=ng^|MpoSMvJH=N|7#3;)HA*4RuxZf#&R7E#kTroH z#sra&ql3_F^C?OuXyh!`-*p&)E_^EVZ{DDa?r!}7U?o=z@RA~v!=LpO?T7`d`Md6z z=i>#4)G@V$bzlo$zb+ZQaooY=$<@~`V{|K(cZSl9%`oqSKIQ&!v03*=riwIG{gbPU zd4Ov`_u9n}oB-M@^z`()0J(YY=f~}Ja!>kA&oYrG(l{2{{PtMoE=vozI5dqlg@DwK zIamwzQ9!E7?E2%&U}?e@v&uT4o;CqAn&OjIEFcVHK-dJT?qnSFI+f*HEv4Sf1+Rcv zl?Otgm2*0i&-pX)D24c1s$~H1zrJt)G}$mCl%zNdqRiNZi)G@Lx^*G!LAnBiJ@H4w z2KWnODZ~;e$%cq?lYn~0d<%S?bKt20Lc*1({P~yO5s3J}CTER=?61O>0NDqRzO!)N zIC5$T#HtVA3fVjmHpKcB!VZ^8WWf5z2OJ_YMD}+5#*K4~)NXW;8tt=p(1AqlCZzqz zKth~ok$%kmx5&P3MwX-@4W8=q*)TwljUM&>i-7iiX?kxA3I+wGzI} z-95L*q3w27BJOdQiS^*5+ALPv@5KHTl=gz)>Qjl8W|&)5Z(u}!S^=~>x>J9+>P0na)jlHj>poSRk^eG;I=%g~aF3G|uoW?+CmW4I5c zb7Q9YVj`FiB-CJM^fR`u&h{$;F^F+HfKSD|E9rUKS!+lcHDWlJx$h^0nR5juC~IV< z9DFysVgmX51Z#P(y=8>@mJt-p?H(kbsQm>H)n4lw2z!Ixzvs*Kc{b}dBT6X@L@W;A z*hUx>pvyz#mgO4*0Z>s~@TfE7m)99Tb6I><0uo)&_!4ZF5D@6L%z6O-WgJKWw){L9 zJJCJ%!u-YU0+o=)H-l9PGoba>+ByeI2(^6~u*l^s4mo0#!#YchS`{uajFwl%uaDk5 zo}M1SP*_^nX_)$T*wMw~si8IU{5joXyqDLHPe5?IjEG)vI339X+)HMF`C;-}c&R`% zuvp8go_M*9cf^rf!tH@XoKC0lsrL}CR6vROt;@%)stQY&>r=8#cbpnd_4`5X;XgSs zHuX1T)kG4RO8uchsn4Pf_-H;JK0def-pf#)nTo>Jw7i*cBO6;U5r3G&_T$-^78E}75x8!8i+wppT^l^9`nB`Q4vS^j^ z$vkEM^C6$IKyL7 z915KXm~bmtWvJYc)ZsK05%S>6yBeb%NQf>X4V$qE(%^*G2JSg=F(_Ym72p$^utX_V z)28liQ8?(m%F$^~e?#TAFBRvMfG(rgWJB@i0DI{oh(F3ffB>DXeu>8sxB5(j6$jm) z|3|}cr2*mhxfiSd6cuCSR6~Vo2pbXW8(1R*Pfbms*TD5mooV~x*X=Bpje&asmFNZm zQt0mJm1mCuRI}fLJV2&T-Ou>LGr}&oWYRQC^7`#J7xfS>5pt~jDTVJ9aX%PT1(ea4 z!TrpK$QK%M>!?;JW9T8MW;f8>TO0+*-U>?$7)i7%lO4PbpdqL+yZ4Ix3L42ClPUEJ zl&_tM+L03C8^Xn|Tw@9z2I`_gwz)D2QDrz;D&NnAK^}q`mS_3gwhQZwq=RC0*j&ii{*#VeYG; z|2~xYvQ~N_V6BYI?Hx7}TUU+B|9WaQMV=;+9Mk|>lWrG)n?V(DdYUzt*iyhm)zQ>Y-AbeBt_P%>VYU;~%wNO~zt}k#>U+%jm zTU2|ZEyLYt;t~L42F{YTUX3<(xJAPtpNeUw>P50w8>|R!0zJ$KQ1)JeDmEBW`WRe# z$OrP|nyl0G471)B1E0?f^fU!%l<8<%!u|1IWt?#FBb^@|w*DGrU=+FC=n*A$>)@D;*76L#1A zF&(_~sbk?*R#wLA{93%Jdz9EK1}{@*7H3y0TSIhqe<6W3$1@Ipo5?VYtSY@e;$UhJNz-t}+Kp zn>t`pT+(q}dU}^vUYr%q^n3nwsHj4rGtb|Ve_Q};O#mHTeiqATRa-JrX$`Vd{yL7{ zb)e`pfo%pIXjoGFm4HS{l=&sk=p|?456aTcV{?5yFZ{thEa=0B>lqpm$?b}hF)`tN zC|@^C^WMxLAgz~b@}%xLtvxKcNmEXPQp9f5ME_Ng{;ERXB2!yB=i<1{!=o$!j~8nH zy6yd3H*N6;p_kv^j}aRq4URW;#gfeVKfjCe^1xgjNP_ieK~f2J@FMcxO1Z~~@jZ|8 z*~n&ogfJ>mC%YFIv2lY^aDnS35gqQP-D}hY$JofW-QfiI9l(KNB0IC5g3Ro+p2;eX z7Kf77Rjt4@XobrqUYyt4$0z0mGm_o{EFvkgx2o6~nA-z8i`NVka%;U9#+g>8jT4Xz z@eoUJ2_?AQA1YObiq$+E&P@BtU`~eM*CGo>tup&CC|FxSwRfSH^EzT*1YFw=r)*wE z31ZJq)E#Z1@~9Bj02 zR|)|EI`BxjN6uu0ARdfka6J*?JDJAt+oWjPc1jovmqkD)uO(eM;}Q+c)e9FcBta-q z0O`$217&=tWn59^mVk)Ju$tb7iUsJqG(p1FIsyMLWouiYCV%Tz@YtAP{sYkiNLnGt zRozrojZC|z0J!W13ulEW+*bETDz(7kfDy1HP6H4Fl#;p_8XBgIX5nuwHQ(FamK}zo zlBch?nGrJH-f_)vwO0$)w|Oj=$vm5;OOa@>r%`H~HWiT%hBacq)}Xs{=T5)xc9qt4 zi|ovsfrFyFzX)4T>2>!!tW=aG$|+v%Go^^yq$DRt#nrcq?A*7MU)!=m>I;B(8dfu| zMnb>U$<7Z_Pc5#^1ZEbN_N|qS%Hrd9Y)7DBnhXn6+R_g~6&8TexfU#;aSYJG9| zP;49C=Q@-4oy4X47AFudi~G62^0HXVu z3Y7=Z!YHI)NK|Vjs?)F!gHTHE7X>iFRGH<`?;OvrIf|oF2m(tm{@mYUw_!PP5(Ye0 zr|xiS>?Mcs%tXj;pSWbPopti->6?dS20GB&L zV59%8amQr*ZTd^v62PvFRElr=qubJY#E(&HK z6MP%z_J$gvS8hJx1m)Al(1gPkxI|Ys+2SZ;saQ9bSk>}A_}1-z)4O@|8B%R>fDoY5 z&c#Mlhf1JTw#6JpmpbE2bk+76tvss6-ET^EE+<+N;-|>`er0~G zRLB90DiaCvxsl<|VvhyZjYV}PZ$mw_Gf&>fd{=l8V5MNtD~~z)QwDb1*?i3*e)L(3 z3j1?P93l4zAf=q|xxkZ$XqWxC;S$hlPLS{%W(v2Tp?i^dmH>Id5F|a4R=~Za)1AYg zhF0Mv$QrqQRMM5C03H|@Vot60p?q6&AHQ{~;|JLfIayh5Jz{*v0I(xjwSzmo^vQkO zL=~lij~T?|KpHW($*gp=83K||6C`IV6rLqOza}J%+{--=iVvPi|(+4^X%f=}IUncBOu=G6rFd^0dfW#1b^sTlQ$ z4oQ8W#O-@>C%bCj*$HZ`SePxvoauK?^P$(EbqjOCNOYFh`3z@Sh{Q(Fhws%h211H_ zGc>>3O0jebZnc6v05vrA2=NEp2Kaqw3{Val!5T zBF;dDZ3gt~d@2{zbzU&%nOg>}EdPdiau76aqb<9$;Z9`ID*ap{pHXV6Dp|+-^|jl& z8WMtRJmeU+*1GoRM*DO=BTNRwx-&w0V{YK?s@^S&?RO)<9E;tVo1ElDC4Rqz|LT1) zl2w2ZX)cdHb;h_@C!-v^*VMtMStjy^xbXTq9BF9?R&8|n216bPd+S3i5ScXj91me? zu^?;=eUv2QiFF`3I|5fEjAQ>xmFZtz04D9^IrrBld!eTjX;20t&eMkNET8liG(9L0 zd$KfCB8_zxMxx#dDF;z&gSBilzXcp>(!hoa!^)9DRQ{ zTLjp~Q25rkZX7e5-)^C^FfTURMQ7Yvbzcz?$qQHO%~Tj+60QKSC#jYP!y2Jv=M&yI zT%vE5u%x?l{_KCc_<-=bUR(r8M3m1=K{5Djb&tnna~C{>lrDyWsnlbCcWa^|djPn0 zZH7>L8G~~+Qn@EK3fbV9tk3$~ zE}wn?H8%vV`N&%rdfl~n?ti%roa@U_w&cNGGnoy*lMccqUD2*%hx{h|*)#0P{a6*( z??zNrBC2UM1RE*Jw^>TYPUovp$!X>pK3^f&+1kRd<`cBj=)@I9e1=Qz0F zv#kNPca;22Th5|T=D+MZI`APIp1G#5=#qm4XXfOAKfSp#5r7)Kq+V))1Bry za*7Dfpp!Wx*hy4Is%MKV@6Z@tsv)rq3ADMSG0(c)zRl=3_1K}e&UHQ#>da68?^?jx zu$2X0!*uEzG6p~-iEjzdoS?R+dG=Z$)++jS7TsyW7S`9{-MfZ?)psLwWqj9Y17YJ zqLjUKro8EaroBVfnIvN8**Q?6ayZOu=1(J@$4I07e}7nLSj%QPI;-<}VE%8#h1dOh zE>V0|38p>gEYzPGfwiUr)JT(r@VHl93@{;T- zOvnO*jzx4h5P2@~(^DMD;J<<4{l}+|dG{~HSFLug&*jk@I|Ovr~(-r456tjPy2h_3oTZn0;w>G3rAj9BdfAe4{P1M}nW0-5lZf(+GucWJD z>(@z`w_%;yfHY1$a{uq%(jzU{=BM#KUFKI18LTCDe=V(>p%^_k2UR?(={-%n#O4 zZ8YG@P*Dz9Oz-!0Bm1i-X5v9Z2fHo=WFL`r1q@A4(B6L)Jlb_vd)Qa!IO5;L@4Wgp z4V4dOd-LG7!TUemP7-#lGWU+(SuX zLh8V{&6(4~HI*gW5(}`&X@F1C%Uh$lrGc-`)DS?$>jSn}PDpDhe?&k&Vx9U$ z;23WVx`~=AkOk z#?)QM$xxLP+p3xp*Z!sI;2U9n)z$mw^UJq)HCns&uVIpuVa;GWLgDn$h0*`;a8&Cc z7-7pR{n#Ur!=|K|_+>JYPJ&wir9pRttHpl}tpT8~{3?L-Ilz^MDWHd9dvU}dK$s5t z_FN4RbDE)DPXj@?-S)M&=ITIxA#AXw*d1snM{OY3OT$n0VGOZ6+-hHNz(ITpx~oJ2 zO+DUs-f#U;9|0>S%FV4@@W`JBzjjL8R%K}s-97>-AkAjNTE@=dtmKR^S zcOH!-Cz22Q@I0Us0~YJM-VeT7=oH1guVy;j5aSD+bXBx-!mJDo%}TN`vcPIulJNsr zxk>8l>uVOxoOeM;0VO#ZeeRTS4qJ>njhL%z`E^Oj7yDW_tIl}-Rh9pGij~k19~G2#X1D}# z=_y8=5kaFQ9339M*+X=rS{~`lP5T*qIr7lQ?&w0_!@3TiH!{D>cKQNRhKCD-knrlN zMpo83@RCh5YQzJ&eU`F8-?0S+PpcWQ1G7yRYb#`52>^IGrN=Y#*agJVVE}SSgFMO* zI_i{EXIJP@!OAd(b9Fl56#YG9kOodTAUYq*JLZ2q_!0LCX_k`fwu46=x+~;%*1*4t z{9a(*C&x7y+9!#k%dw6Z1b0n8L3w_FeCtikouB=Q5QL z#J{T{s;Dv9j~oi`58T*7z@ImHC{ag9=DY=Db7AlLtV&xZfX~>&&SrgjIgcm-(qt0f zSZ9@*77EV4uUk!90ONF4VA18<^GCqG3j-I4=iZi|MR;XB+T#QrviZlM#1B8gTK*}c z+lK6}+)ma@82%}cgTTOd?&1p*deSr5Wgj^+GRT>key}sG8KMx}+SqqFldVNmrIoj( zJNZDIw?6V3lk>;k!I_xI--+Dw`^m*4y>o(Cca|*k;x`yHL$Z*? z_j`tn2lQ!1Ssh+j9lgZPdjYSl33i)|2`DzZi)9CLKIaI#3%P zFN5MI2_cwAwdGW-M8cefCmp%~On6|_h|pok{= zOKei77Z3;&x=${6U-?+4RF{$?+;$Ts{W#nPa*}5d&z`Nb54GZe&E4`iY<;CL&p-7z z*;;v~`W*~iuvi}hxHSS=6OnodCm%6YGU5JkzZeGRh5Nkvon*ZbyNaP(&;jYmx#mq9 z8^Wy5d9GX5D>pLgOvgU}jVNkSN^TDva#d*0&dDD;4T0_SUX-#p(=bog>GvQc;&)t( zH}y;g-46dg`HaQLzN4nq+NV#USh{dwLZ@T&_{+cQM!+-9Ah&q^{#kZ0bT(Hkf-CN@ zS}#U~^{yYjo3XoagxoRtj}G-ZAVid^TPdb{DRY3g3Or`+Z~F#U9Q%l8Rs*yRTL2z! zJEo;hF#$ZzaKMISAAmWG*{67~E$>-qe5uS=9k>%c?6hp`_1Q&q8B3=TT`rE3s^Hqy zTw+F*NS}|H7VF8pzvS9q15~J{hbzkRTLAmhL^{pTqYMX-I4YeR>G%kNuNg2%h+rkO zKa04#<&1n0h9GalTv6%Hxe0|zR$1#FQZrq;bm>ER-?^Qw{nMVERvzHG(N$=ES1at@ zJ2s-EuASS!hFw8TL8}b`FoWR!Y=%H_tkThug4&(Z4cTJY!jGa_w zB#oV>zTC-|krFfu_Z#K#U--PvvohQbdtNB*9llpA1gx?99|#YZViP7pk$99D_?|lg z$CjTkYp6f$3k0>=l=DRSE-+0uHNc~G#UqO!lDHoFaMzk`M&~xx*8-h69oe5s z&qI^X2OCWZmc6*|3_IKR^@-mI5JGst^$qv`JJTY#Vvml1Kg22*E?#V_Q=6}1YQ9&! zev6sRy_3LKWS0*C4K4Y5@3CE$H+Gc@TfYNMB~reJ@yN&zev#GWH$DKvMoODM4F?d# zh#SudSdU|14$8R$iIhB)ta2#^9e@LNzPLbk0UAeIDSM??kFf}>LyRq%?R#-aeM_Q_ z4CoD~b)2W4&Z3>oa!f!27=4287&RGn*Qb{%UTJFiDJ@@C{diY8Y=bStp{ZyD#isE~ zZ5a2`TU4QzGhsUvyRIR80GgAO+7`%HU)l7!0j7|G8=!LLCwO_;Ii}FU%&trK4@=|t zPngh|4vCDs0h>PmPwVI_1 zmxJ;ixTKfwJUt{~%A{^3^MLHfwse1OER1HT{XC)mJI;cDH?r1hg5mJXUv(r#p4hEhFA!em>Kj)4 zAX7(i#@eyZtDB$&P&`Q?U|7opg?2kTTZm#@Nqc=N<_iCzR*kSJ|BgBuBJn)TlWPr zdrsfQoJ7?Mr`nWYv~z$V=DhWC=*^b-48w&QqN@&%aR+EJ;v4ce?uI|0Xfc^S*eJa; zy*c%fX=7){KT{LeMH`k}BX;Jn)qMMx$@Fj}KYFu9l))TJAstb-v#+fE{E zVnxol)fkPRagE5}4?K-}`MW&NLZ}<5@^L)M-?`3YU5y0P$i&6M<7=8tw`V?2*7A)L zu4woIW{b&&O~J-#XqJ}OhP_zp@c#Zt1dFdA-i@erg#=)%QlSbghN5-DrB(Lz!t*^2 z2AQPmU+ab6SxPfjE3?MW&%C>?nO~l{R%krkCM`#-d+plweaGTlrRS#{>^F9O1jh^0 zvWcZ)1&`S#Um>q_PRr&>SMItqJ@(d?BDcO#yPr;l?qs@AZ=WDTo$F#7+Lm6^o#%cy zAu4{-w^Cm=^X)I)#I7cJ^T-YQiSH^`e-|uw5F`)RF8lAG4^e4b>>IG?F9Xjo7yucy zT>YnTBOd3%1DJjYW^`|@jNU&yLasF5fSKtp5l6`Hw47vW_a2N#qERx?^J4XuqQX9t z?x|v@3C-mX_4QJQhDkWWgzog8HLB}>6P5sidUPG`=DxbtU$F$=UU_G%L*fYm*UBT+K@ zyL`WUr8?MWt^-obhV=TCb&>fjFZH^Pqd#SM2ib|@8Z8e`?-QMZpQoUAU4g0jcXN^Y zCIXo@`K|ky-J{pA0Qir+#h@X$&3d5H!kF|tp+R`J`z!r$jnlkQMrA7JB8}qAeIkt> zXj`WPYxbdRNuC`kf2^&-NpcYyyY%bP^Onx~iA?I@p>x1;zzh0Gd~wXT>rEc-()(GF zhu8dR56-ndRN@DqrNR_G*Y^Hu$y(=It7=NIfV&q4#+l$7%-KROcf!jR^h9hr? zx_-1I(`nhQ2KM5nKqUDA5v$b-7*X zQdr5AM$BBrB+5`Ml&eNrlJ%%WC2aGd%~z`%U%n>?I5fTQ*w7f_i%2%OX7pu-130$UT?lj$#_?uwYd);e~uKr4QrNxJYOwu z$mD#)<;(NyBm}uSRV|Cm%VWY}N!|4(H-TE8^3qRG!KkrJaJ-=^po!Gznvw0uJ?ka4 z+|zT|HKqf(tXh;Lg|hqVuL#FD&Qq|iyRZDvcYAO)i;s>MzX{t*&FwA=70W1PI!hLX z4gS_fV#NHW(A4C7a=`l7lZSuhF(^&V0zu^VMe+ahelj2zRNSD)#Z>iYpwK9ZQGrQ2=Ati()uUdOFjWc+0h)|m&mMp zwv5`Gr2KC;g=@vKni+H9={D|TeJz__g-KC~d44Y41g#Pky|w4H(YC*3+!=lN+zi-<8t|Ok;A=+-|CHHGliVdkcMT_=UY?5hq4Bc6U z%)|VdU=xWg2b7%Re`kd7FKPm0>(pu)p8U0S_E~^P5OyxG0s_WiZMRagF+ zrBhs~vQr5u7cp#_gC2jG!2V#$=ph-&6cu?#PqL1n?^Nr1@BV2=oD+;R(sW$mjyH6T zzMgvC^k^*|W`Ro^{0z>f-CM2Bx!JMZ z)E~?H7F&<8T82~{myg`A^2epaHio0;gkA4O!M{F1wnmQHwoj{T`c7%D?86YJOq5c++|=9-l>7cW`Iz>C55N9PM;Q z=AR9X6Iy20GmEl$ZXH%P__cy2ot1(Fb9~QHOkxV(m42jA-Q*@@<1TuM$}Qx|&x9HZ zc^XzsVAQ4r;GI8ABNh>C!QJCT)NkIz?`Q&j8bE}8@Nh~Y>+Ge^a+?5+ zJI$^_Bk$9eBXJ}di6iB6^#)zr=dM{if9}(2-5y(FOseswKyCP;^5y*9v5<~d1n4&I zPwy!)o_=X5-I$IpGmtOcbXmTaz0c|4EKk(Ww;Ty`nl~OAOsuT6ZvV`pw>A^)`}Rad zO^vPSP5(h{sMhjNlbu#)71o7QS@aRb3@90yF*qv)=)(9|M4SUDib|=j66}f{_ zZd2NL&()p6k7;NTlOlukIUe)sM&rE)VPTza=8-gx>2mt7EKgNW)v(iwliQ@xL=^2V zoY&@3<#M0UcKV)J5gh#Urn6&bitybVU%8lR8x-VjJ!WC#e5I$QH$y>}t#JFVerYS}ogPf$hwB>!ZwxOL7&uH+4-R6sE=)2tr` zj=z8rcKtu69KkcFNf2hK{DS;$ojcSiB7ha+Vw2_qcS4p&f zT7At-cB(spE^_+aYw50JEDbKlWNCaovu_dys>(XR`IPB7SF0vcn|l7pi{v4$DEKGK za8=^@j_VGSs)}cq#AhO5n7K5|9!Gh1)A?B1UFPO*np=&|YDFUTILTprP(}nPF;mgd z`~M_mbt{mj<4gZwNDSqAc^8M-O$(cS^SFheNzpH(v*tfJ3n`SZ-)eEb(U`2YVAnpU zqN{iChRAx$(=N}&Lz4L13~HuaR#0&~;Wg=`-;}o6d|7rm|5zt)QA?=P@vORhtqF(_ zu+%-q56H{uyX_JZuNnF!s>{7k?DBJItaqb5^Rm|K!O*nk z=PRgz<`Wg^jTCo3v@8*&CQrz=Sh#SgWG!VJB%jK5*sc5Okrw#yMx^1)B&iou)~Zd_ zMREg6X0q!oeg3$dU$_1H8M@CJo~+*NGWt;AzvE)@anEAYgORq0@MmuE(@~CVcXak4 zC6hE#I-R$!u`*bCSyq4#U27QY8FsbmBc{Wu4I2yw*t~35qj3K4%aDUl(1_d=Tk{;e zzt+No@Jb`fm&`Q2p3*wEmaX*j+;)S2|KiIx-;zBsxOVk1^|%HTJh*1{_i}vZ{Pp~^xqQ!H7W!7kC$H}2rgmeMB_7ZKG%4HmzC!*mprc6uz=JWiHn(FpCbDKV7L0^?Gj79LCk21%j zs1m1Z7trlptH)(BB*xovyl!FEmrwvuEfrqIcxI%v*@0c2vrT$_Ri?`FOkg+PTB(P? zgf^{+rv0pRgvv&?73mA!$q0I4hGS(ap=H^=4!e)VKTelX_|NTRhtxIfpYSr(9ml=# zWvcumy8=7h)v<(d!(5MAl#xRtk#Bb%DUxl$uAZu(5OI%a`O;yHp*t}KjE2uSJyH*} zM98(J1!7lpB*-(UHpYK&OIhz#`?17SSlRP`AK}ILg*YApiwD4d7#-ON=={wt`W?M% zputP0I?uK8D@nZ4j*dy;nLClKtX-hyMZ!3%kExsKHbJdTa0P|t^0q#GK4HLi=xeI7 zp6QV!lKQqIYzEwpXmEwOJ$Q^w*wQ!R@_f3!WX5-Fm%wYh;S8h;*^?Z6@xC5+)|almdgeSwqrAc_6m_C|{dxLK=cg<^63lx@BGC4B=&DZg`zf-n zJWk}0di?WFUWcAduU3Yp_xHA~UYtp8zo3odeYPr(NoU@sa4wJB6X??-XY3f#k^P~6 zkZ~rl@8!cM`pqAnOsJxLRJ@%We~hifE_XzyN1_cFIWA3&iuSI#tVgN+?q4vB=32S zoU9rKWIYyK30qxOCYUGEac~A&tzjsPv6Es%Ok1AWV>;t4AYMj~15d>woI=2st>uxU zRSqgq`MSG%{+rL)J|zNN<*!^!*?!l*s>EcyU|I&R7~N zI@@cdFNgiWe~GsKdeUCHr*8t87<3Vs-JwyxjqvMl#RI&3nutg-^Wz8Izkc*L!2U=a z0G5Y?lltt^9@y0dW|SAZUuT<_YwwyywC;?)y-{XtmtZJUMP?kAy6C-k3BR^{TbJ7e zRiD1BFFMf@WH(m+G5OLEp{AqpvYgY;*XhO^b^(@wqIXMFe1AW)cjgjK?`$NxCqFF- z8ve*Uw%%f*zVTFCZj@>6ZDpSEEyWvBszK8yh>|-Paacwhr(Gi+Q&@g>8fq|!ZZoF{ zllv;j@Jh9YDy!0F|CqTZ!`hiXl#I3}1#R5y~-=CB@&e~%6Q@{0F(Pp$s>qu3Zx zkYiDoeV1S#3S+z*-Qo@o_r_abjuT}B49Qjw$jqQ)AEz4*93ie2Xh}sGU9Eh7*VAbw z=%@8wy-DOPvbF_nTB)W~A#H8(^AM76r{8USd#1angRDO=aDGX3=u4iJR1|mK>;9aY zX!f{y8~&n|WTWvOk7L}u{%Zq@$W7a;G0Bly{U{aXySJ_WG{x^Co;B0UlIf?e-*x?L z#wX5{{P@21&q=-(tO&J*SK(_P@@4?1p! z8;zEh+#C&RUeUDvw*GD6l=7bDJjgCa>&tj2ww5XYJXcx2yl}2 zl$x?YaR6t-@K&qw)`MJgqp09cn!MG$kEe-6gLczIEAM+9q*>;+E|vTyEyEBCZMHq0Gc| zF%HR1^%cFwxQ(il1CL3`Orv%N^tMdh6EeR9>Th@5mRZ^ETvpm(=t{pM`FvbE=YAOL zIm&SU#GlP-YaB)RBoWk#=g5OM^WJnVq~KcjDKDjL``TOg*UcD?e^ly@Tl+D+-7BI4 zeNp+O_#1sDyRlcqhx_S|pNjijoDescPa&C1p=@ouZ~NhXzII+rs-15tEnK4v z_YaAh)l~>qwXtWgdi4G}#IgQa&;0ow2I31RR#hj#S0x+6k!}xD!0UbWfrez$TA)DrZ`np1Gt)Git9*IjfbjT+|KfAz%nU z5hB{a8}x}F=atPGJXe|y^R0x76vz3$TKfMaFUA{) zP5b(6-X+(8c-q;iJp0zyrEcr+MD(^G15z}s{H2kISo9O%|t9c>kzI?!YE505G9mh=w_avo0Sb2y?p(rQq$YmkYM{;^Ue?QcX#E3 z?Vj08o4t-n;R$(*ed9-c=VymHf2A}{mfEGugHFSfCr;j~VjpPRami-B+%XtqC2v<} z)$qQS0`0OzMsdo`(P+}M>co>_9qUlDpNe$bM%GJC2U3Xr<(Y&%)5h^cy}~4kJ>Tj8 zm7@Nio4aOWZ&i}<7V6D|$F{xBXSGBd*{|60f11NbBjF_&{tb7ckVNwv9moHCf;PG; zM0nK5V8ZKYpvV1A62g@=6vjMG89%YJ=7?RrE?Y7?$T9Iw@bxg$zdN@fFWpWFbDlj)UU>~{qVx}_To zIktn2L>9E*jmlxxi&SsvtaA0*mokUK87iP_k-=N0qMdtkk*mY3qbDdF-#{jea)!^m zwR1v1!ph%zOL44YFt2=8y}9v3Ty{Blst@i31U zL(G+rG#mb==>8x7g{=#f1)8hPOXqvQ%}67y1p!U#@*5vYjuvRxMvViGeJ?yfh@+Yb z27>8@Ki$&LL5YvyVAvQ8_|oVWSD|1l*3r-m!#oMBOJxzR{=IG1&7aHaryBk43c>Kdy>s>F8Zgl4|I1hWKap=n(6yt}dQbYHG{9Rl$c@~6NE>qAj=>YGr@^cdFVdeV5 z2V%+(D=HGqBdOp2BO*B>34H(4ED-|ibx50VvT(U($ioC!rbpFFXp7y5eMW^bg2%>kdpcg*EtN9b&{&n~N{t{S85GUJ%U+)ud0$r-@D@+vA z4F`!SM@uv}XL?NN6+-=CQ0XKZlTuMxhD$6d1QP37bH<&BZfKm8@8eFzb8_%0=iL!| zAjcZsfOYFrUEh1;U486}!`uGNnV*7Cd}dEr7vul&!H>MdK*ak#)8b3W4cIy*J~6x3 zWw%C3j4pBS6%r8g=5Vt0f}IGe%4wW5z-DWEvh66lAOx%3A*hUB=WD$0_%& zGX0%vhCRJ!NJZ-oGODJ8DIRKIrm2hkYG-Tc%(6BQXl7>F(6Fozv=M^__ze#s(rfFT^n;UFE#G z39p<+9&T;B#35>Mxxnx!ZIClC4X0R+m!uWVtAt+qnI2dxFBmlzSGvZfB9TZcbD zeGTOeKl4BSi)RoA>H4kt&8;s`3bf$?&)y^)q*&b2jMN6oj=3qMz(G~XG6LnH6BQxh z_Z|)*p+WM=O2n06K)B*I+Ao4oqZ&NZc1iL>Zvf9KumWBx7X0XVq^Ert;i|Q&_jejH zdxtu{yVaZsy>h44DJZk|)$w=#+i`<`iF@wuW9-tP5;-qngjDUc_SYZ=J$ws-`I3m= z4EBBa1YT|)QU94|8XRN-}g zovd8lyE4^Dg}GXFXGWUk;>C-!0s`uptTn3*TWrSv*%pgHI3O8u?)uvb0Lh8IMZkjW zE*G(z{`(gmX;v~+0*wjqwQJtZZE8YC(MKm40R&KIdLNYq~1UJ?Z4LeDpCsHv=r+8^(_8eBeU>s z5c1%^BbcWsw(6-y^ZE#+<$io(tp;%_pa+H~_*8sV3V3(z>^@tn7Fxr{a2(uy6O=C`Bqk;U^G}FcXS4X?-Mcb!a^Z+1 zUKd)%PjKo?H|w`UGTQn0zF}tGW7{5i@2$)AE#*7UKgd$Q4hBXlyyCa=g;uhEgouX- zo3gg%C|3GA4t_*ed5WENB{(wDw3c;gX-NU7j`~9PyeC-Rx$W579B{o)>H)IFwN@IX zM^+KI{u{j>eZBYR7VNYhvu)patO)TBV~FWW_`gr$Uv;C*5iT3NrNv9YlK#WB`?HP& zV)1;qQ+12m1iLU%QdZ&_(3*(c>HT?|U$UEFOEPX=myjq?dbIRI=_C$18Y6}Qb0Mzp ze&@mdT9pgFT<3oR8TEUlN!7P!T=b9k<%wJslxkm|{U^Pzml30S(kFWSBzYh(L7)5j zhJN%re=h$HN9-Urc$l{jb_3T#5mS<}`ZgvV?;|gd%(amUmO|WCAl0>+Bm;rXOVr8u zzkinnHs~K|)L*aqe^?}V8XiQSj(_X!?v`CUmxbO5dEnQHZ zC2S~XRGXqC>saCBU(3v>2GSkg6K@?ZjKnP0t!3k;6aRRbUk?FEu)e+TX#Gts{vEj* zRUnub3C$iNAV`S)y&b*uspHW|+)(boy`w{Qmpj?etK}K8lc;^i)9cSO3Jwg^Ww8e} zbM()1Pi@8@RlUH9R>{$3hLdobl9Gjnh6e4tClD+=48Z{qYb~#Zg(%DL`idL?eA5Rf zp;3CE^!9d5SqMMw-!J+5U+CB1Er|_E(j8tff9;nsxQUOjZ~nYdGz?q_y48p{UO_=2 z3HX6@SH5R3QVH72fLc$pw431)S>E#(FRc5u&sbvNkx=Wnt%a4Wf;&E<0hM6)MK4Lg zA`53yy8yx*`aD!C2wKM%st&?|e;eJQ42aJ41F+P;0c1%xo&|7aX-25m9^fM%2&%*F z%muN9MoRFgK&B2Tr7O{YN^RTy>mmO6Y}Isd;=OAa{;@0snaJv|wR2h?`7np8e?yGQ zz3;^-GEXUh@?Nr(Hl{v?Wk>w>SfjQ-6UYGBAPJ^$B{ZB-)_nu6*c@QE!&wQwl(%4$ za{Bee@$T;LEF_#_GsTSj^y$;J3{+xGDiB+xV6yyu5uJH&b-xs#$4roHxH&n=qv%-g zkxr@trNQHbKb0s8aFbhId}9B50l8m>kFoH8^w>WyAXh~7v5~U+-;-ZS{EpJO57i1W zJ{d|FkqR-GEj9-Hs5d3D60hrUx z{^#eWC+u9N`7oMQ4My=zttBQTTmo+gr5Cx^*hMI=^Sr`zMj3Y|NGN1$mcSc_ak%2( z5GI?ki_o~~REY@*_0nrhub6;2(P>grvvngIm-1oII+!yA9Dfa?XLgI<_QbzMjRrkC z>eg|1xfLL{Y-NSa5r-4lXNw3+*g=l`>0jsNci=&xOI+5))CF~s3})mbylT)b)?r-8 z><4>GIg!n8$5vDrpO|8X!&X)=J7FXR>(~mj0wN%-jqwLaoGC)n`uPIukKT)bKm=-5 z(xO77*-qX#5-5;8PK^vX!uW!3B=C=iD5eeH9+U91`OkTXXT!`ywH8?n$Up(4hv|YD z39GCDa&lUjZ8 z@$7zn4gx=^sGmIR2AON+tsMfqye;6aUa!>G`IGU@n>Qb6c_$~wznp*Y{_6hr46Dsg zn5JnuudKb@xl;k6FB{QQ%<*9*KPhaTi-qM ztmpzz!1lwqIn(465F1E?fnNRI_cJ^EC2BD6@;tM@#J|^J5o7Sc@9IHY?cJ;oU^^*q zZgP~YeCi+J$J6r^0{sz$WdC=0#4vCfvN?7ew3)%zPSzDbfYB_$E1$h?b^Stn7(%o(yb%2Y^(%tJXO zQP(^iJc6q3wI$eelR_k8p{=j`pAbFc4j-Mj9+YwiCmw!J_5{eFhmGrgYK z@owu}r6;FUk@okj^s+FZ^Uy{JAWRv{My?l`nZ?6ga3gGk2|gV@LW*Wm%O6fJygb+# zpHK)x(C>gM-ok!V-{Krl4Mg9E<(z&&6&6gdf$5r4CZnh8hM?4(t?g9FQBw4f1kCyf z)>QKsDpm%w#-w}=^f?COhKG@Wk z#EcmjsRqgu(T}^T5E@1p9eg|}3G6dXlOAhx9udk-t0l{m3Rx>~)%SpHzZ!t)6=1io zLpCaL3zW>q>I0nz$EO*XGOAu)n7SmHve;b)oFC7D)wOQQt`EpL9>Ne|y|<(ClT$sf zR0f)WBWNEQ>sdWp1T;Ml_nxTRxZva;+t6S!cQoA2_lO|+zr|Hg?~&a-juM0+a)fn3 zNg4(%Ur&Os72~lJpZ<7e5_;nIZ*{`~*-3*@pynA4dJaW&&%U(J4KU!gfaESR7uiaE zD5k#vyP?P#0bM8AGsl4mhW{00OtV?3gw0T=ml}V*1s)ouBXlm?bOU>Vh~*f=nd$s@ z@6Oq-z$it;M_->4cFVBgK4wK|!oi)Nv#&=9Mt`OyE#AGgK*(XlVHChXlc!@!&~aCSnb4bxEXrN!||xH#B3I0s`1 z-TeKJfiCMNxf!w^6dB`Rfx$(K6YNx_KY-amE2E*l(8n4!SN|w!FKVgJjJCF(b%NfA zCHR!try*KeuYsm#B(cvq3ZR8`;?+x&)l7J)p=jxoj*Nbz_KR2i=Cq0zCH7#sjkHZS)LWMCYN+CIx3&?%F4%BKP@etQupEx$KJq%SpQ}( ziK9lASAnldBpr%g9LvuQIV{1=hd^%Zqi79p&aGhgplowZhP01>nYkftvU??U^h@U3 zfF3aSwgth_>Fu!1x&Sz7l`hKhd|0P&OnJtX=J4E5Ann}qm@v?|HyZ8@Tc&N705n7x zr-cD)(qpz3;C(!ZPyjAF(!&?6?W7^R*AZemT?1L=^t)Nx&%?O z$a~a(H-Vm8!33(q!XEnEOm15wrmus|aRo3adiD&*Ecc#S&pTR{1+WJ@s%Q6+24nk? z*NTdYLWX{FtZo|MX}F;A(*$E-k-VL`2wKR4=Tp?h_#WY7-GD*<@F-u@tweg7_ ztS?cIPXK0Aj+bA>8!}^`-2pbMMt#iENJE@&5^Y>>^N=7c`?`<#P|+S?u!N<= zhHrR2lZ>^v4J9Rh2i}BShsf)Xijx&!x0>Sh3g;Ix18oqfP3bf}1fm&Z$+vaXuP(M0 zIc33sXWdBig>drJ$tE~yxnSFk=Io~j$#6G!YQ&GyyoKbDQ!v$+G$>|g@L+IihQHah zS$Ks|J1OQb0MMa1Hu(3zfl}rv8s$$dz8 z`D+z?{ICxOn1sA`t;8<_VHj7i#B6xdtJvmaLXJ-jAHxx^4Y%yHA6Gkb4;mw zWvi9wl@Gg}fC0DGkV&oKr=p`{zP)a)f(vaQGG+)`(CPYlgfj{jnZNQ_b8o1x11^}T z!fd7*u-COND$gQeQPcIfXB>5{G(FLFZDD{FAp)xDVbW-jel)X?z4*~W z1PJyDol<&lczi7vt#eBH|0kO`rTt#vJXfmT*15?K+1Q1WfB`V!pmwc-qo#P`&p24LPmCencF!#>;Sj+Q^T z^r6^i%xPb2V4e0IpOYPtK6(iH$SMGWO@#b6?2OQpm%y5wH41B?9zeJ(I=8MsPqqyh z#~FyWUJv#rzWL~%@SRj{yi=WUM9$8`8cPwzf)b1n6UlVw}> zF-;d}>zN%!*h;e1?iZVfgu=LV-L=M-Fr)eKNullQG0^m=kih9^z2-YlSWamHiOV5m z+g9tNODGeFB4R_C8gIDTBqIap95S+~%Jlc58_${IJCeRO_;hL;f$O3`Hbap(oQa^` z_zxsUFNBjYrX{GQ>7Iyt(bAmEplg2wX&YU11Qw(3MN@TxOP~foD)t}T@R5?Ca%&JR3gFd0!wv0#>P{&X!FxNwuqj7IY?!YKnjHhg3$w%hb`ojiLV$4w41v6| z6nH?z-GTSGKX|q;iS8GD%|@I34%r*nVP?Zia4fV>k+5&N@;D!Xq=HK)J-2QzI(va7 z`6PoD7%q0*gJ<88Aw``KL!pnc&8L9i>=4rf^R6N%4*N99sdYXNrt1YT)GWvnw;$oR zgbCdfOZ-4ULjU?Dbv9-IcxvxMFK_rICX=P&Outg=6$Bx5#wjZhA;=IB#N*3jXBcCd2d2!f! zwks%~-Yp>xBULM}MNg_U8>d#A=Nw8?HU^T)$Zk{(%qMdpMkTC?TV}D_%l)&R2$&`M zmxoZsom79zPqN+922pYf=@ln98#Ygf+Z=BSLJn@7Z#mdqkeiA?1d${WrHb?!rp395 z(e}J*prKGaRTie*a+e2*kS|#r@rUmsR)~S<*cEJ9Y#E~^#9MS!*UY9k*kT#3nAANn z5Apzb{~WRxCY>vN&Dxj{2(=%B(z|9Afm^LRGt$z4ehWZ>hpDas6+phju11t!B@Nbi z97otj6jCaHk*Tf8&_oZoJihzvx4J%-hsk5xf<~6UA>(Afs9NRyb{%lDb*yb3n``Lzt8vosMEPN5RHq%EbOg{&Wc071;8z;=0oObR% zS(AG8%Hg!jyXonTyM`5D&8p%Z#WNy{1+^+oYg8{+^Q70(l$W0WJzdy9@uRfc+uQq& z`#xFl01G#xZXMVT+xYe*co19_js~vkvd6>eut6>^u70)^|H4%+Y8u1KQWmp+OMqM? z)!NEPg##Vc5IX#|I`k4sHY4sd1<&rM2LoX?H{z*}Fv)$GzN`kSCu5(Ko?TQI94#OU z+DmoItm&S=4|A$XX%IQTaJbJIC`lL&mvTgk=>WK|?5?s^j1I zFJ*!%Jc1xwM7TXe?;c4w5bpT{%R+AcGC1N z_e1{j>3!Zd#vfIsHSDgFlbn5`DowVxgXHX49ElE@&e=OAUfyHR#hk{+rBBRtbd+>P zbtsE|SEuQmgOrPkrd#scscGoX5V(cbv&?C}!Rn8Dcbi5sdp!4nNtHfwmV3r@W-FwbzUdVOQTGFq%f3)QQ*oS%JuSu=5K!siPK+i@Sk@|)%6-m zn1dZh0?>-qT5a(8^Aga&^*Owxc2c3W_YYzr7n{>*L!OR zKjTgg4e1trTP5eI$nGco^)WHuIJ_y|${Y#5&pWfkQjMw!_E_#^_Vl}ZGKCvO@2=W< z<;AwBC$Jgwc3J#eYBAm@*i{z6+wVUMOrj9Q()2lKDEpN>t4z8XgsKK!gJ|uF`m0`PRZ7pZ(+m zU&w`-Dk6tW9#eQ$lqOO%1EbwvSA^U_Gdt~+eWpgn#FDdX#TI3w16bZYB;lDCPH^Dg z!e=xINqGO>RLWABh|ik#y=SM`GhrJS!Hr)GAqj^aBP-^&nVxt?YC2Ckcb%?ECW7l@dnrnmj8fF7y!aA(nyH!+4Xampk~PXp;ud8+ zJUpmR74@==pUZIR96o-=7#*)8eOPjT$gx90Q&m!{$I`%7E*S1twLJNT;h0qiGwo?F ziY{i*GpFT6&MPO|RcbIYC+>5T(J%QKdz9@kxL5M?cY*I{Ip)h9cGqEz#dpiNM)`pK zwg)m59}98K$$exG1sUh@mAVl(o7U={QsPhoU+Fg0$#=qXsUJ`^VA4)GGTBJPzOIKF z$mEG6(L=NhJ)xC->M@HNi<4oc;`5K1Dp$=A-de8T&Nm;|r#+H;mBG_*73cv3w>?h2 zx@Y+Dr78+>&Fbq*mw*;t zt-K%wC8#UWPEUC9nR{Q*l$A4UkQufWKOUo{v*-C~DExitT&uWi*!TVXi zCG6Nis5xveowp8cK|=_4(HRuD?emtqlx(Uw?4cC&<*w2rf~)7G0C(u0=v!NkS$mk< z>CmoU7Mo1IOL$7I@6pBBHwqd!v)uA8bi3zgGCZPqjAect>1Q$Wo6C&ZTRLAM!kY;$ zYG4RG)4MY##?iA12)jdLKPY-1GfF+xMe$>~x^%hvE3N8#j-YX zccA4H8U;Nbgk@7K%N-Y%SUR36S-$~Oo-%28Sheg3>1jGz^-3%9E8|&pHC+}xh?9tol5Ow{{_Cc}k1!XI_6JfBw?Z(RtXL<&o z*h4BBP3V1A37l|hCf&8oU?MQv+!T5y%j{Z+ZejZYE%YHHOX}N9OEOsAHFPI7~ z#=cV35MUbJwRWJF2kczKP-`@y8A}!Qa`ZgAJa%A810n=>y_>wKCN1UL_{xT@-3?>{ z8G0BDW@vPj#r2z6YYN0T1b3QB?UhN5E2mmey=0PqnD@S5mK*O5 zo;~{1J#{{A4KSkw2v--{p0OVosx1+c>*TMI*=$^_#b$Q7i28 zYJ&SI?O-eg3(-g=+;Q&=na!3r!0GlR#jHGV3z##jblEJRK1|du9@1>KvX#DkctCjG zi@|j&D`tgvo21qi6bJQ*bOmqULu}Kq?fv_s^@*WFjVDL0rgZ<0Ok(RlwcY+H#tM*EH7}9#hLhkC=nxf{?9gk9gq_$SFA#us1 zs?Aalv`ND6A8qv^JdFSvFN!jmna|-_BhFMkT@GL7Z-%3_K zsgd`TRFVRq1Sm*mp7V|To(&I-UEW?kJ`QQG_qO6-POr9;0QW;+qcnkium$_@;VNu4 zFJg8d92?^o%f>&Mbsx=fp>ulm>us6@N5=}pHW|LJA-zAoNaqq@XP{wT%5!+|hV@#jmtPF#ff-XcevDY-|O(V-#ke|*rb*w|a|Z*ASt zsHJBa0u15BZ9!E*?VPllZr^xrotlu|#ei)yU9w|JO1`)|!)A*TFO&dWMWbSE590YM z_)rxdL=Ua4t=;Dp3Y8U636~yJ;=csP#0xtT42l47jGIHgf)stkf6t%Ky8gq(G*ZnO z-xnQBn2Exr11=+(y20=3+S#we`m_GKLXZonn>t2{9<^~34OClM3bwtAQWTdsxyt%d zlxMF*lxx%mE6unAFwjO|L~)oTe9{-rW%}bG!Y|N!md)xG29C=an1vc47ZnY-Bt{4f z`NR#!AmgoMd-!x80ov()4!0wv{e5&~q=o^jg+0pZ#I!?$B-}AD()8Qf7S)v_+~hhN zC1Qe$4J9a<;U9x>v-hEIqiQJGBx|MAe#d+hid$3wuYWfNp^g- zU_X1c5D^g~MaTPYxC}-WQkyNV8Xk_Y@>gAhrq!-VsR@WzPeoHVWCmRL3M7b1bSApi z#WRh-v}*g};4P{>qz7rs!WLWR^H_!Jcy(UM%!Kjw?kD(Kw2a-Pr0CwI#Z#jAf}ENO zzwL{s_vDh;pi4N%U3VhC^~%mef?G%eN`N9{S$&~;3BX+KF3yr*yifKkJk&Wz8hKEc zB2YxzWAMk1a}!r|mdKJ{D%ivFrg>q^@7`xj%2H2M z&3vhB&^>&SxcVHDa!##eSb3TaRu+9=YjWhb6nV6b?J|(6g+h`e;$-XPhs&anGW^uq zDsq6vBTXdXMH^kq6$l3hp|ksgSA0G{-Q^#HgYQEyhn8a}t97T?8zyCXyX|?KuWByD zmzGK;EjK<;=G<_5H<8;LdvJ;k|MtWs$iN^DA4RDf$=%YF(9T&hURhx@zmZ!mBd+@L_%Kiy!Kw0)Lq z2b%R+7)2SZXg<2l@X${6t%Bc}hq{9YY;~K0(mgv9(P|ZL2#Wafyj5xo_~<<$85CVK#%;!KZBtQ zNCJc-Z*&bae1>o4bl4(JLBltbKv>r$Lfj1;P;^Pl=Lr1M#^z9hM_&F1O~yMEeDBZz zrxqYvolBq(Xd|$h59I&BJQBR@Penm9!Rs5$S_xxIS;W+E<56e^f6z1ionyh2{TpVQIcV5*{5LedEjq zn~#5&_|ieXb#ZZV(uE}a^e$@xp?VqxvJ{`NdD%M*uV+_%MTP(F6sa!}Wok)B)j+*+ z5;v0p%)Cl7qc`d|r{!+zd^y# zR{I7$6SIG;7*%uqw?#q~jRzYdUlKxv(>NWGMJ0@e zeSp#jo~5{ez`~6CjUULc$@2UYO!QkP6xi)Giu_z-`5q5(3RFUwz&d(RuD8KPQa;6(~}l zz>N>)#gc?Ceh`2pRJNIF`s^!+Si{6N;%9=d@aKJ^y`>p$B+(S}rk#krG($DfV5kjy zuipqnO)Orf?0*ky-F`gtB_DV4qg6CDH9cVaJOoRI^(iJh`KLuje((wbgUU6d#eq`S zboZNlsXB3XK0dn{A58ztA<#1FKBdf;`Emt2NdGJ>K4)5i3_ElNJ!2T|*nKUDCbxWP z@hALB^lG<}n>JssTB)Ts*4f3S3C1G)<Z49P3ziyNRk-o^fTD&VbXN$K2^Zt-o&5r)+3uyu9goYkmGX{oi& z;*xQ-+8U0Q^+3;n1GvQ(!@r&u z>*SR@sX$%w>5V|JfKF)L!oq{;hf@5tA(+s$@(&q)+-QL>>4Gd%%iGO$Rrn~>ugcMK zgdS1YGeBD-I-L421!w2rK#3DS-7ALwTokFw03OslvPr^UEbmg#aPynYpz~H;i5J?` z#hUS7fVhYH(P}&wpKcMa+xN+e!C()kZ?JqK#-h7z^yJ{V#1adm$Hz0-?QeeOE)y4- zhO~3!83CvweQ3rS&0N>SYIvG=+aH6ODLmm7LPSkf>oAJ`U^oR1f*43D3s}A^Bky~< zIh*sCLI%YV%fBV(XY~W!?cpA4=4q4FX*reL`UXX3Or7U;a6aFjvkQGm#Rt2(I#(Kx z1Pe$!hujYtR;%Z1CJ+Ae&|Wlv`xDZ+4@pnA!SV6>(rM_>7lVB=12`J|to^`&b8D{eA9Pr~8VpYxN)2%nSvf)9=&;|Rj~m@EHtHtc=`votVED4Lvok3x zOC4oWlkVw7Xd`717}EsCslP5N5|S;2%R4+ok~f5p1nT?e`Fg3by%EU#L|OX0Vx_uq zz&-cy%1@fOjMd{VCUT1{TR0QUCAi$uwNCd}D*jxTy}JooF&;YQ~`v`;$= zxkZJhL=_cMw2D4wH{pYwSkFme&yu3IY}sNCE`v+55R&p?TP*N_^1oPX3R<&6v?Ss0 zkQ*=2MfF?mn8n*_Me>dQFcToWzKH!%$_U@S11NYmgW%FI9enbn|8_CnZ7F8Q9g=~Uwf=-sn zc3i;6dJ{bDqh&)^BJ%a~E;$wn6k|yP;JA`D^GF}{u?47_y|Q~eBQEVIePVB>v(Oi( z&9Cg??5L9|NqVfx&DiGkP49!@)+NRZpiG{y>BVShXh@!gB}YTiKR#pJua}jP@mz6n zu{rF|D8+}vrVIoRl!}CNyYx33&N1%y;zniV zd+0c4hq^h9?)8N|E)!JrO|$zQs1JNBbsbOosgQI0H*}2DND}2Sx?4`Y9y9T!wHdi) ztIiV*bgAdfjc&>fB{R4{!g%a5Vce3+fjo-AfAuI$+BGvKUT+!u$y6NPo!p1%i#&gtPXt|2Cf9<#`>B>Xff9s5NLkG)XpCRX z!d4(LverbRf(!8GtKBi)#L>+ zc)r)xg~xXP8YquvX}v-q%f_{J>)+E?f1wQgmuCWY#T7Z9*oIxzLzx(sG(tDR)D~+E zJVQ#6nhM&+^$%$$0u}fZegy>LZjgj$`DCE7#%Ec~$J1Un(pa;c^O&D{6}oLUAW*Dv zEzd>!b)SGj)0{_Xc3*D8LU&aX>fwFBqboX@B>3;DRYp$<*yg=vFg<)Jx-dYl8njlwv^jOd* z&Gw3M505jj&q)ig-uX+HE+xhF`mIpMH?+)^PawdvtE&s~I?qnB%q&8~?%tRPv71&6 z1`)Dyqdw1gZ5uVYaj83>*W>3`u&IdX82%TcgH$|c6YM??_<&iM`r>CkJ6%_{W%1q3 zFq*P!1?S~N^Z1u{?Ju1i=@K#xuX%T~3&wT~H9hw&FH91YmwM%qoHI1%{VnJGkDviG z5whzDUbqEr83!Gpv9GGbf?bneRWEm48BD|IiC^rza(hO7aZxWOc^AFhYESjmgAv`r z8N1azOu{~sqKB1~&3{W<_NPS89Ph$cAE>d@f>;W?MZio=#KY*75!211g$rA;p*wjM zR7v_n)(n00Sq(C==+YGXGZYM~c3k-1Vp8AwS?OpqYVdP@4lq&wzF4v~Rf~y}6Wz64@bC zR`x6d1NMNPehO+TqC|+6M>b!`2RkHnvh8QJ_gIi!YoSYHwx0?T#T7h;P4CCfqD)}I zj}$$Vzu~%v5NzN1UsxgNm|js(*Ufj-5gq9$na*=!r@@u0_R-c1yEHDUXx;L&UlZmo zUAAKD3UZ7%QOtg6{xgDdtF{$1RNfWZu(zoui_uY0QAu%ep?A$Qr)OsRy1cx+ zKDD<;Li>4x(Qt#kQjBErJg%d_)_?Yckf??5%J(k~=e7B2dY`y`>E{uQCa@`3U9kDu#oo)(E6BxZGMxDv}hgv4b<&+g&t~Eq( zIKT!Z=u$sB2*Ut%2SZ_hBb4(roz9LBBIw5msO9Bh@`P|n1!iW?K`Ggw%`7hP!|6?_ z0fi9VotFxHOAi*Wu7lf0JbMyj)(oeCaDS)7H%);r1%grfDXYf;&UQjrGFm$Q^R0&x zQjSMT`j9c&Fkv(q7O(wqOrkZG77{74EWqlwl)9tNy(5 zG}LKu6cgIduNxXv>S*(N$?KxnY_;IY(Q`2pc1DjS$vJ*(qS<0_c(}R~;-jRzJYnr%^PCm4#RQcYgKLsdhmI{i9vIX{bw+3DdCH!C zn>xvBQz856O$on80P;P)G>~JzHPOK}cl3tM&%2UgVa8XVdUNRn2pzn!p`S|@uO1Aq z3KOThC9>kH(3q3Qo7NfD_DfSBn04|Mk_LFjyyFQqpAy zvt0uy1r-$)!0t>Zmv{LdMm72DFs8uA29WjvCzGuMokHGNSOa=51vir48`Ou}92)nb zz4Nph9@3)Qd1+nyUk`f4559^dZ(Qrj|u7hq?OeF3n4?uXc-GWia5di)VHm92`3*k@HodNVYHR;%kcxShb~%q$(dv zx;a0FAc-1hSGi5@ETF1yM7mmxg9{&bhKP{%6Vgv1QSv_hl#N;PSWU!0MkdC z&lGy=C0n2st_D)Pls?`&=_>7%`Uh~qo6QukiWa=(~9~DgbcB^Z; z`Q595roxBcx+0L8JfuWKw7vX(D#-0b-vS>%cJ3rWdCrRgDe8`D38CoYWGFb2aT*81 zk@9+3+%CmO-Z=zcj38#m!}5&EY^3~}Az_YbT~)=^?z2j&Pm}SEr+g*zG-a@NxPe>-GHw>TGMUua} z=-Xv-!oTo`4xJEoW&cO;jt`XKcNXnl5mS@iXx4kFpDVdO}%@H`culX>|RDPY}+%l zodo~Fs0O$7d|wJmv0(4!@RW)GJVj#5jNM86kdF~5?Drjk^@1B4F#bgk0%V}7cvwDn zgMJ}p(m}9h8+#P~MNZg}GO6DKOFaEzlg9pz1SX=J4NN?7=fHl-#$Mh}a55JSk<*6U z{one0@W1z87mD5mum4*koYs1=^&k3D{(l^c4<+u2>*V`BpUt@-ik*~CZhYWcSi#|> zp=(h|5Ejjk=(P$%@>9Sk951}Pat!xB1!S9zwNPI7k*)xl_XN_x_VNvqlIw(GB+w%W zS31Zq6&^T>J_x?rM@tu$>-VnvBZYvxYupkAGJI@eoWW@oYAjrZt1`rb%9o zmB7wqD|M zVyOx&v#3eJO}IZ3ToKAElYad`_laF)CjbZ1QJ@qovZI!TThMyfGS9YMe@ms_VK;%y zph$hII?($*taNoIqlv$8MC|}hw~;c~k@82XPFADre#`98Cpk^{qXdYMw;fzR>|?`Q z(EX;5b?!_i{=o&XJzgAhB6Ldd*jx_McOF%xgtm5RZ-2~s&Tacnq zlWI~t+DBPwEFqQEq%0P%XH{@y6qqmuVTHN5J6lc;-6KC-&34Ww_mrhprVr-rPdnp% zr;L|sPqwF8jjCI3BPVYJD)=Y}o9~xK5AAC$M5=ngCbTZdGOWmqhU6IZWOLZt+Xwy- z%v8;qx)?*BctQ}Nz?=8&`Ct2ajKRveZ{vnf(rQX3kU$~l zI;0-+p(p${wdhf|rS@)q>Pc7=t^%_;u8W=H?qPX>brkQJ-RFCdF@{V07aC5vLucS( zIj7|PnB;v2A5)$D!UpZ^HiJNYq0GXI!3d!QSyVwT!=tEfbY zJ57F_4O}vJII#DUovL$7VOI!}=abqS6C-MG;l73pE?v6u{>UJ(U??t)WU0I!c~wnb zmEKiOMT4|--W{GUsCVN(%MkS}w6fRltMW*1qST5xbvDv!8e^N9g89ZQ1%2x#b1#Ez zjQrTD>ExL2Tesc$sG1`*#+lyd3r(QY{+Q)Md9GRx1r3}=XlNjmW52GF7=vIA-FIP?gNop%{4Fm+!m9(S|;>1I!R zEN}WP>nfTBM$`s(VCH|zasJu7T*LOeFrkHhO1o~ExEzHD;aMsYuC~Ikgv^hF(dqjb z&LXpOcFmgFeV%7$wk-;mOauzNqKyv`fp z-=T%Lw&&3$ht?x2%L7s>4cdHkA74~@w6}MKt`3*3@|3#zU&${^0S4~`L zDvou!js_0{7k))|f!JdGVT#0Dkjzh zF8%>x;=b^%^a*&Jho3Bwq(eI6loyRFTSh6k;wBgiT^6?@!yclbSLk*35e@!w@;7N4 z_7D3^pWIKWE`NRTn~87!;6W?*JBc2$j0x^e?-dLlxG(pzCQ?wI{rJ4O(NUZ(+wX(0 zFY}FauOS7~SZy%-%GGM(c|8mqUcdh0%T30Tg<9*nXE8tSyp->tod8KW3VjmXIC{6h zCFr77Qd1l$pII7TTOHpmd_hA&zZw}x!=%87lf)=6NGwdzJy{qrm5LPJpXPERcSA(? zGM8fA5EuDU!WBCiMRV0?RV*ux4Cr+)YB|?lHK4av*Dzf0^_cgCX;7#>NGTkXW0+C{ zjw4JP)W~hSKh)G`!}dUTlb^esHrR#7l zoI67%KJ?-t>0LedA!oXqgsRlG84t%6zpws&f1aU~mW&+)~6-dKU42{4R?k0o3jBer=ERT{t*{k7os~0BPe!IxM6Uc33UAS1Ex6DG&)28=-+68>Od2C@R;tFan9r= z#6r%n)@$00fth5!w(u!YQgfQ+I*w!z7!y@8+-Fjznl8lIW{*{PGU1;VME-oVW<_PO ztz0eJuuMz6JqPzEo4cQ*EQ4 z{h#U+yy z6GAn4MSXk=E9WY^f!pXtU&P{dC5F52Z||Jodvgq`LsNI=)Tx@dQB5r^VKJ0UEr)KQ zVZFOy$w4C|;K>}T5v*t48LQEI!i8n5sC%LAWOrvAg7F+Db3I-DL4o-l7=th7W47R?jh28366-A2T*S-VfsMWMJ=1)k@)pJW=nG%F_?=dO$OItV0(mXBr z6?WNjUL|lkPiv9%ff+LniFnRQk+Re0@LyX1uNL`CU-# zU^@mAUb}mqzDS*dDe-v0x>M}q7Q9>F(5xNCHb!fS5LkkZsLT25)LdiXKxSOrXR~6W zka_amQx||P$u0T7&Ku=)a?dl|Mz799COFjAroa|ot|FWJ_faJrOY&EBdqv(Q6|wh@%+*iBarA?(8~ zQZ_r~SnM@K$BU+t4RuSXZ;GGUiZz%?){Y-{pDQ#^jB=3gVXR`Rjt?_9YI! zIn{6bzG2GiqW>>sGi1yFf+F~OA!70BRBOHa$$E*3*Wta+fQh10#tfYLLKfUsaz`J> zB+=lO0Rz_4hydY3O?<_ZHbY;QQ2y6HV$1la1aI#qEGDD85`LYTQba02nCs<$q>W>H zMNsrTkMdR7l4GG7!X2&}RkqZR`6e)=A;Y#tniu-~a2u}g!2 z)~?3x9+U4m6NBNrlTuQ6R)9X>Ku1Cwrg!-IQc`ybC9ViSB1>wrS~u%>O0p1S<<8k$ zGJ@`9vKz9mcHR^Rb%VrvwI&AG11Id-%oF2*4#DQS_6$jQz8^;r56rM;A^8=EE(G0v zoMDw`UHVc*Uga;`{7@Nj$cff&!+HhQ|0C-dtO#|Y~~8GQ0*k#zdmDq9ps&@}L1*opRd)2oSZw@pdQm4`%!%iaB=vB%}bB?N!tEd>zU26bUb3BqDU`iDB=XCA)w**z4*GYu<7@`2I15q-|v;xS436|l!_xE5ZA5abh&;P z&S`}D{rnIE(Lec;UNW0Jb-uR~|H&!nG<>md)Tw^YK40&ar}P0&vgeMa2r%BWt4 z*~|AFk>7DDsbW(#f=xD6EZX)oOQIbUI~hEkR)#S#>l7jr?900b_N(j&L>fNiX<*V}n;i(xmuwg52LEQCN#4{7cwE#QpkuA%jR@VC9tx zh}UHe@#{U!6{sLKU}`XNSNl0KQ9f=o`Tado)~-*hc&lU-&3nMEkK9`(^$rQF#I)SViR?4!dj2iy6~Ntr2qc#2&G9RU5BFaj#;iSd08VZFefc(#W_e(C zkj%rexm`4YepiM*B@IFj;7atcUqK=gCD&I~6zTUGx&LjnftC|~Gv^~L<)nPdB72m&vPfOrHR7#C#pRGyR)eDd+b zOx{&@j{d6H#}kO5MwkHf2OWjvOx*uIk(YD&sf{~urdZ|=)!oN`+g@ofxJ49K)ldoI zlh5?P!JM&{aCb&Hg{C_OB!yWo6d~ZUvc61Y7om_#V{?!^U}hWj<=tZNK$N_Z_#J=< z+UPa-^{E}0p&;=7kPHq`Vg@8f_b z@lmh|pz;H9a?OhuK7T@@qR%aw0t60(_M+Z@!lKVHWCKcgn8!;KnH#;e1L`j+DfSRv zCPJd(0}HOo&)29`sRwRpOJ~AoT=Ah1a+^}8%T0{(_QpzACU&vkRVC?XQ4HV1cf@! zMXYlErM~~$tDGB5)Vk_O^T1_li7w*l5u5Z=OC&;#-}HFw(-62!9u_xzZDjj+5)l(H z)0=ELAc_gW@vUFh|B+%iQA{>BQ2hUd|M=h6GeHy+qL}>0rT>pwYlvb(6ceJDASXa< z)FX%hkbutXzirebS`$KR@^#I$o7xhE!ZP}-tj%0M*YMO()8xS4&iPly;UyUvTA_-t z1<;z5G+d1mJ48VDwlSdpGxoj+ua55}?9CJ=AyMSoik^8%5JLRhTkw*Q)HF^ICK(|V zOn5{Z?o7Zt`{!qF{2|m6hQ#IxKI|)WyQ<5RC`$1D%Qq(!8wF`pmYpjB+WyJG=E)V0 zN;t5&F5V+-o;sq00j(oFE$)#TN}Xm?84TPmS{yG6Vb5;Sb_%RKmuHgirsmzS@aoVY z!iL>0xZwERxKD34!vw=d6o+4;MHGj1ts#m7Q5^7QzKG&L6bGU>5Woxs(-55n(OKZt z?}*|+6bGU>{8hsu2AcS1L9`A;>p-*)_!@yEU5JqdF|r^=7R1PcAOZVlhL&g@h}Pl% zsCA&KH*frd3jpsy{v)8o`o+58BGxZ{6}X7vKokc&KSmS>qBs!6VLj;o6VSo%60z95 z9s?7t1JODVtpm|I;H3nK;y@G!qBv~K5EHS(uN)B3IuNY`(K-;V!@o6C|Cyd7Mi#`# zg6J%W&VuMHh|YrOEQljG#EC5MhQx`ib$sYW9MD^Li$rlCio<%8@Czak#epaeL~$Ta za{~zhahiMGK@x}ie_2GLI1t6*uQUSDI{Z2dqIDoz2Ryt)6bGU>5XAwn=0X$)qBs!6 zVPgqyv)BQbY3+Lwg_GV{KHL5J)c21M<$YAc7YJy={(@wGRJo)P!mJH^W~K;3*=}6w z=18=jB7|8R_{;=>p$r(&K5vdh>jHeAdwBgNhsvQOXw2gdbioj3?jA)zW zRC@&cX&d;=t^=Q$jyy@tCOOrBp<8_epV=wkGvkd%nQW3%4T2`F4SZ%#5QZ`}RMsXr z)u2iI(FQ)VI)t!}%Ts4_1s$R|{3`ts#bMnO5ygQh4tR~EL~$UB15q6Q)>lk)7DQ)( z7q$?^fj}J2*;{L&P~vOnWln40#~;KfV?EF#Mj5~CDN!7V;_ydO0?Y(a9EjpT6bE8T zO4^ecbP|J3V$ewpI@gPXcrM{r#6`3YMC(Ab4n*rfv<`T!14MBkiUUy`@KUlwaUhBV zQ5=Y^FvM0Eu!LWUol)yC6R|UD-6Rsl;aB`f6bGU>;I-Zo#epaeL~$T?Rl{sEv8#GL z?M`g6Ur!?t#o<>M7f~FD;((V`B8mf19EjquG08}D7DQ+9t3Xe*4n*rfv<`R?HBlUh z;y@IKzcsY|H6laA4n*ug#144PeME5}iUUy`{?^<_j4X&yk_aXLFNTs|=TQA5DAd}T zG@8WwkG1F{owZgSzD^ZAQpZB26^@e8lj^q=c=I~%JuPf7!>)~%zA#OGhyS+KYYWMf zCAZQ|E4s?{&yrY^eR##w8p@m1gSzZuQR^356wg&h&qh~Y^!<8&gytTppFftDmyH(Q zdaN!;MPpX8mRG~1+E<1>@KgjkfE>0j_m-{=jBQ<6+)HEKvZH;7?Nvi^FS7PIbXjtB&8DW+mRYwzj_Nw7NOa)YRnGJzE#N1KSl* zM}rT|{|){!KlMcQqonMtBk=L7)bBV=)Ko@HRKW7$c*&9#@*#dGlbC?2?SJ5z{}H(E zD1tZbuU(PF|2oXik@sA}tX})RBIUMd_rLBv3q9uTzOQ&J^o6n4XN{jHLoZzxSN^vz zjQ{*!`?r#zg{{Yg@lWb2+g4qat&L4)k>iBXLVu)nsCI_IsOwl~VV>)Jk8kzuZ8V{A zadE5>+p+F4-w0v}{P!mK{F_?RC|gr0UF!h+Q_fSsVo+0yGsArl_ldeLlx8d*_l7`A z2g0@|Wau)(e|^8d&=du2eiKmeimgmI+YFcWwvz}=j>n<%_;z4V7^LiFM_$h$@(tnd#uR;Mf z&w{0x%$w)%uFXsD;Lik9zrR4qMSgz%uAvzg78br3*U9%YbClS0F4xm|ul?6g`C7Mw z0z0-WH$p`qV-6G)*h$+{Qc{?p;NY-k3kF{}jrQRg(F4N&_K*Z0!Tbs|?4Fd{coe=s z2_L=AfLrb#UmeKE7k8Sx?6ff1r&oM;X>ME~m{qD|wJW1!aR^LD@E;fBG6WYhfjQ{8 zk8{QwUwrU_dV+6x^CAecuav$u0dUDX|5b^kW@?~5%(OnbxVhSO`bWd$&z`r#;|w@` z_4!-)&-ibjf{WTqi|bej{<8ltUM!9qrFB$a*GBzShHy~C=DkkiUB#Uk4-rw(*Q=5w zH79--*wl%2IDzm)t=%a;O(4qDh$wfj&IJ#2jn(y~xZ_XkT=&{a7$&_d7u7HSru5%V z5dR&?#!5gy#yl#!4&uv=)$h{a8v3?UV!O`P)^AGb9HqcUjt>mqcwimbB)Z3oA4A*hcW3fw&;Q20m<@Q_%D_!uv-@W*jMk+wO zzJyamOiVAgeRRy#+4=Q&d)I;uNsU<30>L%@%SU=`*-eXM{^~o%NAT>4wE2`+_n9dH zIro*s7;<-k??|gbccFe#B_=zkDzzITGNh7c&|FT34XVsJ7s2d(L1yCAP6-O z#9Pt?L4Y8DBWN5T%V9$ef_Q5%K@cDas&@^D07L*HupGs^xEoXhR0C84RO1~ZP!bnI z&;X7AjsT7TjsT9p*I}p{A!1D+OCU=sGyoBR2tWjwPcWZgK4B3UVE|Uc-;yB+0t5jY zMNE@m$IP&01VOwFqd^cLh_^u_2m%B_jh+D!e*+P@>XnuwcL7i~w^Hju*H6QKD%ekj zZJP%~yyY7Z1PB7i@`I)rR0C84R0CAwgKIpX8lW1W8vj()Amf9Lu1e9^J5+jvPw&iH zvp@9fSbxgNQ3lHH9*>BmtbW#@yT(#JB}yf`t?UviZJxi561IAvGnweVvlhutb=slQ zDfQGF)AZ4eY3N+2guha%jn4i)?xdb9jYp?V(XDL~o=rW@rnxk~p@^mq-37N99qN?u z<~VaxTBdgpg-u?eXk9afmMY=F(z$AEd&A|FWmrFSDmu!Vwpp_K?+EncRNAUDMVvnP za0^ZFdQJ8@$&SYY9EPa?;4lPafCIn*%QgWV01g0$_uOSL7GNweuMOY;Z~!<^f)GTR z;5&ft0KNnG4wMv&C}{-j0PFzl0PFzlKuI7ElY&Sn5LrNE0g(kn7L?UGU;UWl>_8y}NJBxOiID=p0pI{|c+W94deVzyaVeI)(?|0elDW9Y$OR(as_;7GNyESb(t@Nx)GTNP!)I9e^Ex9e^FE zyeM*?1|J}@fXL$SMi%+GsueUEp{vj@Y<>Ro=@oa*7a3E)HG(_1N^D5P9Joqs$Q}b6 z01j9z4{!iD031dePB0e3kqfW`umi9Iu)|O;Yb2l;j@gh0AnGBAO{!d zAS(%3Ni50&H~<^~4%prefCIn*;4peC&#+q!#sb&@*a6t#|C=2+t{v_n>YA;z2zr@b zW+pfN`GzsSl+B;|rN$n0_0KIHjahl*_WrfA_NeF9-T&k8)cpas567rX9GG&ia1YTP zKBm)(*st@~ezv2_zA=TxTnpbytBh-%O}|HO;8|E%JvhUx^5-|VpXYBW*?#O*_3V#? zVy0?Jio~~ujTAs7#jKs8y9K?;2W6VyWX#}WD8s@x@*Yu~1jBaeivZ4IbNLO}gsIkMMq+?$0 zSpDIMoLVIa0~0g|1B5}L1(5~;G5{HX42q$_00C+O!uYUu05Sj>fDCZQhoc;bO)y;m zVSq5?6d{DiPyoUJVSG5o_+Ljxc23UrrTY4XyB2G0f4V*1*tflEpm*L$zyDMOhs+vD z&3(uf9C466t7K(#^98Dm{&9G&UmYb059IoFeq-4DtSzEuIO7oVT&*2#ABY0b*YO6|UT(wMcIjC*JtkX7ays7ew3uK6gF z7?Y9Hvo+T84Aa@Ue!`fTH@oIg%7`7(d16ka@giY|`<{WvKHHahHCpJYNLlEu*TH+w zNnU`O=y&(^z0T!wqm<@ZM*X$R+wFB#w%5~;UU@uQiYdmZHa8`GqI>lIzqe)YO*vug zf8{%O_j_Y+h5tfpbgT2%!m9|Kt;Ws{v2wiOdFnz&M)b97*IXwRCHU6(3&vEh8kvWW z&K0q(t|8iKVSVQfZbwISyhpBo$dnkH#nLf0zd9bm6S?c`Ole+%;xv~0-G;*G!h84b z8UJuDQjyr!@nVKV^2;I2b#k`!^z;;L(68QNdBWhY+UgfpQWi>Ubyi|s%`WdvN~q2f_U>RM;;M3Y0G=W? z_yMK0^=o%$^(bbB;$z0YgiTSM%DB>(Ddds-`aUbcVHc|e zLmxF%HMY1-{lhn&er(r&+SbQw{G)#E<>iAGc0V77Y27W`{i zLqlQ-)!BF_I-nt%zuBYvyiRwE&R8EM;`68rPjPt=lO`(?RprGM)zt}36I@ss=7+b``bsu?K|>sPt8nJ%M^@zghX7ja~BzE(zB@Ve%* zJKiz7U(q1U9w|#mxhv5i4wf5-;p4o6^jE=^RWS{huUPe3h1UBN+#)L|%&V=2z)pLx zSzO<#a?6i8RHDg{IgZvR?WbLn#qr1R864eBj|-pSqZ2jTLoVxY)rYio1Ks6@tnLu;CeKlylIO`?C-cbQXrS5hGK$kLQnQv7%U zK6zpVt>*a(>F$30EEyab7fukH6c{rCxtEW5U8UBJa|Z(42(28r#g@g7OY0FN#2Q8OXA+ebYB!TL~D0_nPf!vvQD-A;ab6817XC zbMTRQo<()6YPjwx;kY&>Ro2v;EOu|W&x>wM>nuv%Iq`cR?Kn!mYtW_#p39>4d1B`Y zmpEcd;rO@5YOArAF&H{l;^ByOne4HPbw=D4n)B zLtvdj)6*(>mXX=tc)d5bH@Lw(GWc3mNdL_OKjV`^ZP&Zn6bmllC=lR?ii)i$6_GcM zC~duI;X=2~;5~L~V{U!&bZJ3wZ?)5mke7N5UCnw-7K^3)r$ynn)-&5AbJ{7oG$`z( zi^NbiOF*nizB? zi1c#Oo=6{P-rG{z+&5)M%i%JI@NZfUKh;eo9b4o0XDAL7HmR64eF)(k$E2+J!pg+b ze%GUmW<)kkFi)s__Du7kkbK(k%t>&1pz|O-Dkmo)&6b@V&=ze!Rxe?VZe}WTF{{je zvYxAROVurAtf1CA>*x5TR>vn+@ow*ZXfjjFw>H=}yEVNx%BcNDa@D>{w}zg|+GS3= z1euPGsWtqsQpuWii+q?Z0-tTGV)-TXbf;!ATM$}CZ?zJZlfC>K$u=e#N9$n7L2-*Flo4uVV7X>4*gMmp9owkV!u|{NKKpdGm&f zM9$*#j*z_JBHY@k#qxGWDHtzHFEjTD&$qaN&8)&V~h_ZDg zclPDeNgI;iL_d}%6zDJ))htMMU)+DLBf+e1Vo3G*IoAFPVKns5Y>nmW^p%Vs{tKlf BUgZD) literal 0 HcmV?d00001 From fd6b1e319305c547b3a806ef7ea92ef98effe782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Wed, 25 Oct 2023 20:57:00 +0200 Subject: [PATCH 28/55] #384 Add documentation --- pom-maven-central.xml | 117 ++++++++++++++++++++++++++---------------- pom.xml | 13 ++++- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/pom-maven-central.xml b/pom-maven-central.xml index 46178a74..2a30e01f 100644 --- a/pom-maven-central.xml +++ b/pom-maven-central.xml @@ -11,7 +11,7 @@ KLoadGen Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial - data based on Data specification + data base on Data specification https://sngular.github.io/kloadgen/ @@ -25,17 +25,6 @@ - - AnxoGomezSngular - Anxo Gómez Sánchez - anxo.gomez@sngular.com - Sngular - https://sngular.github.io/ - - Developer - - Europe/Madrid - jegarcia Jose Enrique Garcia Maciñeiras @@ -195,8 +184,8 @@ davidgarciago David García Gondell david.garciag@sngular.com - Corunet - https://corunet.github.io/ + Sngular + https://sngular.github.io/ Junior Developer @@ -224,6 +213,17 @@ Europe/Madrid + + rabad-sng + Raúl Abad + raul.abad@sngular.com + Sngular + https://www.sngular.com + + Senior Backend Developer + + Europe/Madrid + nuriaricorf Nuria Rico Freire @@ -320,14 +320,14 @@ 2.8.6 32.0.0-jre 2.4.0-b180830.0359 - 11 + 17 provided - 5.5 + 5.6.2 2.6.0 5.8.2 7.1.1 2.4.1.Final - 3.1.0 + 3.5.1 1.18.22 0.9.5 4.2.0 @@ -335,21 +335,10 @@ 4.5.0 2.0.0-alpha1 1.3.1 - 2.32.0 + 2.35.1 - - org.apache.jmeter - jorphan - ${jmeter.version} - - - org.slf4j - slf4j-api - - - org.apache.kafka kafka-clients @@ -365,11 +354,6 @@ - - com.google.guava - guava - ${guava.version} - com.eclipsesource.minimal-json minimal-json @@ -437,6 +421,12 @@ io.apicurio apicurio-registry-client ${apicurio-registry.version} + + + org.jboss.slf4j + slf4j-jboss-logmanager + + io.apicurio @@ -478,6 +468,7 @@ org.slf4j slf4j-api ${slf4j-api.version} + provided org.apache.commons @@ -502,7 +493,7 @@ com.github.everit-org.json-schema org.everit.json.schema - 1.14.0 + 1.14.2 @@ -636,7 +627,43 @@ + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.1.2 + + + com.puppycrawl.tools + checkstyle + 10.2 + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + checkstyle.xml + UTF-8 + true + true + false + + + + validate + validate + + check + + + + com.github.ekryd.sortpom sortpom-maven-plugin @@ -769,10 +796,6 @@ ${jmeter.version} provided - - org.apache.jmeter - jorphan - org.apache.logging.log4j log4j-slf4j-impl @@ -839,10 +862,6 @@ ApacheJMeter_java ${jmeter.version} - - org.apache.jmeter - jorphan - org.apache.logging.log4j log4j-slf4j-impl @@ -945,4 +964,16 @@ + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + checkstyle.xml + + + + + diff --git a/pom.xml b/pom.xml index dad50d5c..11740d81 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ kloadgen - 5.6.5 + 5.7.0 KLoadGen Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial @@ -224,6 +224,17 @@ Europe/Madrid + + nuriaricorf + Nuria Rico Freire + nuria.rico@sngular.com + Sngular + https://sngular.github.io/ + + Junior Developer + + Europe/Madrid + dhergon David Hernández González From ed43cefd3d0a407545b474d668d7d06e0934b9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 27 Oct 2023 12:51:55 +0200 Subject: [PATCH 29/55] Fix AvroSchema cast --- .../extractor/extractors/avro/AvroExtractor.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index 677b36db..f1e73bc7 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -10,14 +10,22 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; - +//import com.sngular.kloadgen.model.json.Schema; +import io.confluent.kafka.schemaregistry.avro.AvroSchema; +import org.apache.avro.Schema; public class AvroExtractor implements ExtractorRegistry { static Map schemaRegistryMap = Map.of(CONFLUENT, new AvroConfluentExtractor(), APICURIO, new AvroApicurioExtractor()); public final List processSchema(final Object schema, SchemaRegistryEnum registryEnum) { - return schemaRegistryMap.get(registryEnum).processSchema(schema); + Schema rawschema; + if(schema instanceof AvroSchema) { + rawschema = ((AvroSchema)schema).rawSchema(); + }else { + rawschema = (Schema) schema; + } + return schemaRegistryMap.get(registryEnum).processSchema(rawschema); } public final List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum) { From 55863cb0b252faa64fe023635f10adb81bae8947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Thu, 16 Nov 2023 12:54:07 +0100 Subject: [PATCH 30/55] #384 merge --- docs/getting-started.md | 6 ++---- .../extractor/extractors/ExtractorFactory.java | 17 +++++++++++------ .../impl/ConfluentSchemaRegistry.java | 2 -- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 02f5bdaf..84675b6e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -6,10 +6,8 @@ Now that you know what KLoadGen is and that you are familiar with its components You will need these tools to start using the plugin: -- JDK/JRE 11+ - - (17 recommended) -- JMeter 5.4+ - - (5.6.2 recommended) +- JDK/JRE 17+ +- JMeter 5.6.2+ - Maven ## Quickstart diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index 1742bd49..46da8594 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -50,17 +50,22 @@ public static Pair> flatPropertiesList(final Str final String registryName = properties.getProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = schemaParsed.getParsedSchemaAdapter(); final String schemaType = abstractParsedSchemaAdapter.getType(); + final AbstractParsedSchemaAdapter parsedSchemaAdapter = schemaParsed.getParsedSchemaAdapter(); + final String schemaType = parsedSchemaAdapter.getType(); final List attributeList = new ArrayList<>(); final SchemaRegistryEnum schemaRegistryEnum = SchemaRegistryEnum.valueOf(registryName.toUpperCase()); final Object schema; - //TODO change parser - schema = switch (schemaRegistryEnum) { - case APICURIO -> ((ApicurioAbstractParsedSchemaMetadata) abstractParsedSchemaAdapter).getSchema(); - case CONFLUENT -> abstractParsedSchemaAdapter.getRawSchema(); - }; - attributeList.addAll(getExtractor(schemaType).processSchema(schema, schemaRegistryEnum)); + if (Objects.nonNull(registryName)) { + //TODO change parser + schema = switch (schemaRegistryEnum) { + case APICURIO -> ((ApicurioAbstractParsedSchemaMetadata) parsedSchemaAdapter).getSchema(); + case CONFLUENT -> parsedSchemaAdapter.getRawSchema(); + default -> throw new KLoadGenException("Schema Registry Type nos supported " + registryName.toUpperCase()); + }; + attributeList = getExtractor(schemaType, registryName.toUpperCase()).processSchema(schema, schemaRegistryEnum); + } return Pair.of(schemaType, attributeList); } } \ No newline at end of file diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java index 3204aca1..22ecde7d 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java @@ -37,14 +37,12 @@ public String getSchemaRegistryUrlKey() { @Override public void setSchemaRegistryClient(final String url, final Map properties) { - log.debug("CREATEION"); this.schemaRegistryClient = new CachedSchemaRegistryClient(List.of(checkPropertyOrVariable(url)), 1000, List.of(new AvroSchemaProvider(), new JsonSchemaProvider(), new ProtobufSchemaProvider()), properties); } @Override public void setSchemaRegistryClient(final Map properties) { - log.debug("CREATITIN"); final String url = properties.get(this.getSchemaRegistryUrlKey()).toString(); this.schemaRegistryClient = new CachedSchemaRegistryClient(List.of(checkPropertyOrVariable(url)), 1000, List.of(new AvroSchemaProvider(), new JsonSchemaProvider(), new ProtobufSchemaProvider()), properties); From ba1d97e2b31c5b7d5ab323019fc83f86797535c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 17 Nov 2023 09:37:08 +0100 Subject: [PATCH 31/55] Fix event-api.yml and fix empty fields validation --- .../kloadgen/processor/SchemaProcessor.java | 36 +++++++++++++++---- .../kloadgen/sampler/AsyncApiSampler.java | 6 +++- .../sampler/gui/AsyncApiSamplerGui.java | 9 +++-- .../adapter/impl/ConfluentSchemaMetadata.java | 2 +- src/test/resources/asyncapi/event-api.yml | 18 ++++------ 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index a278e650..ce6841ea 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -6,10 +6,7 @@ package com.sngular.kloadgen.processor; -import java.util.ArrayDeque; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; import com.sngular.kloadgen.common.SchemaTypeEnum; @@ -20,6 +17,7 @@ import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; +import lombok.NonNull; import lombok.SneakyThrows; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.RandomUtils; @@ -153,7 +151,10 @@ private Object processNestedComplexTypes(final SchemaProcessorPOJO pojo, final S } return returnObject; } - + /* private void makeNonEmptyFieldValueMappingRequiered(final FieldValueMapping fieldValueMapping){ + if () + } +*/ private void makeFieldValueMappingRequiredAndNotNullable(final FieldValueMapping fieldValueMapping) { makeFieldValueMappingRequired(fieldValueMapping); final List temporalFieldValueList = fieldValueMapping.getFieldValuesList(); @@ -166,8 +167,31 @@ private void makeFieldValueMappingRequired(final FieldValueMapping fieldValueMap } private ArrayDeque calculateFieldsToProcess() { + + ArrayDeque arrayBool; final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); - return new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); + List fieldExprMappingAux; + arrayBool = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); + if (arrayBool.isEmpty()) { + fieldExprMappingAux = fieldExprMappings; + arrayBool = new ArrayDeque<>(ListUtils.select(fieldExprMappingAux, this::shouldProcessFieldIfIsNonRequiered)); + } + return arrayBool; + } + + /*private ArrayDeque verifyMandatoryField(ArrayDeque initialFieldExpMappingsQueue, ArrayDeque arrayBool) { + initialFieldExpMappingsQueue. + }*/ + + private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/){ + boolean shouldProcess = false; + //final String[] fields = fieldValueMapping.getFieldName().split("\\."); + if (fieldValueMapping.getFieldValuesList().isEmpty()) { + fieldValueMapping.getFieldValuesList().remove("null"); + } else { + shouldProcess=true; + } + return shouldProcess; } private boolean shouldProcessField(final FieldValueMapping fieldValueMapping, final ArrayDeque initialFieldExpMappingsQueue) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 8843eed4..00585762 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -17,6 +17,7 @@ import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; import com.sngular.kloadgen.model.FieldValueMapping; @@ -65,7 +66,6 @@ public final boolean applies(final ConfigTestElement configElement) { @Override public final SampleResult sample(final Entry entry) { - final var sampleResult = new SampleResult(); sampleResult.setThreadName("AsyncApi Sampler"); sampleResult.sampleStart(); @@ -206,4 +206,8 @@ private String prettyPrint(final RecordMetadata recordMetadata) { private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); } + + public void setAsyncApiRegistry(AsyncApiSR selectedItem) { + + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index f0ec87fc..c66b049c 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -129,7 +129,7 @@ public void modifyTestElement(final TestElement element) { asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } } - // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); + //asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } configureTestElement(element); } @@ -198,10 +198,13 @@ private void populateData(final AsyncApiSampler element) { .forEach(propertyMapping -> propertyList.add(Pair.of(propertyMapping.getPropertyName(), propertyMapping.getPropertyValue()))); fillTable(brokerFieldModel, propertyList); - /*final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); + /* final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); if (!schemaRegistryList.isEmpty()) { fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); - }*/ + } + registryComboBox.removeAllItems(); + asyncApiExtractor.getSchemaRegistryData(asyncApiFile); + registryComboBox.setSelectedIndex(0);*/ topicComboBox.removeAllItems(); asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); topicComboBox.setSelectedIndex(0); diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java index 4af84f87..b7c999cd 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java @@ -7,7 +7,7 @@ import lombok.Getter; @Getter -public class ConfluentSchemaMetadata implements SchemaMetadataAdapter { +public class ConfluentSchemaMetadata implements SchemaMetadataAdapter { private Integer id; diff --git a/src/test/resources/asyncapi/event-api.yml b/src/test/resources/asyncapi/event-api.yml index de1ebf2f..75a6b53b 100644 --- a/src/test/resources/asyncapi/event-api.yml +++ b/src/test/resources/asyncapi/event-api.yml @@ -15,22 +15,13 @@ servers: description: Test MQTT broker channels: - user/signedup: + user-signedup: publish: operationId: onUserSignUp message: $ref : '#/components/messages/UserSignedUp' components: - messages: - UserSignedUp: - name: userSignedUp - title: User signed up event - summary: Inform about a new user registration in the system - contentType: application/json - payload: - $ref: '#/components/schemas/userSignedUpPayload' - schemas: userSignedUpPayload: type: object @@ -48,4 +39,9 @@ components: createdAt: type: string format: date-time - description: "foo" \ No newline at end of file + description: "foo" + messages: + UserSignedUp: + payload: + $ref : '#/components/schemas/userSignedUpPayload' + From b2e5770d7d8241d9c98449966c276d37dead626d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 17 Nov 2023 14:10:27 +0100 Subject: [PATCH 32/55] Fix all non-requiered and empty fields issues --- .../kloadgen/processor/SchemaProcessor.java | 29 ++++++++++--------- .../kloadgen/sampler/AsyncApiSampler.java | 6 +--- .../sampler/gui/AsyncApiSamplerGui.java | 9 ++---- .../adapter/impl/ConfluentSchemaMetadata.java | 2 +- src/test/resources/asyncapi/event-api.yml | 18 +++++++----- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index 1b626f1f..fecdd6e3 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -6,7 +6,10 @@ package com.sngular.kloadgen.processor; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import com.sngular.kloadgen.common.SchemaTypeEnum; @@ -17,7 +20,6 @@ import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; -import lombok.NonNull; import lombok.SneakyThrows; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.RandomUtils; @@ -168,21 +170,22 @@ private void makeFieldValueMappingRequired(final FieldValueMapping fieldValueMap private ArrayDeque calculateFieldsToProcess() { - ArrayDeque arrayBool; + ArrayDeque fieldToProcess; final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); - List fieldExprMappingAux; - arrayBool = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); - if (arrayBool.isEmpty()) { - fieldExprMappingAux = fieldExprMappings; - arrayBool = new ArrayDeque<>(ListUtils.select(fieldExprMappingAux, this::shouldProcessFieldIfIsNonRequiered)); + fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); + + if (fieldToProcess.isEmpty()) + fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered)); + + if(fieldToProcess.isEmpty()) { + while (initialFieldExpMappingsQueue.size()>1){ + initialFieldExpMappingsQueue.removeFirst(); + } + fieldToProcess = new ArrayDeque<>(initialFieldExpMappingsQueue); } - return arrayBool; + return fieldToProcess; } - /*private ArrayDeque verifyMandatoryField(ArrayDeque initialFieldExpMappingsQueue, ArrayDeque arrayBool) { - initialFieldExpMappingsQueue. - }*/ - private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/){ boolean shouldProcess = false; //final String[] fields = fieldValueMapping.getFieldName().split("\\."); diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 00585762..8843eed4 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -17,7 +17,6 @@ import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; import com.sngular.kloadgen.extractor.model.AsyncApiFile; -import com.sngular.kloadgen.extractor.model.AsyncApiSR; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator; import com.sngular.kloadgen.model.FieldValueMapping; @@ -66,6 +65,7 @@ public final boolean applies(final ConfigTestElement configElement) { @Override public final SampleResult sample(final Entry entry) { + final var sampleResult = new SampleResult(); sampleResult.setThreadName("AsyncApi Sampler"); sampleResult.sampleStart(); @@ -206,8 +206,4 @@ private String prettyPrint(final RecordMetadata recordMetadata) { private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); } - - public void setAsyncApiRegistry(AsyncApiSR selectedItem) { - - } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index adc1ea6e..4d9b001b 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -129,7 +129,7 @@ public void modifyTestElement(final TestElement element) { asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } } - //asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); + // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } configureTestElement(element); } @@ -198,13 +198,10 @@ private void populateData(final AsyncApiSampler element) { .forEach(propertyMapping -> propertyList.add(Pair.of(propertyMapping.getPropertyName(), propertyMapping.getPropertyValue()))); fillTable(brokerFieldModel, propertyList); - /* final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); + /*final var schemaRegistryList = asyncApiExtractor.getSchemaRegistryData(asyncApiFile); if (!schemaRegistryList.isEmpty()) { fillTable(schemaRegistryFieldModel, prepareSRServer(schemaRegistryList.get(0))); - } - registryComboBox.removeAllItems(); - asyncApiExtractor.getSchemaRegistryData(asyncApiFile); - registryComboBox.setSelectedIndex(0);*/ + }*/ topicComboBox.removeAllItems(); asyncApiExtractor.getSchemaDataMap(asyncApiFile).values().forEach(topicComboBox::addItem); topicComboBox.setSelectedIndex(0); diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java index 373021fb..db16a217 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentSchemaMetadata.java @@ -7,7 +7,7 @@ import lombok.Getter; @Getter -public class ConfluentSchemaMetadata implements SchemaMetadataAdapter { +public class ConfluentSchemaMetadata implements SchemaMetadataAdapter { private final Integer id; diff --git a/src/test/resources/asyncapi/event-api.yml b/src/test/resources/asyncapi/event-api.yml index 75a6b53b..a568870c 100644 --- a/src/test/resources/asyncapi/event-api.yml +++ b/src/test/resources/asyncapi/event-api.yml @@ -15,13 +15,22 @@ servers: description: Test MQTT broker channels: - user-signedup: + user_signedup: publish: operationId: onUserSignUp message: $ref : '#/components/messages/UserSignedUp' components: + messages: + UserSignedUp: + name: userSignedUp + title: User signed up event + summary: Inform about a new user registration in the system + contentType: application/json + payload: + $ref: '#/components/schemas/userSignedUpPayload' + schemas: userSignedUpPayload: type: object @@ -39,9 +48,4 @@ components: createdAt: type: string format: date-time - description: "foo" - messages: - UserSignedUp: - payload: - $ref : '#/components/schemas/userSignedUpPayload' - + description: "foo" \ No newline at end of file From 3ac589fb098fb0ffe0794d45c1e337d7ca430459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 20 Nov 2023 08:25:43 +0100 Subject: [PATCH 33/55] #384 Fix schema key generation issues --- src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index 62ecf712..cd0e7180 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -395,7 +395,7 @@ public static BaseLoadGenerator configureValueGenerator(final Properties props) } else { try { final String schema; - if (jMeterVariables.get(PropsKeysHelper.VALUE_SCHEMA).isEmpty()) { + if (ObjectUtils.isEmpty(jMeterVariables.get(PropsKeysHelper.VALUE_SCHEMA))) { schema = props.getProperty(PropsKeysHelper.VALUE_SCHEMA); } else { schema = jMeterVariables.get(PropsKeysHelper.VALUE_SCHEMA); From 162823f2c814566db98b522873fcd59bb55f032c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 20 Nov 2023 08:38:48 +0100 Subject: [PATCH 34/55] #384 Codacy issues --- .../SchemaRegistryConfigElementBeanInfo.java | 4 +- .../extractors/avro/AvroExtractor.java | 8 +-- .../sngular/kloadgen/sampler/SamplerUtil.java | 58 ------------------- .../sampler/gui/ApiServerRenderer.java | 11 ++-- .../sampler/gui/AsyncApiSamplerGui.java | 8 +-- 5 files changed, 17 insertions(+), 72 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java index 6fe8a526..cc4795fa 100644 --- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java +++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java @@ -23,8 +23,8 @@ public SchemaRegistryConfigElementBeanInfo() { super(SchemaRegistryConfigElement.class); - createPropertyGroup("schema_registry_config", new String[] {SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_NAME, - SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_URL, SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_PROPERTIES}); + createPropertyGroup("schema_registry_config", new String[] {SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_NAME, SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_URL, + SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_PROPERTIES}); final PropertyDescriptor schemaRegistryName = property(SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_NAME); schemaRegistryName.setPropertyEditorClass(SchemaRegistryNamePropertyEditor.class); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index e73bf921..e2d93c58 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -12,11 +12,11 @@ public class AvroExtractor implements ExtractorRegistry { - private static final Map schemaRegistryMap = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, - new AvroApicurioExtractor()); + private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, + new AvroApicurioExtractor()); public final List processSchema(final T schema, final SchemaRegistryEnum registryEnum) { - return schemaRegistryMap.get(registryEnum).processSchema(schema); + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema); } public final ParsedSchema processSchema(final String fileContent) { @@ -24,7 +24,7 @@ public final ParsedSchema processSchema(final String fileContent) { } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { - return schemaRegistryMap.get(registryEnum).getSchemaNameList(schema); + return SCHEMA_REGISTRY_MAP.get(registryEnum).getSchemaNameList(schema); } } \ No newline at end of file diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index cd0e7180..80dc89be 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -33,7 +33,6 @@ import com.sngular.kloadgen.util.PropsKeysHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import io.apicurio.registry.resolver.SchemaResolverConfig; -import io.apicurio.registry.serde.SerdeConfig; import io.confluent.kafka.schemaregistry.client.SchemaRegistryClientConfig; import org.apache.avro.SchemaParseException; import org.apache.commons.lang3.ObjectUtils; @@ -99,63 +98,6 @@ public static Arguments getCommonProducerDefaultParameters() { return defaultParameters; } - public static Properties setupCommonProperties(final JavaSamplerContext context) { - final Properties props = new Properties(); - - props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, context.getParameter(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)); - if ("true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY))) { - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); - } else if ("true".equals(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.SIMPLE_KEYED_MESSAGE_KEY))) { - props.put(PropsKeysHelper.MESSAGE_KEY_KEY_TYPE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_TYPE)); - props.put(PropsKeysHelper.MESSAGE_KEY_KEY_VALUE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_VALUE)); - if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE))) { - props.put(PropsKeysHelper.KEY_SCHEMA_TYPE, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SCHEMA_TYPE)); - } - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_SERIALIZER_CLASS_PROPERTY)); - } else { - props.put(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY, Boolean.FALSE); - } - - if (Objects.nonNull(context.getParameter(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG))) { - props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, context.getParameter(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG)); - } - - props.put(ProducerConfig.ACKS_CONFIG, context.getParameter(ProducerConfig.ACKS_CONFIG)); - props.put(ProducerConfig.SEND_BUFFER_CONFIG, context.getParameter(ProducerConfig.SEND_BUFFER_CONFIG)); - props.put(ProducerConfig.RECEIVE_BUFFER_CONFIG, context.getParameter(ProducerConfig.RECEIVE_BUFFER_CONFIG)); - props.put(ProducerConfig.BATCH_SIZE_CONFIG, context.getParameter(ProducerConfig.BATCH_SIZE_CONFIG)); - props.put(ProducerConfig.LINGER_MS_CONFIG, context.getParameter(ProducerConfig.LINGER_MS_CONFIG)); - props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, context.getParameter(ProducerConfig.BUFFER_MEMORY_CONFIG)); - props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, context.getParameter(ProducerConfig.COMPRESSION_TYPE_CONFIG)); - props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, context.getParameter(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG)); - props.put(ProducerKeysHelper.SASL_MECHANISM, context.getParameter(ProducerKeysHelper.SASL_MECHANISM)); - - final String schemaRegistryNameValue = JavaSamplerContext.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); - final String enableSchemaRegistrationValue = context.getParameter(SchemaRegistryKeyHelper.ENABLE_AUTO_SCHEMA_REGISTRATION_CONFIG); - if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_APICURIO.equalsIgnoreCase(schemaRegistryNameValue)) { - props.put(SerdeConfig.AUTO_REGISTER_ARTIFACT, enableSchemaRegistrationValue); - props.put(SchemaResolverConfig.REGISTRY_URL, JavaSamplerContext.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, JavaSamplerContext.getJMeterVariables().get(SchemaResolverConfig.REGISTRY_URL)); - } else { - props.put(SchemaRegistryKeyHelper.ENABLE_AUTO_SCHEMA_REGISTRATION_CONFIG, enableSchemaRegistrationValue); - final String schemaRegistryURL = JavaSamplerContext.getJMeterVariables().get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL); - if (StringUtils.isNotBlank(schemaRegistryURL)) { - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_URL, schemaRegistryURL); - } - } - - final Iterator parameters = context.getParameterNamesIterator(); - parameters.forEachRemaining(parameter -> { - if (parameter.startsWith("_")) { - props.put(parameter.substring(1), context.getParameter(parameter)); - } - }); - - verifySecurity(context, props); - - return props; - } - private static String propertyOrDefault(final String property, final String defaultToken, final String valueToSent) { return defaultToken.equals(property) ? valueToSent : property; } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java index 52e4c98e..11e72a8d 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiServerRenderer.java @@ -1,11 +1,14 @@ package com.sngular.kloadgen.sampler.gui; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; - -import javax.swing.*; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; import java.util.Objects; +import javax.swing.JLabel; +import javax.swing.JList; + +import com.sngular.kloadgen.extractor.model.AsyncApiServer; + public class ApiServerRenderer extends JLabel implements javax.swing.ListCellRenderer { protected ApiServerRenderer() { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 4d9b001b..f0acda17 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -129,14 +129,14 @@ public void modifyTestElement(final TestElement element) { asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } } - // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); + // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } configureTestElement(element); } private List mapVectorConf(final Vector dataVector) { final var mapResult = new ArrayList(); - for (Vector v : dataVector) { + for (final Vector v : dataVector) { mapResult.add(PropertyMapping .builder() .propertyName(v.get(0).toString()) @@ -385,7 +385,7 @@ private JPanel createSchemaTab() { } private void topicComboActionListener(final ActionEvent event) { - final JComboBox cb = (JComboBox)event.getSource(); + final JComboBox cb = (JComboBox) event.getSource(); final var selectedSchema = (AsyncApiSchema) cb.getSelectedItem(); if (Objects.nonNull(selectedSchema)) { fillTable(schemaFieldModel, selectedSchema.getProperties()); @@ -396,7 +396,7 @@ private void registryComboActionListener(final ActionEvent actionEvent) { } private void serverChooseActionListener(final ActionEvent actionEvent) { - final JComboBox serverChoose = (JComboBox)actionEvent.getSource(); + final JComboBox serverChoose = (JComboBox) actionEvent.getSource(); if (Objects.nonNull(serverChoose)) { fillTable(brokerFieldModel, prepareServer((AsyncApiServer) serverChoose.getSelectedItem())); } From f5a3d528cf3d8966d1ad399061b28f038840b6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 20 Nov 2023 08:40:11 +0100 Subject: [PATCH 35/55] #384 Codacy issues --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e040abd..a44fba56 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ kloadgen - 5.6.10 + 5.7.0 KLoadGen Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial From adf99bcf2b6eaa52dbfda458160f5c1da1c83898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 20 Nov 2023 09:25:20 +0100 Subject: [PATCH 36/55] #384 Codacy issues --- .../kloadgen/processor/SchemaProcessor.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index fecdd6e3..f5409ed1 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -153,10 +153,7 @@ private Object processNestedComplexTypes(final SchemaProcessorPOJO pojo, final S } return returnObject; } - /* private void makeNonEmptyFieldValueMappingRequiered(final FieldValueMapping fieldValueMapping){ - if () - } -*/ + private void makeFieldValueMappingRequiredAndNotNullable(final FieldValueMapping fieldValueMapping) { makeFieldValueMappingRequired(fieldValueMapping); final List temporalFieldValueList = fieldValueMapping.getFieldValuesList(); @@ -172,13 +169,13 @@ private ArrayDeque calculateFieldsToProcess() { ArrayDeque fieldToProcess; final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); - fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); + fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); - if (fieldToProcess.isEmpty()) - fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered)); - - if(fieldToProcess.isEmpty()) { - while (initialFieldExpMappingsQueue.size()>1){ + if (fieldToProcess.isEmpty()) { + fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequired)); + } + if (fieldToProcess.isEmpty()) { + while (initialFieldExpMappingsQueue.size() > 1) { initialFieldExpMappingsQueue.removeFirst(); } fieldToProcess = new ArrayDeque<>(initialFieldExpMappingsQueue); @@ -186,13 +183,13 @@ private ArrayDeque calculateFieldsToProcess() { return fieldToProcess; } - private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/){ + private boolean shouldProcessFieldIfIsNonRequired(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/) { boolean shouldProcess = false; //final String[] fields = fieldValueMapping.getFieldName().split("\\."); if (fieldValueMapping.getFieldValuesList().isEmpty()) { fieldValueMapping.getFieldValuesList().remove("null"); } else { - shouldProcess=true; + shouldProcess = true; } return shouldProcess; } From 5a86cfecd02843c5c085526beba809728f084ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Mon, 20 Nov 2023 10:51:36 +0100 Subject: [PATCH 37/55] Fix some checkstyle issues --- .../extractors/avro/AvroExtractor.java | 6 +++--- .../kloadgen/processor/SchemaProcessor.java | 17 +++++++++-------- .../sampler/gui/AsyncApiSamplerGui.java | 6 +++--- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index e73bf921..9dd36120 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -12,11 +12,11 @@ public class AvroExtractor implements ExtractorRegistry { - private static final Map schemaRegistryMap = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, + private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, new AvroApicurioExtractor()); public final List processSchema(final T schema, final SchemaRegistryEnum registryEnum) { - return schemaRegistryMap.get(registryEnum).processSchema(schema); + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema); } public final ParsedSchema processSchema(final String fileContent) { @@ -24,7 +24,7 @@ public final ParsedSchema processSchema(final String fileContent) { } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { - return schemaRegistryMap.get(registryEnum).getSchemaNameList(schema); + return SCHEMA_REGISTRY_MAP.get(registryEnum).getSchemaNameList(schema); } } \ No newline at end of file diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index fecdd6e3..f1dc1e61 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -153,10 +153,11 @@ private Object processNestedComplexTypes(final SchemaProcessorPOJO pojo, final S } return returnObject; } - /* private void makeNonEmptyFieldValueMappingRequiered(final FieldValueMapping fieldValueMapping){ + /* private void makeNonEmptyFieldValueMappingRequiered(final FieldValueMapping fieldValueMapping){ if () } -*/ + */ + private void makeFieldValueMappingRequiredAndNotNullable(final FieldValueMapping fieldValueMapping) { makeFieldValueMappingRequired(fieldValueMapping); final List temporalFieldValueList = fieldValueMapping.getFieldValuesList(); @@ -174,11 +175,11 @@ private ArrayDeque calculateFieldsToProcess() { final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); - if (fieldToProcess.isEmpty()) - fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered)); - - if(fieldToProcess.isEmpty()) { - while (initialFieldExpMappingsQueue.size()>1){ + if (fieldToProcess.isEmpty()) { + fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered)); + } + if (fieldToProcess.isEmpty()) { + while (initialFieldExpMappingsQueue.size() > 1) { initialFieldExpMappingsQueue.removeFirst(); } fieldToProcess = new ArrayDeque<>(initialFieldExpMappingsQueue); @@ -186,7 +187,7 @@ private ArrayDeque calculateFieldsToProcess() { return fieldToProcess; } - private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/){ + private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/) { boolean shouldProcess = false; //final String[] fields = fieldValueMapping.getFieldName().split("\\."); if (fieldValueMapping.getFieldValuesList().isEmpty()) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 4d9b001b..f33184a6 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -129,7 +129,7 @@ public void modifyTestElement(final TestElement element) { asyncApiSampler.setSchemaFieldConfiguration(mapVector(schemaFieldModel.getDataVector())); } } - // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); + // asyncApiSampler.setAsyncApiRegistry((AsyncApiSR) registryComboBox.getSelectedItem()); } configureTestElement(element); } @@ -385,7 +385,7 @@ private JPanel createSchemaTab() { } private void topicComboActionListener(final ActionEvent event) { - final JComboBox cb = (JComboBox)event.getSource(); + final JComboBox cb = (JComboBox) event.getSource(); final var selectedSchema = (AsyncApiSchema) cb.getSelectedItem(); if (Objects.nonNull(selectedSchema)) { fillTable(schemaFieldModel, selectedSchema.getProperties()); @@ -396,7 +396,7 @@ private void registryComboActionListener(final ActionEvent actionEvent) { } private void serverChooseActionListener(final ActionEvent actionEvent) { - final JComboBox serverChoose = (JComboBox)actionEvent.getSource(); + final JComboBox serverChoose = (JComboBox) actionEvent.getSource(); if (Objects.nonNull(serverChoose)) { fillTable(brokerFieldModel, prepareServer((AsyncApiServer) serverChoose.getSelectedItem())); } From 3f75a44dc3236ffcbe51b32be21dc733eb1cb836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Mon, 20 Nov 2023 11:25:47 +0100 Subject: [PATCH 38/55] Fix Codacy issues and some warnings --- .../schemaregistry/SchemaRegistryConfigElementBeanInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java index cc4795fa..c3fe6b1d 100644 --- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java +++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java @@ -24,7 +24,7 @@ public SchemaRegistryConfigElementBeanInfo() { super(SchemaRegistryConfigElement.class); createPropertyGroup("schema_registry_config", new String[] {SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_NAME, SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_URL, - SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_PROPERTIES}); + SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_PROPERTIES}); final PropertyDescriptor schemaRegistryName = property(SchemaRegistryConfigElementValue.SCHEMA_REGISTRY_NAME); schemaRegistryName.setPropertyEditorClass(SchemaRegistryNamePropertyEditor.class); From ab704494d782c685be0e744e8232b9aa594374a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 24 Nov 2023 10:48:56 +0100 Subject: [PATCH 39/55] AsyncApiextractorImplTest completed --- .../kloadgen/processor/SchemaProcessor.java | 17 ++-- .../asyncapi/AsyncApiExtractorImplTest.java | 64 +++++++++++++++ .../extractors/json/JsonDefaultTest.java | 16 ---- .../processor/JsonSchemaProcessorTest.java | 21 +++++ .../fixture/JsonSchemaFixturesConstants.java | 79 +++++++++++++------ .../randomtool/random/RandomMapTest.java | 2 +- 6 files changed, 148 insertions(+), 51 deletions(-) create mode 100644 src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java index 716ccbe0..cf930146 100644 --- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java +++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java @@ -171,23 +171,24 @@ private ArrayDeque calculateFieldsToProcess() { final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings); fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))); + if (fieldToProcess.isEmpty()) { fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered)); - } - if (fieldToProcess.isEmpty()) { - while (initialFieldExpMappingsQueue.size() > 1) { - initialFieldExpMappingsQueue.removeFirst(); + if (fieldToProcess.isEmpty()) { + while (initialFieldExpMappingsQueue.size() > 1) { + initialFieldExpMappingsQueue.removeFirst(); + } + fieldToProcess = initialFieldExpMappingsQueue; } - fieldToProcess = new ArrayDeque<>(initialFieldExpMappingsQueue); } + return fieldToProcess; } - private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping/*, final ArrayDeque initialFieldExpMappingsQueue*/) { + private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping) { boolean shouldProcess = false; - //final String[] fields = fieldValueMapping.getFieldName().split("\\."); - if (fieldValueMapping.getFieldValuesList().isEmpty()) { + if (fieldValueMapping.getFieldValuesList().isEmpty() || fieldValueMapping.getFieldValuesList().contains("null")) { fieldValueMapping.getFieldValuesList().remove("null"); } else { shouldProcess = true; diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java new file mode 100644 index 00000000..b2b9b0c7 --- /dev/null +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -0,0 +1,64 @@ +package com.sngular.kloadgen.extractor.asyncapi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.testutil.FileHelper; +import org.apache.jmeter.threads.JMeterContext; +import org.apache.jmeter.threads.JMeterContextService; +import org.apache.jmeter.threads.JMeterVariables; +import org.apache.jmeter.util.JMeterUtils; +import static org.assertj.core.api.Assertions.*; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class AsyncApiExtractorImplTest { + private FileHelper fileHelper = new FileHelper(); + private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + + @BeforeEach + public final void setUp() { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + final JMeterContext jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + } + + @Test + @DisplayName("Should extract asyncapi file") + void testExtractFile() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); + + assertNotNull(asapfle); + assertEquals("{user_signedup=user_signedup}",asapfle.getApiSchemaList().toString()); + assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", + asapfle.getApiServerMap().toString()); + } + @Test + @DisplayName("Should extract basic asyncapi schema") + void testExtractAsyncapiSchema() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final JsonNode openApi = om.readTree(testFile); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processNode(openApi); + JsonNode propertiesSchema = asapfle.getAsyncApiFileNode().path("components").path("schemas").path("userSignedUpPayload").path("properties"); + Assertions.assertThat(asapfle).isNotNull(); + assertThat(propertiesSchema) + .hasSize(4) + .isSubsetOf(openApi.get("components").get("schemas").get("userSignedUpPayload").get("properties")); + } + +} \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java index dccd6efb..deee897f 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java @@ -22,23 +22,7 @@ class JsonDefaultTest { private final Extractor jsonDefaultExtractor = new JsonDefaultExtractor(); - @Test - @DisplayName("Should extract basic types") - void testBasic() throws Exception { - final String testFile = fileHelper.getContent("/jsonschema/basic.jcs"); - - final Map constraints = Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0"); - final JSONObject jsonObject = new JSONObject(testFile); - final Schema schema = SchemaLoader.load(jsonObject); - final List fieldValueMappingList = jsonDefaultExtractor.processSchema(schema.toString()); - Assertions.assertThat(fieldValueMappingList) - .hasSize(3) - .containsExactlyInAnyOrder( - FieldValueMapping.builder().fieldName("firstName").fieldType("string").constraints(constraints).required(false).isAncestorRequired(false).build(), - FieldValueMapping.builder().fieldName("lastName").fieldType("string").constraints(constraints).required(true).isAncestorRequired(false).build(), - FieldValueMapping.builder().fieldName("age").fieldType("number").required(true).isAncestorRequired(false).build()); - } @Test @DisplayName("Should extract a basic array") diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index b5dc8620..d92123b5 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -9,12 +9,16 @@ import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; +import com.sngular.kloadgen.testutil.FileHelper; +import com.sngular.kloadgen.testutil.SchemaParseUtil; +import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; import org.apache.jmeter.util.JMeterUtils; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -32,6 +36,10 @@ private static Stream parametersForTestBasicStructure() { return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED_EXPECTED)); } + private static Stream parametersForTestOptionalFieldNonEmpty(){ + return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED_EXPECTED)); + } + @BeforeEach public final void setUp() { final File file = new File("src/test/resources"); @@ -117,4 +125,17 @@ final void testNestedComplexLevels() { ".*\\\"bush\":\\{\"\\w+\":\\{\"maxHeight\":(\\[(\\{(\"\\w+\":\\d+,?)+},?)+],?)*\"leafs\":(\\[\\{(\"\\w+\":\\[(\"oval\",?)+],?)+}+],+)*.*$"); } + @ParameterizedTest + @DisplayName("Should process non-required fields if it is not empty") + @MethodSource("parametersForTestOptionalFieldNonEmpty") + final void testOptionalFieldNonEmpty(final List schemaAsJson, final String expected){ + + final SchemaProcessor jsonSchemaProcessor = new SchemaProcessor(); + + jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON,null,null,schemaAsJson); + final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); + + JSONAssert.assertEquals(message.toString(), expected, JSONCompareMode.STRICT); + } + } diff --git a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java index 37fecb87..047283e0 100644 --- a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java +++ b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java @@ -12,34 +12,61 @@ public class JsonSchemaFixturesConstants { public static final List SIMPLE_SCHEMA = new ArrayList(Arrays.asList( - FieldValueMapping.builder() - .fieldName("firstName") - .fieldType("string") - .valueLength(0) - .fieldValueList("null") - .required(false) - .isAncestorRequired(false) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("lastName") - .fieldType("string") - .valueLength(0) - .fieldValueList("García") - .required(true) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("age") - .fieldType("number") - .valueLength(0) - .fieldValueList("null") - .required(false) - .constraints(Collections.emptyMap()) - .build() + FieldValueMapping.builder() + .fieldName("firstName") + .fieldType("string") + .valueLength(0) + .fieldValueList("null") + .required(false) + .isAncestorRequired(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("lastName") + .fieldType("string") + .valueLength(0) + .fieldValueList("García") + .required(true) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("age") + .fieldType("number") + .valueLength(0) + .fieldValueList("null") + .required(false) + .constraints(Collections.emptyMap()) + .build() )); - public static final String SIMPLE_SCHEMA_EXPECTED = "{\"lastName\":\"García\"}"; + public static final List SIMPLE_SCHEMA_NONREQUIRED = new ArrayList(Arrays.asList( + FieldValueMapping.builder() + .fieldName("firstName") + .fieldType("string") + .valueLength(0) + .fieldValueList("Graciela") + .required(false) + .isAncestorRequired(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("lastName") + .fieldType("string") + .valueLength(0) + .fieldValueList("null") + .required(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("age") + .fieldType("number") + .valueLength(0) + .fieldValueList("21") + .required(false) + .constraints(Collections.emptyMap()) + .build() + )); + public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\": \"Graciela\",\"age\":21}"; public static final List SIMPLE_SCHEMA_MAP = new ArrayList<>(Arrays.asList( FieldValueMapping.builder() diff --git a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java index 686bb88c..cc78b1c0 100644 --- a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java +++ b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java @@ -53,7 +53,7 @@ private static Stream parametersForGenerateMapFixedKeyRandomValue() { ); } - @ParameterizedTest + @ParameterizedTest(name = "test for {0}") @MethodSource("parametersForGenerateMapRandomValueFromList") void generateMapRandomValueFromList( final String fieldType, final Integer valueLength, final List fieldValuesList, final Map expected, final Integer size) { From 336ce4c75a605ed60781000e4253538e365aa1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 24 Nov 2023 12:36:24 +0100 Subject: [PATCH 40/55] Fix Codacy issues --- .../java/com/sngular/kloadgen/sampler/AsyncApiSampler.java | 4 ++-- .../sngular/kloadgen/processor/JsonSchemaProcessorTest.java | 6 ++---- .../com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java | 4 ++++ 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 8843eed4..2627ac03 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -73,7 +73,7 @@ public final SampleResult sample(final Entry entry) { generator.setUpGenerator(getSchemaFieldConfiguration()); final var messageVal = generator.nextMessage(); if (Objects.nonNull(messageVal)) { - final var producerRecord = getProducerRecord(messageVal, enrichedKeyFlag(), enrichedValueFlag()); + final var producerRecord = getProducerRecord(messageVal, enrichedValueFlag()); fillSamplerResult(producerRecord, sampleResult); final var result = producer.send(producerRecord, (metadata, e) -> { if (e != null) { @@ -174,7 +174,7 @@ public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { this.setProperty("asyncapischemaname", asyncApiSchemaName); } - private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean keyFlag, final boolean valueFlag) { + private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean valueFlag) { final ProducerRecord producerRecord; producerRecord = new ProducerRecord<>(getAsyncApiSchemaName(), getObject(messageVal, valueFlag)); return producerRecord; diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index d92123b5..04c236fa 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -9,9 +9,6 @@ import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; -import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.SchemaParseUtil; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -135,7 +132,8 @@ final void testOptionalFieldNonEmpty(final List schemaAsJson, jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON,null,null,schemaAsJson); final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); - JSONAssert.assertEquals(message.toString(), expected, JSONCompareMode.STRICT); + Assertions.assertThat(message.toString()).isEqualTo(expected); + } } diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java new file mode 100644 index 00000000..6d5c6274 --- /dev/null +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -0,0 +1,4 @@ +import static org.junit.jupiter.api.Assertions.*; +class AsyncApiSamplerTest { + +} \ No newline at end of file From 35bdb2855bd02949b19dfe7e6fea17def9f0e143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 24 Nov 2023 12:53:26 +0100 Subject: [PATCH 41/55] Fix Codacy issues --- .../kloadgen/processor/fixture/JsonSchemaFixturesConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java index 047283e0..d4a7e842 100644 --- a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java +++ b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java @@ -66,7 +66,7 @@ public class JsonSchemaFixturesConstants { .constraints(Collections.emptyMap()) .build() )); - public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\": \"Graciela\",\"age\":21}"; + public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\":\"Graciela\",\"age\":21.0}"; public static final List SIMPLE_SCHEMA_MAP = new ArrayList<>(Arrays.asList( FieldValueMapping.builder() From 43317a5186191e61ebdb849c988a8a92ee42fb07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 24 Nov 2023 13:25:46 +0100 Subject: [PATCH 42/55] AsyncApiextractorImplTest completed --- .../kloadgen/processor/fixture/JsonSchemaFixturesConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java index d4a7e842..0bf29801 100644 --- a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java +++ b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java @@ -66,7 +66,7 @@ public class JsonSchemaFixturesConstants { .constraints(Collections.emptyMap()) .build() )); - public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\":\"Graciela\",\"age\":21.0}"; + public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\":\"Graciela\",\"age\":21.0}"; public static final List SIMPLE_SCHEMA_MAP = new ArrayList<>(Arrays.asList( FieldValueMapping.builder() From 620f676cbdf31c9418e26a27c3268852aa1363b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Fri, 24 Nov 2023 14:32:58 +0100 Subject: [PATCH 43/55] Fix Codacy issues --- .../kloadgen/sampler/AsyncApiSampler.java | 4 -- .../sampler/gui/AsyncApiSamplerGui.java | 41 +++++++++---------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 2627ac03..d6030cf7 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -180,10 +180,6 @@ private ProducerRecord getProducerRecord(final EnrichedRecord me return producerRecord; } - private Boolean enrichedKeyFlag() { - return false; - } - private Boolean enrichedValueFlag() { return false; } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index f0acda17..1f56866d 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -268,38 +268,37 @@ private JPanel createAsyncApiFileSelectPanel() { final JPanel fileChoosingPanel = new JPanel(); fileChoosingPanel.setLayout(new GridBagLayout()); fileChoosingPanel.setName("AsyncApi File"); - var gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.weighty = 0.03; - gridBagConstraints.fill = GridBagConstraints.BOTH; + gridEstablish(0, 0, 0.03, GridBagConstraints.BOTH, -1); asyncApiFileTextField = new JTextField(); asyncApiFileTextField.setPreferredSize(new Dimension(249, 30)); asyncApiFileTextField.setText(""); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - fileChoosingPanel.add(asyncApiFileTextField, gridBagConstraints); + fileChoosingPanel.add(asyncApiFileTextField, gridEstablish(1, 0, -1, GridBagConstraints.HORIZONTAL, GridBagConstraints.WEST)); final JButton fileButton = new JButton(); fileButton.setText("Open File"); fileButton.addActionListener(this::actionFileChooser); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - fileChoosingPanel.add(fileButton, gridBagConstraints); + fileChoosingPanel.add(fileButton, gridEstablish(2, 0, -1, GridBagConstraints.HORIZONTAL, -1)); final JLabel label1 = new JLabel(); label1.setText("AsyncApi File"); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = GridBagConstraints.WEST; - fileChoosingPanel.add(label1, gridBagConstraints); + fileChoosingPanel.add(label1, gridEstablish(0, 0, -1, -1, GridBagConstraints.WEST)); return fileChoosingPanel; } + private GridBagConstraints gridEstablish(final int x, final int y, final double w, final int fill, final int anchor) { + final var gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = x; + gridBagConstraints.gridy = y; + if (w != -1) { + gridBagConstraints.weighty = w; + } + if (fill != -1) { + gridBagConstraints.fill = fill; + } + if (anchor != -1) { + gridBagConstraints.anchor = anchor; + } + return gridBagConstraints; + } + private JTabbedPane createAsyncApiTabs() { final var tabbedPanel = new JTabbedPane(); tabbedPanel.addTab("Broker", createBrokerPanel()); From 06d0dde7a6000afbc731c10aa6d2e8258b5f77d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Fri, 24 Nov 2023 14:58:21 +0100 Subject: [PATCH 44/55] #384 fix style codacy --- .../extractors/ExtractorRegistry.java | 5 +- .../protobuf/ProtobufExtractor.java | 8 +- .../sampler/gui/AsyncApiSamplerGui.java | 7 +- .../asyncapi/AsyncApiExtractorImplTest.java | 86 +++++++++---------- .../processor/JsonSchemaProcessorTest.java | 6 +- .../kloadgen/sampler/AsyncApiSamplerTest.java | 4 - 6 files changed, 55 insertions(+), 61 deletions(-) delete mode 100644 src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java index 27026c59..2024f088 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java @@ -4,11 +4,12 @@ import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; -public interface ExtractorRegistry { +public interface ExtractorRegistry { List processSchema(final T schema, SchemaRegistryEnum registry); - Object processSchema(final String fileContent); + T processSchema(final String fileContent); List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java index 456d876a..8a9436c0 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java @@ -10,17 +10,17 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; -public class ProtobuffExtractor implements ExtractorRegistry { +public class ProtobufExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new ProtoBufConfluentExtractor(), SchemaRegistryEnum.APICURIO, new ProtoBufApicurioExtractor()); - public final List processSchema(final ParsedSchema schemaReceived, final SchemaRegistryEnum registryEnum) { + public final List processSchema(final T schemaReceived, final SchemaRegistryEnum registryEnum) { return new ArrayList(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived)); } - public final ParsedSchema processSchema(final String fileContent) { - return new ParsedSchema(fileContent, "PROTOBUF"); + public final T processSchema(final String fileContent) { + return (T) new ParsedSchema(fileContent, "PROTOBUF"); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 1f56866d..5edfcd21 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -61,6 +61,7 @@ import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; +@SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); @@ -81,8 +82,6 @@ public final class AsyncApiSamplerGui extends AbstractSamplerGui { private JComboBox topicComboBox; - private JComboBox registryComboBox; - private AsyncApiFile asyncApiFile; public AsyncApiSamplerGui() { @@ -362,10 +361,10 @@ private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new BorderLayout(0, 0)); registryUrlPanel.add(new JLabeledTextField("Schema Registry URL")); - registryComboBox = new JComboBox<>(); + final JComboBox registryComboBox = new JComboBox<>(); registryComboBox.setRenderer(new AsyncApiSRRenderer()); registryComboBox.addActionListener(this::registryComboActionListener); - registryUrlPanel.add(this.registryComboBox, BorderLayout.NORTH); + registryUrlPanel.add(registryComboBox, BorderLayout.NORTH); registryUrlPanel.add(new JScrollPane(new JTable(schemaRegistryFieldModel)), BorderLayout.CENTER); return registryUrlPanel; } diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java index b2b9b0c7..25a9f63c 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -1,5 +1,9 @@ package com.sngular.kloadgen.extractor.asyncapi; +import java.io.File; +import java.io.IOException; +import java.util.Locale; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -9,56 +13,50 @@ import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; import org.apache.jmeter.util.JMeterUtils; -import static org.assertj.core.api.Assertions.*; - import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - class AsyncApiExtractorImplTest { - private FileHelper fileHelper = new FileHelper(); - private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); - - @BeforeEach - public final void setUp() { - final File file = new File("src/test/resources"); - final String absolutePath = file.getAbsolutePath(); - JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); - final JMeterContext jmcx = JMeterContextService.getContext(); - jmcx.setVariables(new JMeterVariables()); - JMeterUtils.setLocale(Locale.ENGLISH); - } - - @Test - @DisplayName("Should extract asyncapi file") - void testExtractFile() throws IOException { - final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); - assertNotNull(asapfle); - assertEquals("{user_signedup=user_signedup}",asapfle.getApiSchemaList().toString()); - assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", - asapfle.getApiServerMap().toString()); - } - @Test - @DisplayName("Should extract basic asyncapi schema") - void testExtractAsyncapiSchema() throws IOException { - final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final JsonNode openApi = om.readTree(testFile); - final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processNode(openApi); - JsonNode propertiesSchema = asapfle.getAsyncApiFileNode().path("components").path("schemas").path("userSignedUpPayload").path("properties"); - Assertions.assertThat(asapfle).isNotNull(); - assertThat(propertiesSchema) - .hasSize(4) - .isSubsetOf(openApi.get("components").get("schemas").get("userSignedUpPayload").get("properties")); - } + private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + + private final FileHelper fileHelper = new FileHelper(); + + @BeforeEach + public final void setUp() { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + final JMeterContext jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + } + + @Test + @DisplayName("Should extract asyncapi file") + void testExtractFile() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); + + org.junit.jupiter.api.Assertions.assertNotNull(asapfle); + org.junit.jupiter.api.Assertions.assertEquals("{user_signedup=user_signedup}", asapfle.getApiSchemaList().toString()); + org.junit.jupiter.api.Assertions.assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", + asapfle.getApiServerMap().toString()); + } + + @Test + @DisplayName("Should extract basic asyncapi schema") + void testExtractAsyncapiSchema() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final JsonNode openApi = om.readTree(testFile); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processNode(openApi); + final JsonNode propertiesSchema = asapfle.getAsyncApiFileNode().path("components").path("schemas").path("userSignedUpPayload").path("properties"); + Assertions.assertThat(asapfle).isNotNull(); + Assertions.assertThat(propertiesSchema) + .hasSize(4) + .isSubsetOf(openApi.get("components").get("schemas").get("userSignedUpPayload").get("properties")); + } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index 04c236fa..b05d5b24 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -33,7 +33,7 @@ private static Stream parametersForTestBasicStructure() { return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED_EXPECTED)); } - private static Stream parametersForTestOptionalFieldNonEmpty(){ + private static Stream parametersForTestOptionalFieldNonEmpty() { return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED_EXPECTED)); } @@ -125,11 +125,11 @@ final void testNestedComplexLevels() { @ParameterizedTest @DisplayName("Should process non-required fields if it is not empty") @MethodSource("parametersForTestOptionalFieldNonEmpty") - final void testOptionalFieldNonEmpty(final List schemaAsJson, final String expected){ + final void testOptionalFieldNonEmpty(final List schemaAsJson, final String expected) { final SchemaProcessor jsonSchemaProcessor = new SchemaProcessor(); - jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON,null,null,schemaAsJson); + jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, schemaAsJson); final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); Assertions.assertThat(message.toString()).isEqualTo(expected); diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java deleted file mode 100644 index 6d5c6274..00000000 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ /dev/null @@ -1,4 +0,0 @@ -import static org.junit.jupiter.api.Assertions.*; -class AsyncApiSamplerTest { - -} \ No newline at end of file From 55bd5ca50d5f71690fed69ae0eb3f9dc1e92fa06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Graciela=20M=C3=A9ndez=20Olmos?= Date: Mon, 27 Nov 2023 09:14:10 +0100 Subject: [PATCH 45/55] Test AsyncApiSampler --- .../kloadgen/sampler/AsyncApiSamplerTest.java | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index 6d5c6274..f6409c2f 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -1,4 +1,85 @@ +package com.sngular.kloadgen.sampler; + +import com.fasterxml.jackson.databind.JsonNode; +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; +import com.sngular.kloadgen.testutil.FileHelper; +import com.sngular.kloadgen.testutil.SchemaParseUtil; +import com.sngular.kloadgen.util.ProducerKeysHelper; +import com.sngular.kloadgen.util.PropsKeysHelper; +import io.confluent.kafka.schemaregistry.ParsedSchema; +import org.apache.jmeter.threads.JMeterContext; +import org.apache.jmeter.threads.JMeterContextService; +import org.apache.jmeter.threads.JMeterVariables; +import org.apache.jmeter.util.JMeterUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.stream.Stream; + import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + class AsyncApiSamplerTest { - + private final FileHelper fileHelper = new FileHelper(); + + private JMeterContext jmcx; + + private static Stream parametersForConfigureValueGeneratorTest() { + return Stream.of("localhost:8081", ""); + } + + private AsyncApiSampler sampler = new AsyncApiSampler(); + + private ApiExtractor apiExtractor; + @BeforeEach + public final void setUp() throws IOException { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + sampler = new AsyncApiSampler(); + apiExtractor = mock(ApiExtractor.class); + + } + + /*@Test + void testAsyncApiSampleBasic() throws IOException { + JsonNode asyncApiFileNode = mock(JsonNode.class); + sampler.setAsyncApiFileNode(asyncApiFileNode); + JMeterVariables jmvar = new JMeterVariables(); + jmvar.putAll(getVariablesJsonSchema()); + + + + + }*/ + + + public JMeterVariables getVariablesJsonSchema() throws IOException { + + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); + + final var variables = new JMeterVariables(); + variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); + variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED); + variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); + return variables; + } + + + } \ No newline at end of file From 1f790278c58cdf553daeeafd4a26ae5e19a9cd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GracielaM=C3=A9ndezOlmos?= Date: Mon, 27 Nov 2023 09:40:18 +0100 Subject: [PATCH 46/55] "Changes" --- .../OSS_checkstyle_suppressions.xml | 1 + pom-maven-central.xml | 27 +++- pom.xml | 21 +++ ...ueFileSerializedConfigElementBeanInfo.java | 38 ++--- .../kloadgen/extractor/SchemaExtractor.java | 14 +- .../extractors/ExtractorFactory.java | 36 +++-- .../extractors/ExtractorRegistry.java | 9 +- .../avro/AvroConfluentExtractor.java | 7 +- .../extractors/avro/AvroExtractor.java | 12 +- .../extractors/json/JsonDefaultExtractor.java | 12 +- .../extractors/json/JsonExtractor.java | 15 +- .../AbstractProtoFileExtractor.java | 28 +--- .../ProtoBufApicurioExtractor.java | 6 +- .../ProtoBufConfluentExtractor.java | 14 +- .../ProtobufExtractor.java} | 28 ++-- .../loadgen/impl/ProtobufLoadGenerator.java | 12 +- .../kloadgen/parsedschema/IParsedSchema.java | 13 ++ .../kloadgen/parsedschema/ParsedSchema.java | 150 ++++++++++++++++++ .../impl/AvroObjectCreatorFactory.java | 24 +-- .../impl/ProtobufObjectCreatorFactory.java | 18 +-- .../editor/FileSubjectPropertyEditor.java | 52 +++--- .../sampler/KafkaProducerSampler.java | 30 ++-- .../sngular/kloadgen/sampler/SamplerUtil.java | 18 +-- .../sampler/gui/AsyncApiSamplerGui.java | 44 ++--- .../impl/ApicurioParsedSchemaMetadata.java | 2 +- .../impl/ConfluentParsedSchemaMetadata.java | 14 +- .../impl/ConfluentSchemaRegistry.java | 25 ++- .../extractor/SchemaExtractorTest.java | 37 +++-- .../asyncapi/AsyncApiExtractorImplTest.java | 80 +++++----- .../extractors/ExtractorFactoryTest.java | 91 +++++++++++ .../avro/AvroApicurioExtractorTest.java | 5 +- .../avro/AvroConfluentExtractorTest.java | 54 ++++--- .../ProtobufApicurioExtractorTest.java | 10 +- .../ProtobufConfluentExtractorTest.java | 30 ++-- .../processor/AvroSchemaProcessorTest.java | 31 ++-- .../processor/JsonSchemaProcessorTest.java | 16 +- .../ProtobufSchemaProcessorTest.java | 42 +++-- .../editor/FileSubjectPropertyEditorTest.java | 13 +- .../kloadgen/sampler/SamplerUtilTest.java | 35 ++-- .../serializer/AvroDeserializerTest.java | 20 ++- .../GenericRecordAvroSerializersTest.java | 15 +- .../serializer/JsonSerializerTest.java | 15 +- .../serializer/ProtobufSerializerTest.java | 69 ++++---- ...ava => ProtobufSerializerTestFixture.java} | 12 +- .../kloadgen/testutil/ParsedSchemaUtil.java | 17 +- .../kloadgen/testutil/SchemaParseUtil.java | 42 ----- .../resources/avro-files/testCastIssue.avsc | 28 ++++ 47 files changed, 764 insertions(+), 568 deletions(-) rename src/main/java/com/sngular/kloadgen/extractor/extractors/{protobuff => protobuf}/AbstractProtoFileExtractor.java (96%) rename src/main/java/com/sngular/kloadgen/extractor/extractors/{protobuff => protobuf}/ProtoBufApicurioExtractor.java (90%) rename src/main/java/com/sngular/kloadgen/extractor/extractors/{protobuff => protobuf}/ProtoBufConfluentExtractor.java (50%) rename src/main/java/com/sngular/kloadgen/extractor/extractors/{protobuff/ProtobuffExtractor.java => protobuf/ProtobufExtractor.java} (53%) create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java create mode 100644 src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java rename src/test/java/com/sngular/kloadgen/extractor/extractors/{protobuff => protobuf}/ProtobufApicurioExtractorTest.java (99%) rename src/test/java/com/sngular/kloadgen/extractor/extractors/{protobuff => protobuf}/ProtobufConfluentExtractorTest.java (95%) rename src/test/java/com/sngular/kloadgen/serializer/{ProtobuffSerializerTestFixture.java => ProtobufSerializerTestFixture.java} (99%) delete mode 100644 src/test/java/com/sngular/kloadgen/testutil/SchemaParseUtil.java create mode 100644 src/test/resources/avro-files/testCastIssue.avsc diff --git a/config/checkstyle/OSS_checkstyle_suppressions.xml b/config/checkstyle/OSS_checkstyle_suppressions.xml index 66733102..0f269aa4 100644 --- a/config/checkstyle/OSS_checkstyle_suppressions.xml +++ b/config/checkstyle/OSS_checkstyle_suppressions.xml @@ -15,6 +15,7 @@ + diff --git a/pom-maven-central.xml b/pom-maven-central.xml index 6f71fc15..cc4defa9 100644 --- a/pom-maven-central.xml +++ b/pom-maven-central.xml @@ -301,6 +301,17 @@ Europe/Madrid + + RobertoSngular + Roberto Riveira Veiga + roberto.riveira@sngular.com + Sngular + https://sngular.github.io/ + + Backend Developer + + Europe/Madrid + @@ -658,7 +669,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.1.2 + 3.3.0 com.puppycrawl.tools @@ -692,7 +703,7 @@ com.github.ekryd.sortpom sortpom-maven-plugin - 3.0.0 + 3.3.0 @@ -705,7 +716,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.9.0 true true @@ -717,7 +728,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources @@ -730,7 +741,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.2 + 3.4.0 attach-javadocs @@ -775,7 +786,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -786,7 +797,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.1.0 sign-artifacts @@ -852,7 +863,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.3.0 diff --git a/pom.xml b/pom.xml index a44fba56..d9000804 100644 --- a/pom.xml +++ b/pom.xml @@ -310,6 +310,27 @@ Trainee Backend Developer + + + GraciMndzSNG + Graciela Méndez Olmos + graciela.mendez@sngular.com + Sngular + https://sngular.github.io/ + + Backend Developer + + Europe/Madrid + + + pablorodriguez-sngular + Pablo Rodríguez Pérez + pablo.rodriguezp@sngular.com + Sngular + https://sngular.github.io/ + + Backend Developer + Europe/Madrid diff --git a/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java index 0e3d9c2e..dc82d504 100644 --- a/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java +++ b/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java @@ -6,19 +6,15 @@ package com.sngular.kloadgen.config.valuefileserialized; -import java.beans.PropertyDescriptor; -import java.util.ArrayList; - import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.property.editor.FileSubjectPropertyEditor; -import com.sngular.kloadgen.property.editor.NameStrategyPropertyEditor; -import com.sngular.kloadgen.property.editor.SchemaConverterPropertyEditor; -import com.sngular.kloadgen.property.editor.SchemaTypePropertyEditor; -import com.sngular.kloadgen.property.editor.ValueSerializerPropertyEditor; +import com.sngular.kloadgen.property.editor.*; import org.apache.jmeter.testbeans.BeanInfoSupport; import org.apache.jmeter.testbeans.gui.TableEditor; import org.apache.jmeter.testbeans.gui.TypeEditor; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; + public class ValueFileSerializedConfigElementBeanInfo extends BeanInfoSupport { private static final String VALUE_SUBJECT_NAME = "valueSubjectName"; @@ -42,33 +38,23 @@ public ValueFileSerializedConfigElementBeanInfo() { final PropertyDescriptor nameStrategyPropertyProps = property(VALUE_NAME_STRATEGY); nameStrategyPropertyProps.setPropertyEditorClass(NameStrategyPropertyEditor.class); - nameStrategyPropertyProps.setValue(NOT_UNDEFINED, Boolean.TRUE); - nameStrategyPropertyProps.setValue(DEFAULT, ""); - nameStrategyPropertyProps.setValue(NOT_EXPRESSION, Boolean.FALSE); + complete(nameStrategyPropertyProps); final PropertyDescriptor serializerPropertyProps = property(VALUE_SERIALIZER_PROPERTY); serializerPropertyProps.setPropertyEditorClass(ValueSerializerPropertyEditor.class); - serializerPropertyProps.setValue(NOT_UNDEFINED, Boolean.TRUE); - serializerPropertyProps.setValue(DEFAULT, ""); - serializerPropertyProps.setValue(NOT_EXPRESSION, Boolean.FALSE); + complete(serializerPropertyProps); final PropertyDescriptor subjectNameProps = property(VALUE_SUBJECT_NAME); subjectNameProps.setPropertyEditorClass(FileSubjectPropertyEditor.class); - subjectNameProps.setValue(NOT_UNDEFINED, Boolean.TRUE); - subjectNameProps.setValue(DEFAULT, ""); - subjectNameProps.setValue(NOT_EXPRESSION, Boolean.FALSE); + complete(subjectNameProps); final PropertyDescriptor schemaType = property(VALUE_SCHEMA_TYPE); schemaType.setPropertyEditorClass(SchemaTypePropertyEditor.class); - schemaType.setValue(NOT_UNDEFINED, Boolean.TRUE); - schemaType.setValue(DEFAULT, ""); - schemaType.setValue(NOT_EXPRESSION, Boolean.FALSE); + complete(schemaType); final PropertyDescriptor avroSchemaProps = property(VALUE_SCHEMA_DEFINITION); avroSchemaProps.setPropertyEditorClass(SchemaConverterPropertyEditor.class); - avroSchemaProps.setValue(NOT_UNDEFINED, Boolean.TRUE); - avroSchemaProps.setValue(DEFAULT, ""); - avroSchemaProps.setValue(NOT_EXPRESSION, Boolean.FALSE); + complete(avroSchemaProps); final TypeEditor tableEditor = TypeEditor.TableEditor; final PropertyDescriptor tableProperties = property(VALUE_SCHEMA_PROPERTIES, tableEditor); @@ -79,4 +65,10 @@ public ValueFileSerializedConfigElementBeanInfo() { tableProperties.setValue(DEFAULT, new ArrayList<>()); tableProperties.setValue(NOT_UNDEFINED, Boolean.TRUE); } + + private void complete(final PropertyDescriptor propertyDescriptor) { + propertyDescriptor.setValue(NOT_UNDEFINED, Boolean.TRUE); + propertyDescriptor.setValue(DEFAULT, ""); + propertyDescriptor.setValue(NOT_EXPRESSION, Boolean.FALSE); + } } diff --git a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java index 86fc9ede..e8161d69 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java @@ -1,5 +1,12 @@ package com.sngular.kloadgen.extractor; +import com.sngular.kloadgen.common.SchemaRegistryEnum; +import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; +import lombok.Getter; +import org.apache.commons.lang3.tuple.Pair; + import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -7,13 +14,6 @@ import java.util.List; import java.util.stream.Stream; -import com.sngular.kloadgen.common.SchemaRegistryEnum; -import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; -import com.sngular.kloadgen.model.FieldValueMapping; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import lombok.Getter; -import org.apache.commons.lang3.tuple.Pair; - @Getter public final class SchemaExtractor { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index be6b5399..aa0c87e6 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -1,17 +1,13 @@ package com.sngular.kloadgen.extractor.extractors; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Properties; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.extractors.avro.AvroExtractor; import com.sngular.kloadgen.extractor.extractors.json.JsonExtractor; -import com.sngular.kloadgen.extractor.extractors.protobuff.ProtobuffExtractor; +import com.sngular.kloadgen.extractor.extractors.protobuf.ProtobufExtractor; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; import com.sngular.kloadgen.util.JMeterHelper; @@ -20,23 +16,35 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.threads.JMeterContextService; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + public final class ExtractorFactory { - private static final AvroExtractor AVRO_EXTRACTOR = new AvroExtractor<>(); + private static AvroExtractor avroExtractor = new AvroExtractor(); - private static final JsonExtractor JSON_EXTRACTOR = new JsonExtractor(); + private static JsonExtractor jsonExtractor = new JsonExtractor(); - private static final ProtobuffExtractor PROTOBUFF_EXTRACTOR = new ProtobuffExtractor(); + private static ProtobufExtractor protobufExtractor = new ProtobufExtractor(); private ExtractorFactory() { } - public static ExtractorRegistry getExtractor(final String schemaType) { + public static void configExtractorFactory(final AvroExtractor avroExtractor, final JsonExtractor jsonExtractor, final ProtobufExtractor protobufExtractor) { + ExtractorFactory.avroExtractor = avroExtractor; + ExtractorFactory.jsonExtractor = jsonExtractor; + ExtractorFactory.protobufExtractor = protobufExtractor; + } + + public static ExtractorRegistry getExtractor(final String schemaType) { if (schemaType != null && EnumUtils.isValidEnum(SchemaTypeEnum.class, schemaType.toUpperCase())) { return switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) { - case JSON -> JSON_EXTRACTOR; - case AVRO -> AVRO_EXTRACTOR; - case PROTOBUF -> PROTOBUFF_EXTRACTOR; + case JSON -> jsonExtractor; + case AVRO -> avroExtractor; + case PROTOBUF -> protobufExtractor; + default -> throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); }; } else { throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); @@ -60,7 +68,7 @@ public static Pair> flatPropertiesList(final Str case APICURIO -> ((ApicurioParsedSchemaMetadata) parsedSchemaAdapter).getSchema(); case CONFLUENT -> parsedSchemaAdapter.getRawSchema(); }; - attributeList.addAll(getExtractor(schemaType).processSchema(schema, schemaRegistryEnum)); + attributeList.addAll(getExtractor(schemaType).processSchema(new ParsedSchema(schema), schemaRegistryEnum)); } return Pair.of(schemaType, attributeList); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java index 27026c59..07768734 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java @@ -1,14 +1,15 @@ package com.sngular.kloadgen.extractor.extractors; -import java.util.List; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; + +import java.util.List; -public interface ExtractorRegistry { +public interface ExtractorRegistry { List processSchema(final T schema, SchemaRegistryEnum registry); - Object processSchema(final String fileContent); + T processSchema(final String fileContent); List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java index 4dc1513b..e4cf9089 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java @@ -1,12 +1,11 @@ package com.sngular.kloadgen.extractor.extractors.avro; -import java.util.List; - import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; -import io.confluent.kafka.schemaregistry.avro.AvroSchema; import org.apache.avro.Schema; +import java.util.List; + public class AvroConfluentExtractor extends AbstractAvroFileExtractor implements Extractor { public final List processSchema(final Schema schema) { @@ -14,7 +13,7 @@ public final List processSchema(final Schema schema) { } public final List getSchemaNameList(final String schema) { - return getSchemaNameList(new AvroSchema(schema).rawSchema()); + return getSchemaNameList(new Schema.Parser().parse(schema)); } } \ No newline at end of file diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index 2c52e527..2dd462a2 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -1,27 +1,25 @@ package com.sngular.kloadgen.extractor.extractors.avro; -import java.util.List; -import java.util.Map; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import io.confluent.kafka.schemaregistry.avro.AvroSchema; +import com.sngular.kloadgen.parsedschema.ParsedSchema; + +import java.util.List; +import java.util.Map; public class AvroExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, new AvroApicurioExtractor()); - public final List processSchema(final T schema, final SchemaRegistryEnum registryEnum) { return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema); } public final ParsedSchema processSchema(final String fileContent) { - return new AvroSchema(fileContent); + return new ParsedSchema(fileContent, "AVRO"); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java index 618cbce9..3225025f 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java @@ -1,22 +1,22 @@ package com.sngular.kloadgen.extractor.extractors.json; +import com.sngular.kloadgen.extractor.extractors.Extractor; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.json.Field; +import com.sngular.kloadgen.model.json.Schema; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import com.sngular.kloadgen.extractor.extractors.Extractor; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.model.json.Field; -import com.sngular.kloadgen.model.json.Schema; - public class JsonDefaultExtractor extends AbstractJsonExtractor implements Extractor { @Override public final List processSchema(final String schema) { - final Schema parsed = getSchemaParser().parse(schema.toString()); + final Schema parsed = getSchemaParser().parse(schema); final List attributeList = new ArrayList<>(); parsed.getProperties().forEach(field -> attributeList.addAll(processField(field, true, null))); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java index 2988d8e2..f8aaf4b9 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java @@ -1,27 +1,26 @@ package com.sngular.kloadgen.extractor.extractors.json; -import java.util.List; -import java.util.Map; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import io.confluent.kafka.schemaregistry.json.JsonSchema; +import com.sngular.kloadgen.parsedschema.ParsedSchema; + +import java.util.List; +import java.util.Map; -public class JsonExtractor implements ExtractorRegistry { +public class JsonExtractor implements ExtractorRegistry { private static final Map> SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new JsonDefaultExtractor(), SchemaRegistryEnum.APICURIO, new JsonDefaultExtractor()); public final List processSchema(final T schemaReceived, final SchemaRegistryEnum registryEnum) { - return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.toString()); + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.rawSchema().toString()); } public final ParsedSchema processSchema(final String fileContent) { - return new JsonSchema(fileContent); + return new ParsedSchema(fileContent, "JSON"); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/AbstractProtoFileExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java similarity index 96% rename from src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/AbstractProtoFileExtractor.java rename to src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java index 32282b7d..ea2f71b7 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/AbstractProtoFileExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java @@ -1,16 +1,4 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.github.os72.protobuf.dynamic.DynamicSchema; import com.google.protobuf.Descriptors; @@ -18,17 +6,17 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.util.ProtobufHelper; import com.squareup.wire.schema.Field; -import com.squareup.wire.schema.internal.parser.EnumConstantElement; -import com.squareup.wire.schema.internal.parser.EnumElement; -import com.squareup.wire.schema.internal.parser.FieldElement; -import com.squareup.wire.schema.internal.parser.MessageElement; -import com.squareup.wire.schema.internal.parser.OneOfElement; -import com.squareup.wire.schema.internal.parser.ProtoFileElement; -import com.squareup.wire.schema.internal.parser.TypeElement; +import com.squareup.wire.schema.internal.parser.*; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public abstract class AbstractProtoFileExtractor { public static final String ARRAY_POSTFIX = "-array"; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufApicurioExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java similarity index 90% rename from src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufApicurioExtractor.java rename to src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java index 509fe09c..8170c571 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufApicurioExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java @@ -1,11 +1,11 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.util.List; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.squareup.wire.schema.internal.parser.ProtoFileElement; +import java.util.List; + public class ProtoBufApicurioExtractor extends AbstractProtoFileExtractor implements Extractor { public final List processSchema(final ProtoFileElement schemaReceived) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java similarity index 50% rename from src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufConfluentExtractor.java rename to src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java index 3b24537a..7dca1ad1 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtoBufConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java @@ -1,15 +1,17 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.util.List; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.squareup.wire.schema.internal.parser.ProtoFileElement; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor { +import java.util.List; + +public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor { - public final List processSchema(final ProtobufSchema schemaReceived) { - return processSchemaDefault(schemaReceived.rawSchema()); + public final List processSchema(final ParsedSchema schemaReceived) { + return processSchemaDefault((ProtoFileElement) schemaReceived.rawSchema()); } public final List getSchemaNameList(final String schema) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobuffExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java similarity index 53% rename from src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobuffExtractor.java rename to src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java index bdfc42e7..b4d3a91f 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobuffExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java @@ -1,34 +1,26 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import com.squareup.wire.schema.internal.parser.ProtoFileElement; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; +import com.sngular.kloadgen.parsedschema.ParsedSchema; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; -public class ProtobuffExtractor implements ExtractorRegistry { +public class ProtobufExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new ProtoBufConfluentExtractor(), SchemaRegistryEnum.APICURIO, new ProtoBufApicurioExtractor()); public final List processSchema(final T schemaReceived, final SchemaRegistryEnum registryEnum) { - final var resultSchema = new ArrayList(); - if (schemaReceived instanceof ProtoFileElement) { - resultSchema.addAll(SCHEMA_REGISTRY_MAP.get(SchemaRegistryEnum.APICURIO).processSchema(schemaReceived)); - } else { - resultSchema.addAll(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived)); - } - return resultSchema; + return new ArrayList(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived)); } - public final ParsedSchema processSchema(final String fileContent) { - return new ProtobufSchema(fileContent); + public final T processSchema(final String fileContent) { + return (T) new ParsedSchema(fileContent, "PROTOBUF"); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java index 9e1f747e..931c15e6 100644 --- a/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java +++ b/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java @@ -1,10 +1,5 @@ package com.sngular.kloadgen.loadgen.impl; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; @@ -18,6 +13,11 @@ import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + @Slf4j public class ProtobufLoadGenerator implements SRLoadGenerator, BaseLoadGenerator { @@ -45,7 +45,7 @@ public final void setUpGenerator( public final void setUpGenerator(final String schema, final List fieldExprMappings) { final ProtobufSchema protobufSchema = new ProtobufSchema(schema); this.protobufSchemaProcessor - .processSchema(SchemaTypeEnum.PROTOBUF, protobufSchema, new BaseSchemaMetadata<>( + .processSchema(SchemaTypeEnum.PROTOBUF, protobufSchema.rawSchema(), new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new SchemaMetadata(1, 1, SchemaTypeEnum.PROTOBUF.name(), Collections.emptyList(), schema))), fieldExprMappings); } diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java new file mode 100644 index 00000000..b7d46327 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java @@ -0,0 +1,13 @@ +package com.sngular.kloadgen.parsedschema; + +public interface IParsedSchema { + + String schemaType(); + + String name(); + + String canonicalString(); + + Object rawSchema(); + +} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java new file mode 100644 index 00000000..bc33fece --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java @@ -0,0 +1,150 @@ +package com.sngular.kloadgen.parsedschema; + +import com.sngular.kloadgen.exception.KLoadGenException; +import com.squareup.wire.schema.internal.parser.ProtoFileElement; +import io.confluent.kafka.schemaregistry.avro.AvroSchema; +import io.confluent.kafka.schemaregistry.json.JsonSchema; +import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; +import org.apache.avro.Schema; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class ParsedSchema implements IParsedSchema { + + private final T schema; + private final String schemaType; + + public ParsedSchema(final String fileContent, final String schemaType) { + switch (schemaType) { + case "AVRO" -> { + this.schema = (T) new Schema.Parser().parse(fileContent); + } + case "JSON" -> { + this.schema = (T) new JsonSchema(fileContent); + } + case "PROTOBUF" -> { + this.schema = (T) new ProtobufSchema(fileContent); + } + default -> throw new IllegalArgumentException("schemaType not supported: " + schemaType); + } + this.schemaType = schemaType; + } + + public ParsedSchema(final File file, final String schemaType) throws IOException { + this(new String(Files.readAllBytes(file.toPath())), schemaType); + } + + public ParsedSchema(final T schema, final String type) { + this.schema = schema; + this.schemaType = type; + } + + public ParsedSchema(final T schema) { + this.schema = schema; + this.schemaType = switch (this.schema.getClass().getSimpleName()) { + case "Schema", "AvroSchema", "UnionSchema", "RecordSchema" -> "AVRO"; + case "ProtoBuf", "ProtoFileElement" -> "PROTOBUF"; + case "JsonSchema", "ObjectSchema" -> "JSON"; + default -> throw new KLoadGenException(String.format("Need to specify schemaType for %s", this.schema.getClass().getSimpleName())); + }; + } + + public ParsedSchema(final io.confluent.kafka.schemaregistry.ParsedSchema parsedSchema) throws IOException { + this(parsedSchema.canonicalString(), parsedSchema.schemaType()); + } + + public final Object schema() { + return this.schema; + } + + public final String schemaType() { + return this.schemaType; + } + + public final String name() { + return null; + } + + public final String canonicalString() { + return switch (this.schemaType) { + case "AVRO" -> stringAvro(this.schema); + case "JSON" -> stringJson(this.schema); + case "PROTOBUF" -> stringProto(this.schema); + default -> this.schema.toString(); + }; + } + + private String stringAvro(final T schema) { + final String result; + if (schema instanceof AvroSchema) { + result = ((AvroSchema) this.schema).canonicalString(); + } else { + result = this.schema.toString(); + } + return result; + } + + private String stringJson(final T schema) { + final String result; + if (schema instanceof JsonSchema) { + result = ((JsonSchema) this.schema).canonicalString(); + } else { + result = this.schema.toString(); + } + return result; + } + + private String stringProto(final T schema) { + final String result; + if (schema instanceof ProtobufSchema) { + result = ((ProtobufSchema) this.schema).canonicalString(); + } else if (schema instanceof ProtoFileElement) { + result = ((ProtoFileElement) this.schema).toSchema(); + } else { + result = this.schema.toString(); + } + return result; + } + + public final Object rawSchema() { + return switch (this.schemaType) { + case "AVRO" -> rawAvro(this.schema); + case "JSON" -> rawJson(this.schema); + case "PROTOBUF" -> rawProto(this.schema); + default -> this.schema; + }; + } + + private Object rawAvro(final T schema) { + final Object result; + if (schema instanceof AvroSchema) { + result = ((AvroSchema) this.schema).rawSchema(); + } else { + result = this.schema; + } + return result; + } + + private Object rawJson(final T schema) { + final Object result; + if (schema instanceof JsonSchema) { + result = ((JsonSchema) this.schema).rawSchema(); + } else { + result = this.schema.toString(); + } + return result; + } + + private Object rawProto(final T schema) { + final Object result; + if (schema instanceof ProtobufSchema) { + result = ((ProtobufSchema) this.schema).rawSchema(); + } else { + result = this.schema; + } + return result; + } + +} diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java index 48b655f2..992f4c52 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java @@ -1,36 +1,24 @@ package com.sngular.kloadgen.processor.objectcreatorfactory.impl; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.ConstraintTypeEnum; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO; import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory; import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.randomtool.generator.AvroGeneratorTool; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; +import com.sngular.kloadgen.schemaregistry.adapter.impl.*; import com.sngular.kloadgen.serializer.EnrichedRecord; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.avro.Schema; import org.apache.avro.Schema.Type; import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericRecord; import org.apache.commons.collections4.IteratorUtils; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + public final class AvroObjectCreatorFactory implements ObjectCreatorFactory { private static final AvroGeneratorTool AVRO_GENERATOR_TOOL = new AvroGeneratorTool(); diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java index abab03c3..f52c7e41 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java @@ -1,16 +1,5 @@ package com.sngular.kloadgen.processor.objectcreatorfactory.impl; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - import com.google.protobuf.Descriptors; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.DescriptorValidationException; @@ -20,6 +9,7 @@ import com.google.protobuf.DynamicMessage.Builder; import com.google.protobuf.Message; import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO; import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory; import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; @@ -30,9 +20,13 @@ import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.squareup.wire.schema.internal.parser.ProtoFileElement; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.commons.lang3.StringUtils; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + public class ProtobufObjectCreatorFactory implements ObjectCreatorFactory { private static final ProtoBufGeneratorTool PROTOBUF_GENERATOR_TOOL = new ProtoBufGeneratorTool(); diff --git a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java index b1aa7409..0655c43e 100644 --- a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java +++ b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java @@ -6,34 +6,14 @@ package com.sngular.kloadgen.property.editor; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.beans.PropertyDescriptor; -import java.beans.PropertyEditor; -import java.beans.PropertyEditorSupport; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.filechooser.FileSystemView; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.extractor.SchemaExtractor; import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.util.PropsKeysHelper; -import io.confluent.kafka.schemaregistry.ParsedSchema; import lombok.extern.slf4j.Slf4j; import org.apache.avro.AvroRuntimeException; import org.apache.jmeter.gui.ClearGui; @@ -42,9 +22,23 @@ import org.apache.jmeter.testbeans.gui.TableEditor; import org.apache.jmeter.testbeans.gui.TestBeanGUI; import org.apache.jmeter.testbeans.gui.TestBeanPropertyEditor; -import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.util.JMeterUtils; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.beans.PropertyDescriptor; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorSupport; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + @Slf4j public class FileSubjectPropertyEditor extends PropertyEditorSupport implements TestBeanPropertyEditor, ClearGui { @@ -56,8 +50,6 @@ public class FileSubjectPropertyEditor extends PropertyEditorSupport implements private final JButton openFileDialogButton = new JButton(JMeterUtils.getResString("file_visualizer_open")); - private ParsedSchema parserSchema; - private JComboBox schemaTypeComboBox; public FileSubjectPropertyEditor() { @@ -98,11 +90,9 @@ public final void actionFileChooser(final ActionEvent event) { final String schemaType = schemaTypeComboBox.getSelectedItem().toString(); final ExtractorRegistry extractor = ExtractorFactory.getExtractor(schemaType); final String fileContent = SchemaExtractor.readSchemaFile(schemaFile.getPath()); - this.parserSchema = (ParsedSchema) extractor.processSchema(fileContent); + final ParsedSchema parserSchema = (ParsedSchema) extractor.processSchema(fileContent); final List schemaFieldList = extractor.processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT); - buildTable(schemaFieldList); - JMeterContextService.getContext().getProperties().setProperty(PropsKeysHelper.VALUE_SCHEMA, fileContent); - JMeterContextService.getContext().getProperties().setProperty(PropsKeysHelper.VALUE_SCHEMA_TYPE, schemaType); + buildTable(schemaFieldList, fileContent, schemaType); } catch (final IOException e) { JOptionPane.showMessageDialog(panel, "Can't read a file : " + e.getMessage(), ERROR_FAILED_TO_RETRIEVE_PROPERTIES, JOptionPane.ERROR_MESSAGE); @@ -119,7 +109,7 @@ public final List getAttributeList(final ParsedSchema selecte return result; } - public final void buildTable(final List attributeList) { + public final void buildTable(final List attributeList, final String fileContent, final String schemaType) { if (!attributeList.isEmpty()) { try { @@ -138,6 +128,10 @@ public final void buildTable(final List attributeList) { for (PropertyEditor propertyEditor : propertyEditors) { if (propertyEditor instanceof TableEditor) { propertyEditor.setValue(attributeList); + } else if (propertyEditor instanceof SchemaConverterPropertyEditor) { + propertyEditor.setValue(fileContent); + } else if (propertyEditor instanceof SchemaTypePropertyEditor) { + propertyEditor.setValue(schemaType); } } } catch (NoSuchFieldException | IllegalAccessException e) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java index 3664785d..0bfc683b 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java @@ -6,17 +6,6 @@ package com.sngular.kloadgen.sampler; -import java.io.Serial; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ExecutionException; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.model.HeaderMapping; @@ -43,6 +32,12 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.serialization.StringSerializer; +import java.io.Serial; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ExecutionException; + public final class KafkaProducerSampler extends AbstractJavaSamplerClient implements Serializable { private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; @@ -134,7 +129,6 @@ public SampleResult runTest(final JavaSamplerContext javaSamplerContext) { final var kafkaHeaders = safeGetKafkaHeaders(jMeterContext); if (Objects.nonNull(messageVal)) { - try { final var producerRecord = getProducerRecord(messageVal, enrichedKeyFlag(), enrichedValueFlag()); final var headersSB = new ArrayList<>(SamplerUtil.populateHeaders(kafkaHeaders, producerRecord)); @@ -197,10 +191,20 @@ private Boolean enrichedValueFlag() { private void fillSamplerResult(final ProducerRecord producerRecord, final SampleResult sampleResult) { final String result = "key: " + producerRecord.key() - + ", payload: " + producerRecord.value(); + + ", payload: " + stringValue(producerRecord.value()); sampleResult.setSamplerData(result); } + private String stringValue(final Object value) { + final String result; + if (value instanceof EnrichedRecord) { + result = ((EnrichedRecord) value).getGenericRecord().toString(); + } else { + result = value.toString(); + } + return result; + } + private void fillSampleResult(final SampleResult sampleResult, final String respondeData, final boolean successful) { sampleResult.setResponseData(respondeData, StandardCharsets.UTF_8.name()); sampleResult.setSuccessful(successful); diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index 80dc89be..055b3498 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -6,18 +6,6 @@ package com.sngular.kloadgen.sampler; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.AvroSRLoadGenerator; @@ -49,6 +37,10 @@ import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.common.security.auth.SecurityProtocol; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.*; + public final class SamplerUtil { private static final StatelessGeneratorTool STATELESS_GENERATOR_TOOL = new StatelessGeneratorTool(); @@ -344,7 +336,7 @@ public static BaseLoadGenerator configureValueGenerator(final Properties props) } generator.setUpGenerator(schema, (List) jMeterVariables.getObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES)); } catch (final SchemaParseException exc) { - generator.setUpGenerator(props.getProperty(PropsKeysHelper.VALUE_SCHEMA), (List) jMeterVariables.getObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES)); + generator.setUpGenerator(jMeterVariables.get(PropsKeysHelper.VALUE_SCHEMA), (List) jMeterVariables.getObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES)); } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 1f56866d..0daae73d 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -12,33 +12,6 @@ package com.sngular.kloadgen.sampler.gui; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileSystemView; -import javax.swing.table.DefaultTableModel; - import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; @@ -61,6 +34,17 @@ import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import java.util.*; + +@SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final JFileChooser fileChooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); @@ -81,8 +65,6 @@ public final class AsyncApiSamplerGui extends AbstractSamplerGui { private JComboBox topicComboBox; - private JComboBox registryComboBox; - private AsyncApiFile asyncApiFile; public AsyncApiSamplerGui() { @@ -362,10 +344,10 @@ private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new BorderLayout(0, 0)); registryUrlPanel.add(new JLabeledTextField("Schema Registry URL")); - registryComboBox = new JComboBox<>(); + final JComboBox registryComboBox = new JComboBox<>(); registryComboBox.setRenderer(new AsyncApiSRRenderer()); registryComboBox.addActionListener(this::registryComboActionListener); - registryUrlPanel.add(this.registryComboBox, BorderLayout.NORTH); + registryUrlPanel.add(registryComboBox, BorderLayout.NORTH); registryUrlPanel.add(new JScrollPane(new JTable(schemaRegistryFieldModel)), BorderLayout.CENTER); return registryUrlPanel; } diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java index 4d91b818..4f17938e 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java @@ -1,6 +1,6 @@ package com.sngular.kloadgen.schemaregistry.adapter.impl; -import io.confluent.kafka.schemaregistry.ParsedSchema; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java index 182ffc69..99d3e10e 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java @@ -1,6 +1,6 @@ package com.sngular.kloadgen.schemaregistry.adapter.impl; -import io.confluent.kafka.schemaregistry.ParsedSchema; +import com.sngular.kloadgen.parsedschema.IParsedSchema; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; import lombok.Getter; import org.apache.avro.Schema; @@ -8,15 +8,15 @@ @Getter public final class ConfluentParsedSchemaMetadata extends AbstractParsedSchemaAdapter { - private String schemaType; + private final String schemaType; - private String name; + private final String name; private String canonicalString; private Object rawSchema; - private ConfluentParsedSchemaMetadata(final ParsedSchema parsedSchema) { + private ConfluentParsedSchemaMetadata(final IParsedSchema parsedSchema) { this.schemaType = parsedSchema.schemaType(); this.name = parsedSchema.name(); this.canonicalString = parsedSchema.canonicalString(); @@ -35,11 +35,7 @@ public ConfluentParsedSchemaMetadata(final ProtobufSchema schema) { this.canonicalString = schema.canonicalString(); } - public ConfluentParsedSchemaMetadata() { - - } - - public static AbstractParsedSchemaAdapter parse(final ParsedSchema parsedSchema) { + public static AbstractParsedSchemaAdapter parse(final IParsedSchema parsedSchema) { return new ConfluentParsedSchemaMetadata(parsedSchema); } diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java index 66b25fb1..8b98d8f4 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java @@ -1,20 +1,9 @@ package com.sngular.kloadgen.schemaregistry.impl; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; -import io.confluent.kafka.schemaregistry.ParsedSchema; +import com.sngular.kloadgen.schemaregistry.adapter.impl.*; import io.confluent.kafka.schemaregistry.avro.AvroSchemaProvider; import io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient; import io.confluent.kafka.schemaregistry.client.SchemaRegistryClient; @@ -25,6 +14,12 @@ import lombok.extern.slf4j.Slf4j; import org.apache.jmeter.threads.JMeterContextService; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + @Slf4j public final class ConfluentSchemaRegistry implements SchemaRegistryAdapter { @@ -71,7 +66,7 @@ public BaseSchemaMetadata getLatestSchemaMetadata(final public BaseParsedSchema getSchemaBySubject(final String subjectName) { try { final ConfluentSchemaMetadata schemaMetadata = ConfluentSchemaMetadata.parse(this.schemaRegistryClient.getLatestSchemaMetadata(subjectName)); - final ParsedSchema parsedSchema = this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, schemaMetadata.getId()); + final ParsedSchema parsedSchema = new ParsedSchema(this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, schemaMetadata.getId())); final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = ConfluentParsedSchemaMetadata.parse(parsedSchema); return new BaseParsedSchema(abstractParsedSchemaAdapter); } catch (RestClientException | IOException e) { @@ -82,7 +77,7 @@ public BaseParsedSchema getSchemaBySubject(final public BaseParsedSchema getSchemaBySubjectAndId(final String subjectName, final BaseSchemaMetadata metadata) { try { - final ParsedSchema parsedSchema = this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, metadata.getSchemaMetadataAdapter().getId()); + final ParsedSchema parsedSchema = new ParsedSchema(this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, metadata.getSchemaMetadataAdapter().getId())); final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = ConfluentParsedSchemaMetadata.parse(parsedSchema); return new BaseParsedSchema(abstractParsedSchemaAdapter); } catch (RestClientException | IOException e) { diff --git a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java index 7f2255ba..f244472b 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java @@ -6,22 +6,16 @@ package com.sngular.kloadgen.extractor; -import java.io.File; -import java.io.IOException; -import java.util.Locale; -import java.util.Properties; - import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.testutil.ParsedSchemaUtil; -import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.JMeterHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -37,6 +31,11 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.Properties; + @ExtendWith(MockitoExtension.class) class SchemaExtractorTest { @@ -74,7 +73,7 @@ void testFlatPropertiesListWithAVRO() throws IOException { final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.APICURIO.toString()); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); final var baseParsedSchema = new BaseParsedSchema<>(ApicurioParsedSchemaMetadata.parse(parsedSchema)); jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); @@ -90,7 +89,7 @@ void testFlatPropertiesListWithJson() throws IOException { final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final var parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); + final var parsedSchema = new ParsedSchema(testFile, "JSON"); final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); @@ -106,8 +105,8 @@ void testFlatPropertiesListWithProtobuf() throws IOException { final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final var parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "PROTOBUF"); + final BaseParsedSchema baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); final var result = SchemaExtractor.flatPropertiesList("protobufSubject"); @@ -140,4 +139,20 @@ void testFlatPropertiesListWithException() { } + @Test + @DisplayName("Test flatPropertiesList with AVRO and CONFLUENT") + void testSchemaTypeIsCorrectWhenAvroConfluent() throws IOException { + final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); + properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); + + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var baseParsedSchema = new BaseParsedSchema<>(ConfluentAbstractParsedSchemaMetadata.parse(parsedSchema)); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); + + final var result = SchemaExtractor.flatPropertiesList("avroSubject"); + + Assertions.assertThat(result).isNotNull(); + } + } diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java index b2b9b0c7..d42832fc 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -9,8 +9,6 @@ import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; import org.apache.jmeter.util.JMeterUtils; -import static org.assertj.core.api.Assertions.*; - import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -18,47 +16,47 @@ import java.io.File; import java.io.IOException; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.Locale; class AsyncApiExtractorImplTest { - private FileHelper fileHelper = new FileHelper(); - private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); - - @BeforeEach - public final void setUp() { - final File file = new File("src/test/resources"); - final String absolutePath = file.getAbsolutePath(); - JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); - final JMeterContext jmcx = JMeterContextService.getContext(); - jmcx.setVariables(new JMeterVariables()); - JMeterUtils.setLocale(Locale.ENGLISH); - } - - @Test - @DisplayName("Should extract asyncapi file") - void testExtractFile() throws IOException { - final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); - assertNotNull(asapfle); - assertEquals("{user_signedup=user_signedup}",asapfle.getApiSchemaList().toString()); - assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", - asapfle.getApiServerMap().toString()); - } - @Test - @DisplayName("Should extract basic asyncapi schema") - void testExtractAsyncapiSchema() throws IOException { - final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final JsonNode openApi = om.readTree(testFile); - final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processNode(openApi); - JsonNode propertiesSchema = asapfle.getAsyncApiFileNode().path("components").path("schemas").path("userSignedUpPayload").path("properties"); - Assertions.assertThat(asapfle).isNotNull(); - assertThat(propertiesSchema) - .hasSize(4) - .isSubsetOf(openApi.get("components").get("schemas").get("userSignedUpPayload").get("properties")); - } + private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + + private final FileHelper fileHelper = new FileHelper(); + + @BeforeEach + public final void setUp() { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + final JMeterContext jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + } + + @Test + @DisplayName("Should extract asyncapi file") + void testExtractFile() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); + + org.junit.jupiter.api.Assertions.assertNotNull(asapfle); + org.junit.jupiter.api.Assertions.assertEquals("{user_signedup=user_signedup}", asapfle.getApiSchemaList().toString()); + org.junit.jupiter.api.Assertions.assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", + asapfle.getApiServerMap().toString()); + } + + @Test + @DisplayName("Should extract basic asyncapi schema") + void testExtractAsyncapiSchema() throws IOException { + final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); + final JsonNode openApi = om.readTree(testFile); + final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processNode(openApi); + final JsonNode propertiesSchema = asapfle.getAsyncApiFileNode().path("components").path("schemas").path("userSignedUpPayload").path("properties"); + Assertions.assertThat(asapfle).isNotNull(); + Assertions.assertThat(propertiesSchema) + .hasSize(4) + .isSubsetOf(openApi.get("components").get("schemas").get("userSignedUpPayload").get("properties")); + } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java new file mode 100644 index 00000000..9bc20133 --- /dev/null +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java @@ -0,0 +1,91 @@ +package com.sngular.kloadgen.extractor.extractors; + +import com.sngular.kloadgen.common.SchemaRegistryEnum; +import com.sngular.kloadgen.extractor.SchemaExtractor; +import com.sngular.kloadgen.extractor.extractors.avro.AvroConfluentExtractor; +import com.sngular.kloadgen.extractor.extractors.avro.AvroExtractor; +import com.sngular.kloadgen.extractor.extractors.json.JsonExtractor; +import com.sngular.kloadgen.extractor.extractors.protobuf.ProtobufExtractor; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; +import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentAbstractParsedSchemaMetadata; +import com.sngular.kloadgen.testutil.FileHelper; +import com.sngular.kloadgen.util.JMeterHelper; +import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import org.apache.avro.Schema; +import org.apache.jmeter.threads.JMeterContext; +import org.apache.jmeter.threads.JMeterContextService; +import org.apache.jmeter.threads.JMeterVariables; +import org.apache.jmeter.util.JMeterUtils; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Properties; + + +@SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") +class ExtractorFactoryTest { + + @Captor + private ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Schema.class); + + private final Properties properties = new Properties(); + + private final Extractor avroConfluentExtractor = new AvroConfluentExtractor(); + + private MockedStatic jmeterHelperMockedStatic; + + private MockedStatic jmeterContextServiceMockedStatic; + + @BeforeEach + public void init() { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + final JMeterContext jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + + jmeterHelperMockedStatic = Mockito.mockStatic(JMeterHelper.class); + jmeterContextServiceMockedStatic = Mockito.mockStatic(JMeterContextService.class, Answers.RETURNS_DEEP_STUBS); + argumentCaptor = ArgumentCaptor.forClass(Schema.class); + } + + @AfterEach + public void tearDown() { + properties.clear(); + jmeterHelperMockedStatic.close(); + jmeterContextServiceMockedStatic.close(); + } + + @Test + void flatPropertiesList() throws IOException { + final AvroExtractor avroExtractor = Mockito.mock(AvroExtractor.class); + ExtractorFactory.configExtractorFactory(avroExtractor, new JsonExtractor(), new ProtobufExtractor()); + + final File testFile = new FileHelper().getFile("/avro-files/embedded-avros-example-test.avsc"); + properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); + + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var baseParsedSchema = new BaseParsedSchema<>(ConfluentAbstractParsedSchemaMetadata.parse(parsedSchema)); + + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); + + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); + + Mockito.when(avroExtractor.processSchema(new ParsedSchema(argumentCaptor.capture(), ""), ArgumentMatchers.isA(SchemaRegistryEnum.class))).thenReturn(fieldValueMappingList); + final var result = SchemaExtractor.flatPropertiesList(schema.getName()); + + Assertions.assertThat(result).isNotNull(); + } +} \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java index 387197f7..5ad7b5cd 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java @@ -1,7 +1,5 @@ package com.sngular.kloadgen.extractor.extractors.avro; -import java.util.List; - import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; @@ -10,6 +8,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + class AvroApicurioExtractorTest { private final FileHelper fileHelper = new FileHelper(); @@ -42,7 +42,6 @@ void testFlatPropertiesEmbeddedAvros() throws Exception { void testOptionalEnum() throws Exception { final String testFile = fileHelper.getContent("/avro-files/optionalEnum.avsc"); - //final ParsedSchema parsedSchema = avroConfluentExtractor.getSchemaNameList(testFile); final Schema schema = new Schema.Parser().parse(testFile); final List fieldValueMappingList = avroApicurioExtractor.processSchema(schema); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java index 6977c561..66d6db1e 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java @@ -1,15 +1,17 @@ package com.sngular.kloadgen.extractor.extractors.avro; -import java.util.List; - import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; -import io.confluent.kafka.schemaregistry.avro.AvroSchema; import org.apache.avro.Schema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.util.List; + class AvroConfluentExtractorTest { @@ -24,8 +26,8 @@ class AvroConfluentExtractorTest { void testFlatPropertiesEmbeddedAvros() throws Exception { final String testFile = fileHelper.getContent("/avro-files/embedded-avros-example-test.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(4) @@ -45,8 +47,8 @@ void testFlatPropertiesEmbeddedAvros() throws Exception { void testOptionalEnum() throws Exception { final String testFile = fileHelper.getContent("/avro-files/optionalEnum.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(1) @@ -68,8 +70,8 @@ void testOptionalEnum() throws Exception { void testFlatPropertiesOptionalMapArray() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testOptionalMap.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(8) @@ -97,8 +99,8 @@ void testFlatPropertiesOptionalMapArray() throws Exception { @DisplayName("Should extract Map of Record") void testFlatPropertiesMap() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testMap.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(9) @@ -129,8 +131,8 @@ void testFlatPropertiesMap() throws Exception { void testFlatPropertiesLogicalTypes() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testLogicalTypes.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(10) @@ -159,8 +161,8 @@ void testFlatPropertiesLogicalTypes() throws Exception { void testFlatPropertiesOptionalArray() throws Exception { final String testFile = fileHelper.getContent("/avro-files/issue.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -179,8 +181,8 @@ void testFlatPropertiesOptionalArray() throws Exception { void testFlatPropertiesUnionRecordAvros() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testUnionRecord.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(8) @@ -209,8 +211,8 @@ void testFlatPropertiesUnionRecordAvros() throws Exception { void testFlatPropertiesRecordUnionReverseOrder() throws Exception { final String testFile = fileHelper.getContent("/avro-files/testUnionReverseOrder.avsc"); - final AvroSchema schema = new AvroSchema(testFile); - final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema.rawSchema()); + final Schema schema = new Schema.Parser().parse(testFile); + final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(5) @@ -227,4 +229,18 @@ void testFlatPropertiesRecordUnionReverseOrder() throws Exception { .build()); } + @Test + @DisplayName("Should Extract Schema instead AvroSchema") + void testCastException() throws Exception { + final AvroConfluentExtractor avroCE = Mockito.mock(AvroConfluentExtractor.class); + final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Schema.class); + final String testFile = fileHelper.getContent("/avro-files/testCastIssue.avsc"); + final Schema schema = new Schema.Parser().parse(testFile); + avroCE.processSchema(schema); + + Mockito.verify(avroCE).processSchema(argumentCaptor.capture()); + final Schema captureSchema = argumentCaptor.getValue(); + Assertions.assertThat(schema).isEqualTo(captureSchema); + } + } diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufApicurioExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java similarity index 99% rename from src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufApicurioExtractorTest.java rename to src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java index 8f35d767..6462e62c 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufApicurioExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java @@ -1,8 +1,4 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.io.File; -import java.util.List; -import java.util.Locale; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; @@ -19,6 +15,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.io.File; +import java.util.List; +import java.util.Locale; + class ProtobufApicurioExtractorTest { private final FileHelper fileHelper = new FileHelper(); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufConfluentExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java similarity index 95% rename from src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufConfluentExtractorTest.java rename to src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java index 6f46ca64..c79a4169 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuff/ProtobufConfluentExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java @@ -1,13 +1,9 @@ -package com.sngular.kloadgen.extractor.extractors.protobuff; - -import java.io.File; -import java.util.List; -import java.util.Locale; +package com.sngular.kloadgen.extractor.extractors.protobuf; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; -import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -17,11 +13,15 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.io.File; +import java.util.List; +import java.util.Locale; + class ProtobufConfluentExtractorTest { private final FileHelper fileHelper = new FileHelper(); - private final Extractor protoBufConfluentExtractor = new ProtoBufConfluentExtractor(); + private final Extractor protoBufConfluentExtractor = new ProtoBufConfluentExtractor(); @BeforeEach public void setUp() { @@ -38,7 +38,7 @@ public void setUp() { @DisplayName("Test Extractor with simple proto file") void testFlatProperties() throws Exception { final String testFile = fileHelper.getContent("/proto-files/easyTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -53,7 +53,7 @@ void testFlatProperties() throws Exception { @DisplayName("Test Extractor with data structure map and array") void testEmbeddedTypes() throws Exception { final String testFile = fileHelper.getContent("/proto-files/embeddedTypeTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(2) @@ -68,7 +68,7 @@ void testEmbeddedTypes() throws Exception { @DisplayName("Test Extractor with data structure enums and collections") void testEnumType() throws Exception { final String testFile = fileHelper.getContent("/proto-files/enumTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -86,7 +86,7 @@ void testEnumType() throws Exception { @DisplayName("Test Extractor with data structure Any of") void testOneOfsType() throws Exception { final String testFile = fileHelper.getContent("/proto-files/oneOfTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(4) @@ -106,7 +106,7 @@ void testOneOfsType() throws Exception { @DisplayName("Test Extractor with complex structure") void testComplexProto() throws Exception { final String testFile = fileHelper.getContent("/proto-files/complexTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(13) @@ -131,7 +131,7 @@ void testComplexProto() throws Exception { @DisplayName("Test Extractor with real proto") void testProvided() throws Exception { final String testFile = fileHelper.getContent("/proto-files/providedTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(32) @@ -175,7 +175,7 @@ void testProvided() throws Exception { @DisplayName("Test Extractor with data structure maps") void testMap() throws Exception { final String testFile = fileHelper.getContent("/proto-files/mapTest.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(7) @@ -194,7 +194,7 @@ void testMap() throws Exception { @DisplayName("Test Extractor with multi types") void completeTest() throws Exception { final String testFile = fileHelper.getContent("/proto-files/completeProto.proto"); - final ProtobufSchema schema = new ProtobufSchema(testFile); + final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(11) diff --git a/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java index 9608c3d2..d209a484 100644 --- a/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java @@ -6,28 +6,15 @@ package com.sngular.kloadgen.processor; -import java.io.File; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.fixture.AvroSchemaFixturesConstants; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.SchemaParseUtil; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.avro.LogicalTypes; import org.apache.avro.Schema; import org.apache.avro.SchemaBuilder; @@ -46,6 +33,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + class AvroSchemaProcessorTest { private final FileHelper fileHelper = new FileHelper(); @@ -81,7 +76,7 @@ void testAvroSchemaProcessorWithSubEntitySimpleArray() throws IOException { FieldValueMapping.builder().fieldName("topLevelIntArray[3]").fieldType("int-array").valueLength(0).fieldValueList("[2]").required(true).isAncestorRequired(true).build()); final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); final SchemaProcessor avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final GenericRecord entity = setUpEntityForAvroTestWithSubEntitySimpleArray(parsedSchema); @@ -131,7 +126,7 @@ void testAvroSchemaProcessorWithSubEntityArray() throws IOException { .build()); final var testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final var parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final var parsedSchema = new ParsedSchema(testFile, "AVRO"); final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var entity = setUpEntityForAvroTestWithSubEntityArray(parsedSchema); @@ -175,7 +170,7 @@ void testEmbeddedAvroSchemaProcessor() throws IOException { FieldValueMapping.builder().fieldName("timestamp").fieldType("long").valueLength(0).fieldValueList("5").required(true).isAncestorRequired(true).build() ); final var testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); - final var parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final var parsedSchema = new ParsedSchema(testFile, "AVRO"); final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var message = (EnrichedRecord) avroSchemaProcessor.next(); @@ -553,7 +548,7 @@ void testEnumProcessor() throws IOException { .build() ); final File testFile = fileHelper.getFile("/avro-files/optionalEnum.avsc"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); final SchemaProcessor avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final EnrichedRecord message = (EnrichedRecord) avroSchemaProcessor.next(); diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index 04c236fa..80f7f6c6 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -1,10 +1,5 @@ package com.sngular.kloadgen.processor; -import java.io.File; -import java.util.List; -import java.util.Locale; -import java.util.stream.Stream; - import com.fasterxml.jackson.databind.node.ObjectNode; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; @@ -23,6 +18,11 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; + public class JsonSchemaProcessorTest { private static Stream parametersForTestNullOnOptionalField() { @@ -33,7 +33,7 @@ private static Stream parametersForTestBasicStructure() { return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_REQUIRED_EXPECTED)); } - private static Stream parametersForTestOptionalFieldNonEmpty(){ + private static Stream parametersForTestOptionalFieldNonEmpty() { return Stream.of(Arguments.of(JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED_EXPECTED)); } @@ -125,11 +125,11 @@ final void testNestedComplexLevels() { @ParameterizedTest @DisplayName("Should process non-required fields if it is not empty") @MethodSource("parametersForTestOptionalFieldNonEmpty") - final void testOptionalFieldNonEmpty(final List schemaAsJson, final String expected){ + final void testOptionalFieldNonEmpty(final List schemaAsJson, final String expected) { final SchemaProcessor jsonSchemaProcessor = new SchemaProcessor(); - jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON,null,null,schemaAsJson); + jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, schemaAsJson); final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); Assertions.assertThat(message.toString()).isEqualTo(expected); diff --git a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java index 40e1ba83..1b6bdc31 100644 --- a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java @@ -1,26 +1,18 @@ package com.sngular.kloadgen.processor; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Map; - import com.google.protobuf.Descriptors; import com.google.protobuf.DynamicMessage; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.SchemaExtractor; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; import com.sngular.kloadgen.schemaregistry.SchemaRegistryManagerFactory; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.commons.collections.MapUtils; import org.apache.jmeter.threads.JMeterContext; @@ -32,6 +24,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.io.File; +import java.io.IOException; +import java.util.*; + class ProtobufSchemaProcessorTest { private final FileHelper fileHelper = new FileHelper(); @@ -62,7 +58,7 @@ void textEmbeddedTypeTestSchemaProcessor() throws KLoadGenException, IOException FieldValueMapping.builder().fieldName("phones.phoneType").fieldType("enum").fieldValueList("[MOBILE, HOME, WORK]").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -96,7 +92,7 @@ void testProtobufGoogleTypes() throws IOException { FieldValueMapping.builder().fieldName("occurrence_id").fieldType("StringValue").fieldValueList("Isabel").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("load_number").fieldType("Int32Value").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -121,10 +117,10 @@ void testProtobufGoogleTypes() throws IOException { @DisplayName("Be able to process enum in the schema") void testProtoBufEnumSchemaProcessor() throws IOException { final File testFile = fileHelper.getFile("/proto-files/enumTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF")); + final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); fieldValueMappingList.get(0).setFieldValuesList("HOME, WORK"); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -160,9 +156,9 @@ void testProtoBufEnumSchemaProcessor() throws IOException { @DisplayName("Be able to process easy schema") void testProtoBufEasyTestProcessor() throws IOException { final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF")); + final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -191,9 +187,9 @@ void testProtoBufEasyTestProcessor() throws IOException { void testProtoBufOneOfProcessor() throws IOException { final File testFile = fileHelper.getFile("/proto-files/oneOfTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF")); + final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -230,7 +226,7 @@ void testProtoBufMapTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("addressesNoDot[:].number").fieldType("int").fieldValueList("6").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("addressesNoDot[:].zipcode").fieldType("int").fieldValueList("15011").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -295,7 +291,7 @@ void testProtoBufComplexTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("response").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("presents[:].options[]").fieldType("string-array").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -364,7 +360,7 @@ void testProtoBufProvidedComplexTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("report_by_name").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("create_user_id").fieldType("string").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, SchemaParseUtil.getParsedSchema(testFile, + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); @@ -472,7 +468,7 @@ void testFailing() throws IOException { final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -504,7 +500,7 @@ void testProtoBufProvidedWithNotNestedTypeProcessor() throws IOException { FieldValueMapping.builder().fieldName("customer_account.billing_party.address.address_line_two").fieldType("string").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -538,7 +534,7 @@ void testDateTimeTypes() throws IOException { .build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - SchemaParseUtil.getParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final Map map = genericRecord.getAllFields(); diff --git a/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java b/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java index 8edde20b..b8e8fb3c 100644 --- a/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java +++ b/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java @@ -6,18 +6,17 @@ package com.sngular.kloadgen.property.editor; -import java.io.File; -import java.io.IOException; -import java.util.List; - import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.SchemaParseUtil; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.io.File; +import java.io.IOException; +import java.util.List; + class FileSubjectPropertyEditorTest { private final FileHelper fileHelper = new FileHelper(); @@ -28,7 +27,7 @@ class FileSubjectPropertyEditorTest { @DisplayName("File Subject Property Editor extract AVRO") void extractEmbeddedAvroTest() throws IOException { final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); - final ParsedSchema schema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final ParsedSchema schema = new ParsedSchema(testFile, "AVRO"); final List fieldValueMappingList = editor.getAttributeList(schema); Assertions.assertThat(fieldValueMappingList) diff --git a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java index 98f21e39..69662413 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java @@ -6,22 +6,14 @@ package com.sngular.kloadgen.sampler; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Locale; -import java.util.Properties; -import java.util.stream.Stream; - import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; import com.sngular.kloadgen.serializer.SerializerTestFixture; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.ProducerKeysHelper; import com.sngular.kloadgen.util.PropsKeysHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -31,6 +23,13 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Locale; +import java.util.Properties; +import java.util.stream.Stream; + class SamplerUtilTest { private final FileHelper fileHelper = new FileHelper(); @@ -67,14 +66,14 @@ void configureValueGeneratorTest(final String jmeterProps) throws IOException { public JMeterVariables getVariablesAvro() throws IOException { final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "avro"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "test"); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "test"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.rawSchema())); variables.put(PropsKeysHelper.VALUE_SCHEMA_TYPE, "avro"); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.rawSchema())); variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( FieldValueMapping.builder().fieldName("subEntity.anotherLevel.subEntityIntArray[2]").fieldType("int-array").valueLength(0).fieldValueList("[1]").required(true) .isAncestorRequired(true).build(), @@ -109,14 +108,14 @@ void configureKeyGeneratorTest(final String jmeterProps) throws IOException { public JMeterVariables getVariablesJsonSchema() throws IOException { final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "JSON"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.rawSchema())); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.rawSchema())); variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA); variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); return variables; @@ -125,13 +124,13 @@ public JMeterVariables getVariablesJsonSchema() throws IOException { public JMeterVariables getVariablesProtobuf() throws IOException { final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "PROTOBUF"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "PROTOBUF"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "protobuf"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "protobufSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.schema())); variables.put(PropsKeysHelper.VALUE_SCHEMA_TYPE, "protobuf"); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.schema())); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "protobufSubject"); variables.putObject(PropsKeysHelper.KEY_SCHEMA_PROPERTIES, Arrays.asList( SerializerTestFixture.createFieldValueMapping("street", "string"), diff --git a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java index 4fbf94b8..136c2e91 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java @@ -1,21 +1,12 @@ package com.sngular.kloadgen.serializer; -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - -import javax.xml.bind.DatatypeConverter; - import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; -import com.sngular.kloadgen.testutil.SchemaParseUtil; import com.sngular.kloadgen.util.PropsKeysHelper; -import io.confluent.kafka.schemaregistry.ParsedSchema; import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -24,6 +15,13 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import javax.xml.bind.DatatypeConverter; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + @Slf4j class AvroDeserializerTest { @@ -81,7 +79,7 @@ void deserialize(final File schemaFile, final List fieldValue avroDeserializer.configure(Map.of(PropsKeysHelper.VALUE_SCHEMA, schemaStr), false); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(schemaFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "AVRO"); AVRO_SCHEMA_PROCESSOR.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = AVRO_SCHEMA_PROCESSOR.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java b/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java index 4aa2fee8..7d2ab8e8 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java @@ -1,17 +1,11 @@ package com.sngular.kloadgen.serializer; -import java.io.File; -import java.util.List; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; -import com.sngular.kloadgen.testutil.SchemaParseUtil; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.apache.avro.generic.GenericRecord; import org.apache.kafka.common.serialization.Serializer; import org.assertj.core.api.Assertions; @@ -20,6 +14,11 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.io.File; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + public class GenericRecordAvroSerializersTest { private static final SchemaProcessor AVRO_SCHEMA_PROCESSOR = new SchemaProcessor(); @@ -73,7 +72,7 @@ void genericAvroRecordSerializerTest(final Serializer serializer, ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, schemaStr))); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(schemaFile, "AVRO"); + final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "AVRO"); AVRO_SCHEMA_PROCESSOR.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = AVRO_SCHEMA_PROCESSOR.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java index 922f6093..e9db77b3 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java @@ -1,24 +1,23 @@ package com.sngular.kloadgen.serializer; -import java.io.File; -import java.util.List; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - import com.fasterxml.jackson.databind.node.ObjectNode; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; -import com.sngular.kloadgen.testutil.SchemaParseUtil; -import io.confluent.kafka.schemaregistry.ParsedSchema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Named; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.io.File; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + public class JsonSerializerTest { private static final SchemaProcessor JSON_SCHEMA_PROCESSOR = new SchemaProcessor(); @@ -63,7 +62,7 @@ final void recordSerializersTestLogicalTypes(final File schemaFile, final List getSchemaToTest() { final Builder builder = Stream.builder(); - final File testCompleteProtoFile = ProtobuffSerializerTestFixture.TEST_COMPLETE_PROTO.getFirst(); - builder.add(Arguments.arguments(Named.of(testCompleteProtoFile.getName(), testCompleteProtoFile), ProtobuffSerializerTestFixture.TEST_COMPLETE_PROTO.getSecond())); - final File testComplexFile = ProtobuffSerializerTestFixture.TEST_COMPLEX.getFirst(); - builder.add(Arguments.arguments(Named.of(testComplexFile.getName(), testComplexFile), ProtobuffSerializerTestFixture.TEST_COMPLEX.getSecond())); - final File testDateTimeFile = ProtobuffSerializerTestFixture.TEST_DATE_TIME.getFirst(); - builder.add(Arguments.arguments(Named.of(testDateTimeFile.getName(), testDateTimeFile), ProtobuffSerializerTestFixture.TEST_DATE_TIME.getSecond())); - final File testDeveFile = ProtobuffSerializerTestFixture.TEST_DEVE.getFirst(); - builder.add(Arguments.arguments(Named.of(testDeveFile.getName(), testDeveFile), ProtobuffSerializerTestFixture.TEST_DEVE.getSecond())); - final File testEasyFile = ProtobuffSerializerTestFixture.TEST_EASY.getFirst(); - builder.add(Arguments.arguments(Named.of(testEasyFile.getName(), testEasyFile), ProtobuffSerializerTestFixture.TEST_EASY.getSecond())); - final File testEmbeddedTypeFile = ProtobuffSerializerTestFixture.TEST_EMBEDDED_TYPE.getFirst(); - builder.add(Arguments.arguments(Named.of(testEmbeddedTypeFile.getName(), testEmbeddedTypeFile), ProtobuffSerializerTestFixture.TEST_EMBEDDED_TYPE.getSecond())); - final File testEnumFile = ProtobuffSerializerTestFixture.TEST_ENUM.getFirst(); - builder.add(Arguments.arguments(Named.of(testEnumFile.getName(), testEnumFile), ProtobuffSerializerTestFixture.TEST_ENUM.getSecond())); - final File testGoogleTypesFile = ProtobuffSerializerTestFixture.TEST_GOOGLE_TYPES.getFirst(); - builder.add(Arguments.arguments(Named.of(testGoogleTypesFile.getName(), testGoogleTypesFile), ProtobuffSerializerTestFixture.TEST_GOOGLE_TYPES.getSecond())); - final File testIssue311File = ProtobuffSerializerTestFixture.TEST_ISSUE_311.getFirst(); - builder.add(Arguments.arguments(Named.of(testIssue311File.getName(), testIssue311File), ProtobuffSerializerTestFixture.TEST_ISSUE_311.getSecond())); - final File testMapFile = ProtobuffSerializerTestFixture.TEST_MAP.getFirst(); - builder.add(Arguments.arguments(Named.of(testMapFile.getName(), testMapFile), ProtobuffSerializerTestFixture.TEST_MAP.getSecond())); - final File testOneOfFile = ProtobuffSerializerTestFixture.TEST_ONE_OF.getFirst(); - builder.add(Arguments.arguments(Named.of(testOneOfFile.getName(), testOneOfFile), ProtobuffSerializerTestFixture.TEST_ONE_OF.getSecond())); - final File testProvidedFile = ProtobuffSerializerTestFixture.TEST_PROVIDED.getFirst(); - builder.add(Arguments.arguments(Named.of(testProvidedFile.getName(), testProvidedFile), ProtobuffSerializerTestFixture.TEST_PROVIDED.getSecond())); + final File testCompleteProtoFile = ProtobufSerializerTestFixture.TEST_COMPLETE_PROTO.getFirst(); + builder.add(Arguments.arguments(Named.of(testCompleteProtoFile.getName(), testCompleteProtoFile), ProtobufSerializerTestFixture.TEST_COMPLETE_PROTO.getSecond())); + final File testComplexFile = ProtobufSerializerTestFixture.TEST_COMPLEX.getFirst(); + builder.add(Arguments.arguments(Named.of(testComplexFile.getName(), testComplexFile), ProtobufSerializerTestFixture.TEST_COMPLEX.getSecond())); + final File testDateTimeFile = ProtobufSerializerTestFixture.TEST_DATE_TIME.getFirst(); + builder.add(Arguments.arguments(Named.of(testDateTimeFile.getName(), testDateTimeFile), ProtobufSerializerTestFixture.TEST_DATE_TIME.getSecond())); + final File testDeveFile = ProtobufSerializerTestFixture.TEST_DEVE.getFirst(); + builder.add(Arguments.arguments(Named.of(testDeveFile.getName(), testDeveFile), ProtobufSerializerTestFixture.TEST_DEVE.getSecond())); + final File testEasyFile = ProtobufSerializerTestFixture.TEST_EASY.getFirst(); + builder.add(Arguments.arguments(Named.of(testEasyFile.getName(), testEasyFile), ProtobufSerializerTestFixture.TEST_EASY.getSecond())); + final File testEmbeddedTypeFile = ProtobufSerializerTestFixture.TEST_EMBEDDED_TYPE.getFirst(); + builder.add(Arguments.arguments(Named.of(testEmbeddedTypeFile.getName(), testEmbeddedTypeFile), ProtobufSerializerTestFixture.TEST_EMBEDDED_TYPE.getSecond())); + final File testEnumFile = ProtobufSerializerTestFixture.TEST_ENUM.getFirst(); + builder.add(Arguments.arguments(Named.of(testEnumFile.getName(), testEnumFile), ProtobufSerializerTestFixture.TEST_ENUM.getSecond())); + final File testGoogleTypesFile = ProtobufSerializerTestFixture.TEST_GOOGLE_TYPES.getFirst(); + builder.add(Arguments.arguments(Named.of(testGoogleTypesFile.getName(), testGoogleTypesFile), ProtobufSerializerTestFixture.TEST_GOOGLE_TYPES.getSecond())); + final File testIssue311File = ProtobufSerializerTestFixture.TEST_ISSUE_311.getFirst(); + builder.add(Arguments.arguments(Named.of(testIssue311File.getName(), testIssue311File), ProtobufSerializerTestFixture.TEST_ISSUE_311.getSecond())); + final File testMapFile = ProtobufSerializerTestFixture.TEST_MAP.getFirst(); + builder.add(Arguments.arguments(Named.of(testMapFile.getName(), testMapFile), ProtobufSerializerTestFixture.TEST_MAP.getSecond())); + final File testOneOfFile = ProtobufSerializerTestFixture.TEST_ONE_OF.getFirst(); + builder.add(Arguments.arguments(Named.of(testOneOfFile.getName(), testOneOfFile), ProtobufSerializerTestFixture.TEST_ONE_OF.getSecond())); + final File testProvidedFile = ProtobufSerializerTestFixture.TEST_PROVIDED.getFirst(); + builder.add(Arguments.arguments(Named.of(testProvidedFile.getName(), testProvidedFile), ProtobufSerializerTestFixture.TEST_PROVIDED.getSecond())); return builder.build(); } @@ -78,12 +77,12 @@ private static Stream getSchemaToTest() { @ParameterizedTest @MethodSource("getSchemaToTest") void serialize(final File schemaFile, final List fieldValueMappings) throws IOException { - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(schemaFile, "Protobuf"); + final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "PROTOBUF"); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); final BaseSchemaMetadata confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, ""))); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema.rawSchema(), confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = protobufSchemaProcessor.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/ProtobuffSerializerTestFixture.java b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java similarity index 99% rename from src/test/java/com/sngular/kloadgen/serializer/ProtobuffSerializerTestFixture.java rename to src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java index 136a8ca7..9cf338d5 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/ProtobuffSerializerTestFixture.java +++ b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java @@ -1,14 +1,14 @@ package com.sngular.kloadgen.serializer; -import java.io.File; -import java.util.Arrays; -import java.util.List; - import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; import org.apache.commons.math3.util.Pair; -public class ProtobuffSerializerTestFixture { +import java.io.File; +import java.util.Arrays; +import java.util.List; + +public class ProtobufSerializerTestFixture { static final Pair> TEST_COMPLETE_PROTO = new Pair<>( new FileHelper().getFile("/proto-files/completeProto.proto"), @@ -227,6 +227,6 @@ public class ProtobuffSerializerTestFixture { SerializerTestFixture.createFieldValueMapping("create_user_id", "string")) ); - protected ProtobuffSerializerTestFixture() { + protected ProtobufSerializerTestFixture() { } } diff --git a/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java b/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java index f0008f7a..7469ba29 100644 --- a/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java +++ b/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java @@ -1,11 +1,8 @@ package com.sngular.kloadgen.testutil; -import java.util.List; +import com.sngular.kloadgen.parsedschema.IParsedSchema; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import io.confluent.kafka.schemaregistry.client.rest.entities.SchemaReference; - -public final class ParsedSchemaUtil implements ParsedSchema { +public final class ParsedSchemaUtil implements IParsedSchema { @Override public String schemaType() { @@ -22,16 +19,6 @@ public String canonicalString() { return null; } - @Override - public List references() { - return null; - } - - @Override - public List isBackwardCompatible(final ParsedSchema parsedSchema) { - return null; - } - @Override public Object rawSchema() { return null; diff --git a/src/test/java/com/sngular/kloadgen/testutil/SchemaParseUtil.java b/src/test/java/com/sngular/kloadgen/testutil/SchemaParseUtil.java deleted file mode 100644 index be52e15c..00000000 --- a/src/test/java/com/sngular/kloadgen/testutil/SchemaParseUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.sngular.kloadgen.testutil; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import com.sngular.kloadgen.common.SchemaTypeEnum; -import com.sngular.kloadgen.exception.KLoadGenException; -import io.confluent.kafka.schemaregistry.ParsedSchema; -import io.confluent.kafka.schemaregistry.avro.AvroSchema; -import io.confluent.kafka.schemaregistry.json.JsonSchema; -import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -import org.apache.commons.lang3.EnumUtils; - -public final class SchemaParseUtil { - - private SchemaParseUtil() { - } - - public static ParsedSchema getParsedSchema(final File schema, final String type) throws IOException { - return getParsedSchema(new String(Files.readAllBytes(schema.toPath())), type); - } - - public static ParsedSchema getParsedSchema(final String schema, final String type) { - final SchemaTypeEnum schemaType = EnumUtils.isValidEnum(SchemaTypeEnum.class, type.toUpperCase()) - ? SchemaTypeEnum.valueOf(type.toUpperCase()) : null; - final ParsedSchema schemaParsed; - try { - assert schemaType != null; - schemaParsed = switch (schemaType) { - case JSON -> new JsonSchema(schema); - case AVRO -> new AvroSchema(schema); - case PROTOBUF -> new ProtobufSchema(schema); - }; - } catch (final KLoadGenException e) { - final String logMsg = "Please, make sure that the schema sources fed are correct"; - throw new KLoadGenException("Error obtaining object creator factory. " + logMsg); - } - return schemaParsed; - } - -} diff --git a/src/test/resources/avro-files/testCastIssue.avsc b/src/test/resources/avro-files/testCastIssue.avsc new file mode 100644 index 00000000..eb7e000a --- /dev/null +++ b/src/test/resources/avro-files/testCastIssue.avsc @@ -0,0 +1,28 @@ +{ +"type":"record", +"name":"TopicName", +"fields": [ + {"name":"messageId", + "type":"string" + }, + {"name":"messageTime", + "type":"long" + }, + {"name":"data", + "type":{ + "type":"array", + "items":{ + "type":"record", + "name":"DataItems", + "fields": [{ + "name":"numericFieldValueList", + "type":"int" + }, + { + "name":"stringFieldValueList", + "type":"string" + } + ] + } + }}] +} \ No newline at end of file From 6226e34ae02cf09b16fce26ca048ba4f2c2390d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GracielaM=C3=A9ndezOlmos?= Date: Mon, 27 Nov 2023 09:46:26 +0100 Subject: [PATCH 47/55] "Fix AsyncApiSamplerTest issues" --- .../sngular/kloadgen/sampler/AsyncApiSamplerTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index 59c89c88..f121daf1 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -1,7 +1,11 @@ package com.sngular.kloadgen.sampler; import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; import com.sngular.kloadgen.testutil.FileHelper; +import com.sngular.kloadgen.util.ProducerKeysHelper; +import com.sngular.kloadgen.util.PropsKeysHelper; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -52,11 +56,11 @@ void testAsyncApiSampleBasic() throws IOException { }*/ -/* + public JMeterVariables getVariablesJsonSchema() throws IOException { final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final ParsedSchema parsedSchema = SchemaParseUtil.getParsedSchema(testFile, "JSON"); + final ParsedSchema parsedSchema = new ParsedSchema(testFile, "JSON"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); @@ -67,7 +71,7 @@ public JMeterVariables getVariablesJsonSchema() throws IOException { variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED); variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); return variables; - }*/ + } From f1bf5ec2a87d4b7241509fa9e1d0ad93e7c9d60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GracielaM=C3=A9ndezOlmos?= Date: Mon, 27 Nov 2023 12:54:42 +0100 Subject: [PATCH 48/55] "Fix Codacy and Extractor issues" --- .../KafkaHeadersConfigElement.java | 2 +- ...ueFileSerializedConfigElementBeanInfo.java | 12 ++++--- .../kloadgen/extractor/SchemaExtractor.java | 16 ++++----- .../extractors/ExtractorFactory.java | 10 +++--- .../extractors/ExtractorRegistry.java | 6 ++-- .../avro/AvroConfluentExtractor.java | 4 +-- .../extractors/avro/AvroExtractor.java | 10 +++--- .../extractors/json/JsonDefaultExtractor.java | 10 +++--- .../extractors/json/JsonExtractor.java | 7 ++-- .../protobuf/AbstractProtoFileExtractor.java | 26 ++++++++++---- .../protobuf/ProtoBufApicurioExtractor.java | 4 +-- .../protobuf/ProtoBufConfluentExtractor.java | 4 +-- .../protobuf/ProtobufExtractor.java | 10 +++--- .../loadgen/impl/ProtobufLoadGenerator.java | 10 +++--- .../kloadgen/parsedschema/ParsedSchema.java | 8 ++--- .../impl/AvroObjectCreatorFactory.java | 22 +++++++++--- .../impl/ProtobufObjectCreatorFactory.java | 16 ++++++--- .../editor/FileSubjectPropertyEditor.java | 33 +++++++++-------- .../randomtool/random/RandomObject.java | 15 +++++--- .../sampler/KafkaProducerSampler.java | 17 +++++---- .../sngular/kloadgen/sampler/SamplerUtil.java | 16 ++++++--- .../sampler/gui/ApiSchemaRenderer.java | 5 +-- .../sampler/gui/AsyncApiSamplerGui.java | 36 +++++++++++++------ .../impl/ConfluentSchemaRegistry.java | 19 ++++++---- .../serializer/ProtobufSerializer.java | 4 +-- .../extractor/SchemaExtractorTest.java | 12 +++---- .../extractors/ExtractorFactoryTest.java | 23 +++++++----- 27 files changed, 219 insertions(+), 138 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java b/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java index 5878bd68..5698d1dc 100644 --- a/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java +++ b/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java @@ -32,7 +32,7 @@ public class KafkaHeadersConfigElement extends ConfigTestElement implements Test private List kafkaHeaders; @Override - public final void iterationStart(final LoopIterationEvent iterEvent) { + public final void iterationStart(final LoopIterationEvent iteEvent) { final JMeterContext context = getThreadContext(); diff --git a/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java index dc82d504..325c34d4 100644 --- a/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java +++ b/src/main/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementBeanInfo.java @@ -6,15 +6,19 @@ package com.sngular.kloadgen.config.valuefileserialized; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; + import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.property.editor.*; +import com.sngular.kloadgen.property.editor.FileSubjectPropertyEditor; +import com.sngular.kloadgen.property.editor.NameStrategyPropertyEditor; +import com.sngular.kloadgen.property.editor.SchemaConverterPropertyEditor; +import com.sngular.kloadgen.property.editor.SchemaTypePropertyEditor; +import com.sngular.kloadgen.property.editor.ValueSerializerPropertyEditor; import org.apache.jmeter.testbeans.BeanInfoSupport; import org.apache.jmeter.testbeans.gui.TableEditor; import org.apache.jmeter.testbeans.gui.TypeEditor; -import java.beans.PropertyDescriptor; -import java.util.ArrayList; - public class ValueFileSerializedConfigElementBeanInfo extends BeanInfoSupport { private static final String VALUE_SUBJECT_NAME = "valueSubjectName"; diff --git a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java index e8161d69..034e5e89 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java @@ -1,12 +1,5 @@ package com.sngular.kloadgen.extractor; -import com.sngular.kloadgen.common.SchemaRegistryEnum; -import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import lombok.Getter; -import org.apache.commons.lang3.tuple.Pair; - import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -14,6 +7,13 @@ import java.util.List; import java.util.stream.Stream; +import com.sngular.kloadgen.common.SchemaRegistryEnum; +import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.ParsedSchema; +import lombok.Getter; +import org.apache.commons.lang3.tuple.Pair; + @Getter public final class SchemaExtractor { @@ -31,7 +31,7 @@ public static Pair> flatPropertiesList(final Str } public static List flatPropertiesList(final ParsedSchema parserSchema) { - return ExtractorFactory.getExtractor(parserSchema.schemaType()).processSchema(parserSchema.rawSchema(), SchemaRegistryEnum.CONFLUENT); + return ExtractorFactory.getExtractor(parserSchema.schemaType()).processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT); } public static String readSchemaFile(final String filePath) throws IOException { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index aa0c87e6..62b50dc3 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -1,5 +1,10 @@ package com.sngular.kloadgen.extractor.extractors; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; @@ -16,11 +21,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.threads.JMeterContextService; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Properties; - public final class ExtractorFactory { private static AvroExtractor avroExtractor = new AvroExtractor(); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java index 07768734..21b6f72c 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java @@ -1,15 +1,15 @@ package com.sngular.kloadgen.extractor.extractors; +import java.util.List; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; -import java.util.List; - public interface ExtractorRegistry { List processSchema(final T schema, SchemaRegistryEnum registry); - T processSchema(final String fileContent); + ParsedSchema processSchema(final String fileContent); List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java index e4cf9089..fd1b3e1d 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractor.java @@ -1,11 +1,11 @@ package com.sngular.kloadgen.extractor.extractors.avro; +import java.util.List; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import org.apache.avro.Schema; -import java.util.List; - public class AvroConfluentExtractor extends AbstractAvroFileExtractor implements Extractor { public final List processSchema(final Schema schema) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index 2dd462a2..073202a1 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -1,21 +1,21 @@ package com.sngular.kloadgen.extractor.extractors.avro; +import java.util.List; +import java.util.Map; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; -import java.util.List; -import java.util.Map; - -public class AvroExtractor implements ExtractorRegistry { +public class AvroExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, new AvroApicurioExtractor()); public final List processSchema(final T schema, final SchemaRegistryEnum registryEnum) { - return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema); + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema.rawSchema()); } public final ParsedSchema processSchema(final String fileContent) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java index 3225025f..4d0d9bfc 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultExtractor.java @@ -1,16 +1,16 @@ package com.sngular.kloadgen.extractor.extractors.json; -import com.sngular.kloadgen.extractor.extractors.Extractor; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.model.json.Field; -import com.sngular.kloadgen.model.json.Schema; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import com.sngular.kloadgen.extractor.extractors.Extractor; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.json.Field; +import com.sngular.kloadgen.model.json.Schema; + public class JsonDefaultExtractor extends AbstractJsonExtractor implements Extractor { @Override diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java index f8aaf4b9..88ef7776 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java @@ -1,14 +1,14 @@ package com.sngular.kloadgen.extractor.extractors.json; +import java.util.List; +import java.util.Map; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; -import java.util.List; -import java.util.Map; - public class JsonExtractor implements ExtractorRegistry { @@ -19,6 +19,7 @@ public final List processSchema(final T schemaReceived, final return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.rawSchema().toString()); } + public final ParsedSchema processSchema(final String fileContent) { return new ParsedSchema(fileContent, "JSON"); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java index ea2f71b7..cde204b7 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/AbstractProtoFileExtractor.java @@ -1,22 +1,34 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import com.github.os72.protobuf.dynamic.DynamicSchema; import com.google.protobuf.Descriptors; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.util.ProtobufHelper; import com.squareup.wire.schema.Field; -import com.squareup.wire.schema.internal.parser.*; +import com.squareup.wire.schema.internal.parser.EnumConstantElement; +import com.squareup.wire.schema.internal.parser.EnumElement; +import com.squareup.wire.schema.internal.parser.FieldElement; +import com.squareup.wire.schema.internal.parser.MessageElement; +import com.squareup.wire.schema.internal.parser.OneOfElement; +import com.squareup.wire.schema.internal.parser.ProtoFileElement; +import com.squareup.wire.schema.internal.parser.TypeElement; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public abstract class AbstractProtoFileExtractor { public static final String ARRAY_POSTFIX = "-array"; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java index 8170c571..eac42a6a 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufApicurioExtractor.java @@ -1,11 +1,11 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.util.List; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.squareup.wire.schema.internal.parser.ProtoFileElement; -import java.util.List; - public class ProtoBufApicurioExtractor extends AbstractProtoFileExtractor implements Extractor { public final List processSchema(final ProtoFileElement schemaReceived) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java index 7dca1ad1..62f3b73c 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java @@ -1,13 +1,13 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.util.List; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.squareup.wire.schema.internal.parser.ProtoFileElement; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -import java.util.List; - public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor { public final List processSchema(final ParsedSchema schemaReceived) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java index b4d3a91f..9ad3f29a 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java @@ -1,15 +1,15 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - public class ProtobufExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new ProtoBufConfluentExtractor(), @@ -19,7 +19,7 @@ public final List processSchema(final T schemaReceived, final return new ArrayList(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived)); } - public final T processSchema(final String fileContent) { + public final ParsedSchema processSchema(final String fileContent) { return (T) new ParsedSchema(fileContent, "PROTOBUF"); } diff --git a/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java index 931c15e6..87774e6b 100644 --- a/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java +++ b/src/main/java/com/sngular/kloadgen/loadgen/impl/ProtobufLoadGenerator.java @@ -1,5 +1,10 @@ package com.sngular.kloadgen.loadgen.impl; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; @@ -13,11 +18,6 @@ import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; import lombok.extern.slf4j.Slf4j; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; - @Slf4j public class ProtobufLoadGenerator implements SRLoadGenerator, BaseLoadGenerator { diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java index bc33fece..43aec860 100644 --- a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java +++ b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java @@ -1,5 +1,9 @@ package com.sngular.kloadgen.parsedschema; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + import com.sngular.kloadgen.exception.KLoadGenException; import com.squareup.wire.schema.internal.parser.ProtoFileElement; import io.confluent.kafka.schemaregistry.avro.AvroSchema; @@ -7,10 +11,6 @@ import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; import org.apache.avro.Schema; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - public class ParsedSchema implements IParsedSchema { private final T schema; diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java index 992f4c52..d48782d4 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java @@ -1,5 +1,17 @@ package com.sngular.kloadgen.processor.objectcreatorfactory.impl; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.ConstraintTypeEnum; import com.sngular.kloadgen.parsedschema.ParsedSchema; @@ -7,7 +19,11 @@ import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory; import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.randomtool.generator.AvroGeneratorTool; -import com.sngular.kloadgen.schemaregistry.adapter.impl.*; +import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; +import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; +import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import com.sngular.kloadgen.serializer.EnrichedRecord; import org.apache.avro.Schema; import org.apache.avro.Schema.Type; @@ -15,10 +31,6 @@ import org.apache.avro.generic.GenericRecord; import org.apache.commons.collections4.IteratorUtils; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - public final class AvroObjectCreatorFactory implements ObjectCreatorFactory { private static final AvroGeneratorTool AVRO_GENERATOR_TOOL = new AvroGeneratorTool(); diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java index f52c7e41..9420c220 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java @@ -1,5 +1,16 @@ package com.sngular.kloadgen.processor.objectcreatorfactory.impl; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + import com.google.protobuf.Descriptors; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.DescriptorValidationException; @@ -22,11 +33,6 @@ import com.squareup.wire.schema.internal.parser.ProtoFileElement; import org.apache.commons.lang3.StringUtils; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - public class ProtobufObjectCreatorFactory implements ObjectCreatorFactory { private static final ProtoBufGeneratorTool PROTOBUF_GENERATOR_TOOL = new ProtoBufGeneratorTool(); diff --git a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java index 0655c43e..ef2abee6 100644 --- a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java +++ b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java @@ -6,6 +6,19 @@ package com.sngular.kloadgen.property.editor; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.beans.PropertyDescriptor; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorSupport; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.extractor.SchemaExtractor; @@ -14,6 +27,12 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.util.PropsKeysHelper; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.filechooser.FileSystemView; import lombok.extern.slf4j.Slf4j; import org.apache.avro.AvroRuntimeException; import org.apache.jmeter.gui.ClearGui; @@ -24,20 +43,6 @@ import org.apache.jmeter.testbeans.gui.TestBeanPropertyEditor; import org.apache.jmeter.util.JMeterUtils; -import javax.swing.*; -import javax.swing.filechooser.FileSystemView; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.beans.PropertyDescriptor; -import java.beans.PropertyEditor; -import java.beans.PropertyEditorSupport; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - @Slf4j public class FileSubjectPropertyEditor extends PropertyEditorSupport implements TestBeanPropertyEditor, ClearGui { diff --git a/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java b/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java index 0a959b62..aa5dfd5d 100644 --- a/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java +++ b/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java @@ -85,7 +85,8 @@ public Object generateRandom( break; case ValidTypeConstants.BYTES: try { - value = getIntegerValueOrRandom(valueLength, Collections.emptyList(), Collections.emptyMap()).byteValueExact(); + value = getIntegerValueOrRandom(valueLength, Collections.emptyList(), Collections.emptyMap()) + .byteValueExact(); } catch (final ArithmeticException exception) { value = Byte.MAX_VALUE; } @@ -149,7 +150,8 @@ public Object generateRandom( return value; } - private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List fieldValueList, final Map constraints) { + private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List fieldValueList, + final Map constraints) { final BigInteger value; if (!fieldValueList.isEmpty()) { @@ -176,7 +178,8 @@ private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List return value; } - private BigDecimal getDecimalValueOrRandom(final Integer valueLength, final List fieldValueList, final Map constraints) { + private BigDecimal getDecimalValueOrRandom(final Integer valueLength, final List fieldValueList, + final Map constraints) { final BigDecimal value; if (!fieldValueList.isEmpty()) { @@ -421,8 +424,10 @@ private static LocalTime getTimeMicrosValueOrRandom(final List fieldValu private static LocalDateTime getRandomLocalDateTime(final List fieldValueList) { final LocalDateTime value; - final long minDay = LocalDateTime.of(1900, 1, 1, 0, 0).toEpochSecond(ZoneOffset.UTC); - final long maxDay = LocalDateTime.of(2100, 1, 1, 0, 0).toEpochSecond(ZoneOffset.UTC); + final long minDay = LocalDateTime.of(1900, 1, 1, 0, 0) + .toEpochSecond(ZoneOffset.UTC); + final long maxDay = LocalDateTime.of(2100, 1, 1, 0, 0) + .toEpochSecond(ZoneOffset.UTC); final long randomSeconds = minDay + RandomUtils.nextLong(0, maxDay - minDay); if (fieldValueList.isEmpty()) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java index 0bfc683b..e005b386 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java @@ -6,6 +6,17 @@ package com.sngular.kloadgen.sampler; +import java.io.Serial; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ExecutionException; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.model.HeaderMapping; @@ -32,12 +43,6 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.serialization.StringSerializer; -import java.io.Serial; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.ExecutionException; - public final class KafkaProducerSampler extends AbstractJavaSamplerClient implements Serializable { private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s"; diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index 055b3498..b3d573ba 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -6,6 +6,18 @@ package com.sngular.kloadgen.sampler; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.loadgen.BaseLoadGenerator; import com.sngular.kloadgen.loadgen.impl.AvroSRLoadGenerator; @@ -37,10 +49,6 @@ import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.common.security.auth.SecurityProtocol; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.*; - public final class SamplerUtil { private static final StatelessGeneratorTool STATELESS_GENERATOR_TOOL = new StatelessGeneratorTool(); diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java index f6a97d6d..a00d582f 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java @@ -4,13 +4,10 @@ import java.awt.Component; import java.util.Objects; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import javax.swing.JLabel; import javax.swing.JList; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; - - - public class ApiSchemaRenderer extends JLabel implements javax.swing.ListCellRenderer { protected ApiSchemaRenderer() { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index 0daae73d..b12fb4d2 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -12,6 +12,18 @@ package com.sngular.kloadgen.sampler.gui; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Vector; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.ApiExtractor; import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; @@ -24,6 +36,20 @@ import com.sngular.kloadgen.sampler.AsyncApiSampler; import com.sngular.kloadgen.sampler.SamplerUtil; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.config.Argument; @@ -34,16 +60,6 @@ import org.apache.jorphan.gui.JLabeledTextField; import org.apache.kafka.clients.producer.ProducerConfig; -import javax.swing.*; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileSystemView; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.List; -import java.util.*; - @SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") public final class AsyncApiSamplerGui extends AbstractSamplerGui { diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java index 8b98d8f4..f0987b2c 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java @@ -1,9 +1,20 @@ package com.sngular.kloadgen.schemaregistry.impl; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.*; +import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; +import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; +import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import io.confluent.kafka.schemaregistry.avro.AvroSchemaProvider; import io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient; import io.confluent.kafka.schemaregistry.client.SchemaRegistryClient; @@ -14,12 +25,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.jmeter.threads.JMeterContextService; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - @Slf4j public final class ConfluentSchemaRegistry implements SchemaRegistryAdapter { diff --git a/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java b/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java index 18a264cd..b62bf8cd 100644 --- a/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java +++ b/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java @@ -11,17 +11,17 @@ import java.nio.ByteBuffer; import java.util.Arrays; -import javax.xml.bind.DatatypeConverter; - import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.DynamicMessage; import io.confluent.kafka.schemaregistry.protobuf.MessageIndexes; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; +import javax.xml.bind.DatatypeConverter; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.serialization.Serializer; + @Slf4j public class ProtobufSerializer implements Serializer { diff --git a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java index f244472b..d5f7a303 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java @@ -6,6 +6,11 @@ package com.sngular.kloadgen.extractor; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.Properties; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.parsedschema.ParsedSchema; @@ -31,11 +36,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.File; -import java.io.IOException; -import java.util.Locale; -import java.util.Properties; - @ExtendWith(MockitoExtension.class) class SchemaExtractorTest { @@ -146,7 +146,7 @@ void testSchemaTypeIsCorrectWhenAvroConfluent() throws IOException { properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentAbstractParsedSchemaMetadata.parse(parsedSchema)); + final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java index 9bc20133..8431b4bb 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java @@ -1,5 +1,11 @@ package com.sngular.kloadgen.extractor.extractors; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Properties; + import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.SchemaExtractor; import com.sngular.kloadgen.extractor.extractors.avro.AvroConfluentExtractor; @@ -9,7 +15,7 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentAbstractParsedSchemaMetadata; +import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.JMeterHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; @@ -22,13 +28,12 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.*; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Locale; -import java.util.Properties; +import org.mockito.Answers; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Captor; +import org.mockito.MockedStatic; +import org.mockito.Mockito; @SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") @@ -75,7 +80,7 @@ void flatPropertiesList() throws IOException { properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentAbstractParsedSchemaMetadata.parse(parsedSchema)); + final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); From 3754b7c0b7f6eef74ed1487a724c2153b657eb82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 27 Nov 2023 20:07:47 +0100 Subject: [PATCH 49/55] #384 Refactor Extractor. Fix some Codacy issues --- .../kloadgen/extractor/SchemaExtractor.java | 4 +- .../extractors/ExtractorFactory.java | 21 +- .../extractors/ExtractorRegistry.java | 9 +- .../extractors/avro/AvroExtractor.java | 14 +- .../extractors/json/JsonExtractor.java | 14 +- .../protobuf/ProtoBufConfluentExtractor.java | 8 +- .../protobuf/ProtobufExtractor.java | 14 +- .../parsedschema/AbstractParsedSchema.java | 27 ++ .../parsedschema/AvroParsedSchema.java | 15 + .../kloadgen/parsedschema/IParsedSchema.java | 13 - .../parsedschema/JsonParsedSchema.java | 13 + .../kloadgen/parsedschema/ParsedSchema.java | 150 --------- .../parsedschema/ProtobufParsedSchema.java | 15 + .../impl/AvroObjectCreatorFactory.java | 17 +- .../impl/ProtobufObjectCreatorFactory.java | 13 +- .../processor/util/SchemaProcessorUtils.java | 8 +- .../editor/FileSubjectPropertyEditor.java | 22 +- .../kloadgen/sampler/AsyncApiSampler.java | 112 +++---- .../sampler/KafkaProducerSampler.java | 25 +- .../sngular/kloadgen/sampler/SamplerUtil.java | 130 ++++---- .../sampler/gui/ApiSchemaRenderer.java | 3 +- .../sampler/gui/AsyncApiSamplerGui.java | 182 +++++------ .../schemaregistry/SchemaRegistryAdapter.java | 8 +- .../impl/AbstractParsedSchemaAdapter.java | 8 - .../impl/ApicurioParsedSchemaMetadata.java | 28 -- .../adapter/impl/BaseParsedSchema.java | 16 - .../impl/ConfluentParsedSchemaMetadata.java | 59 ---- .../impl/ApicurioSchemaRegistry.java | 66 ++-- .../impl/ConfluentSchemaRegistry.java | 39 ++- .../sngular/kloadgen/util/JMeterHelper.java | 4 +- ...KafkaHeadersConfigElementBeanInfoTest.java | 3 + ...eySerializedConfigElementBeanInfoTest.java | 2 + .../KeySerializedConfigElementTest.java | 2 +- .../keysimple/KeySimpleConfigElementTest.java | 6 +- .../ValueFileSerializedConfigElementTest.java | 2 +- .../ValueSerializedConfigElementTest.java | 2 +- .../ValueSimpleConfigElementTest.java | 3 +- .../kloadgen/extractor/FakeParsedSchema.java | 15 + .../extractor/SchemaExtractorTest.java | 42 ++- .../asyncapi/AsyncApiExtractorImplTest.java | 10 +- .../extractors/ExtractorFactoryTest.java | 21 +- .../avro/AvroApicurioExtractorTest.java | 4 +- .../avro/AvroConfluentExtractorTest.java | 7 +- .../extractors/json/JsonDefaultTest.java | 2 - .../ProtobufApicurioExtractorTest.java | 10 +- .../ProtobufConfluentExtractorTest.java | 33 +- .../loadgen/impl/AvroSRLoadGeneratorTest.java | 11 +- .../impl/ProtobufSRLoadGeneratorTest.java | 3 - .../kloadgen/model/FieldValueMappingTest.java | 50 ++- .../kloadgen/model/HeaderMappingTest.java | 8 +- .../kloadgen/model/PropertyMappingTest.java | 9 +- .../processor/AvroSchemaProcessorTest.java | 295 +++++++++--------- .../processor/JsonSchemaProcessorTest.java | 18 +- .../ProtobufSchemaProcessorTest.java | 93 +++--- .../fixture/JsonSchemaFixturesConstants.java | 109 +++---- .../editor/FileSubjectPropertyEditorTest.java | 13 +- .../SerialisedSubjectPropertyEditorTest.java | 2 +- .../generator/AvroGeneratorToolTest.java | 240 +++++++------- .../randomtool/random/RandomIteratorTest.java | 33 +- .../randomtool/random/RandomMapTest.java | 6 +- .../kloadgen/sampler/AsyncApiSamplerTest.java | 91 +++--- .../kloadgen/sampler/SamplerUtilTest.java | 36 +-- .../serializer/AvroDeserializerTest.java | 38 +-- .../AvroSerializersTestFixture.java | 7 +- .../GenericRecordAvroSerializersTest.java | 17 +- .../serializer/JsonSerializerTest.java | 18 +- .../serializer/JsonSerializerTestFixture.java | 3 +- .../serializer/ProtobufSerializerTest.java | 53 ++-- .../ProtobufSerializerTestFixture.java | 8 +- .../sngular/kloadgen/testutil/FileHelper.java | 6 + .../kloadgen/testutil/ParsedSchemaUtil.java | 27 -- 71 files changed, 1111 insertions(+), 1304 deletions(-) create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java delete mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java delete mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java create mode 100644 src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java delete mode 100644 src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/AbstractParsedSchemaAdapter.java delete mode 100644 src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java delete mode 100644 src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/BaseParsedSchema.java delete mode 100644 src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java create mode 100644 src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java delete mode 100644 src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java diff --git a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java index 034e5e89..ac884640 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java @@ -10,7 +10,7 @@ import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; import lombok.Getter; import org.apache.commons.lang3.tuple.Pair; @@ -30,7 +30,7 @@ public static Pair> flatPropertiesList(final Str return ExtractorFactory.flatPropertiesList(subjectName); } - public static List flatPropertiesList(final ParsedSchema parserSchema) { + public static List flatPropertiesList(final AbstractParsedSchema parserSchema) { return ExtractorFactory.getExtractor(parserSchema.schemaType()).processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index 62b50dc3..4cb47419 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Properties; import com.sngular.kloadgen.common.SchemaRegistryEnum; @@ -12,12 +11,10 @@ import com.sngular.kloadgen.extractor.extractors.json.JsonExtractor; import com.sngular.kloadgen.extractor.extractors.protobuf.ProtobufExtractor; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; import com.sngular.kloadgen.util.JMeterHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.threads.JMeterContextService; @@ -37,14 +34,13 @@ public static void configExtractorFactory(final AvroExtractor avroExtractor, fin ExtractorFactory.protobufExtractor = protobufExtractor; } - public static ExtractorRegistry getExtractor(final String schemaType) { + public static ExtractorRegistry getExtractor(final String schemaType) { if (schemaType != null && EnumUtils.isValidEnum(SchemaTypeEnum.class, schemaType.toUpperCase())) { return switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) { case JSON -> jsonExtractor; case AVRO -> avroExtractor; case PROTOBUF -> protobufExtractor; - default -> throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); }; } else { throw new KLoadGenException(String.format("Schema type not supported %s", schemaType)); @@ -55,20 +51,13 @@ public static Pair> flatPropertiesList(final Str final Properties properties = JMeterContextService.getContext().getProperties(); final var schemaParsed = JMeterHelper.getParsedSchema(subjectName, properties); final String registryName = properties.getProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); - final AbstractParsedSchemaAdapter parsedSchemaAdapter = schemaParsed.getParsedSchemaAdapter(); - final String schemaType = parsedSchemaAdapter.getType(); + final String schemaType = schemaParsed.getSchemaType(); final List attributeList = new ArrayList<>(); final SchemaRegistryEnum schemaRegistryEnum = SchemaRegistryEnum.valueOf(registryName.toUpperCase()); - final Object schema; - if (Objects.nonNull(registryName)) { - //TODO change parser - schema = switch (schemaRegistryEnum) { - case APICURIO -> ((ApicurioParsedSchemaMetadata) parsedSchemaAdapter).getSchema(); - case CONFLUENT -> parsedSchemaAdapter.getRawSchema(); - }; - attributeList.addAll(getExtractor(schemaType).processSchema(new ParsedSchema(schema), schemaRegistryEnum)); + if (StringUtils.isNotEmpty(registryName)) { + attributeList.addAll(getExtractor(schemaType).processSchema(schemaParsed, schemaRegistryEnum)); } return Pair.of(schemaType, attributeList); } diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java index 21b6f72c..8aaf1fe2 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java @@ -4,12 +4,13 @@ import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; -public interface ExtractorRegistry { - List processSchema(final T schema, SchemaRegistryEnum registry); +public interface ExtractorRegistry> { - ParsedSchema processSchema(final String fileContent); + List processSchema(final AbstractParsedSchema schema, SchemaRegistryEnum registry); + + T processSchema(final String fileContent); List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum); diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java index 073202a1..c78f8d59 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java @@ -7,19 +7,21 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; +import org.apache.avro.Schema; -public class AvroExtractor implements ExtractorRegistry { +public class AvroExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO, new AvroApicurioExtractor()); - public final List processSchema(final T schema, final SchemaRegistryEnum registryEnum) { - return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema.rawSchema()); + public final List processSchema(final AbstractParsedSchema schema, final SchemaRegistryEnum registryEnum) { + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema.getSchema()); } - public final ParsedSchema processSchema(final String fileContent) { - return new ParsedSchema(fileContent, "AVRO"); + public final AvroParsedSchema processSchema(final String fileContent) { + return new AvroParsedSchema(null, new Schema.Parser().parse(fileContent)); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java index 88ef7776..ca3ac322 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java @@ -7,21 +7,21 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; - -public class JsonExtractor implements ExtractorRegistry { +public class JsonExtractor implements ExtractorRegistry { private static final Map> SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new JsonDefaultExtractor(), SchemaRegistryEnum.APICURIO, new JsonDefaultExtractor()); - public final List processSchema(final T schemaReceived, final SchemaRegistryEnum registryEnum) { - return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.rawSchema().toString()); + public final List processSchema(final AbstractParsedSchema schemaReceived, final SchemaRegistryEnum registryEnum) { + return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.getRawSchema().toString()); } - public final ParsedSchema processSchema(final String fileContent) { - return new ParsedSchema(fileContent, "JSON"); + public final JsonParsedSchema processSchema(final String fileContent) { + return new JsonParsedSchema(null, fileContent); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java index 62f3b73c..ea73b9a6 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java @@ -4,14 +4,14 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; import com.squareup.wire.schema.internal.parser.ProtoFileElement; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor { +public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor> { - public final List processSchema(final ParsedSchema schemaReceived) { - return processSchemaDefault((ProtoFileElement) schemaReceived.rawSchema()); + public final List processSchema(final AbstractParsedSchema schemaReceived) { + return processSchemaDefault(schemaReceived.getRawSchema()); } public final List getSchemaNameList(final String schema) { diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java index 9ad3f29a..d1944c11 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java @@ -8,19 +8,23 @@ import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; +import com.squareup.wire.schema.Location; +import com.squareup.wire.schema.internal.parser.ProtoParser; -public class ProtobufExtractor implements ExtractorRegistry { +public class ProtobufExtractor implements ExtractorRegistry { private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new ProtoBufConfluentExtractor(), SchemaRegistryEnum.APICURIO, new ProtoBufApicurioExtractor()); - public final List processSchema(final T schemaReceived, final SchemaRegistryEnum registryEnum) { + public final List processSchema(final AbstractParsedSchema schemaReceived, final SchemaRegistryEnum registryEnum) { return new ArrayList(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived)); } - public final ParsedSchema processSchema(final String fileContent) { - return (T) new ParsedSchema(fileContent, "PROTOBUF"); + public final ProtobufParsedSchema processSchema(final String fileContent) { + final var protoDescriptor = new ProtoParser(Location.get("/"), fileContent.toCharArray()); + return new ProtobufParsedSchema(null, protoDescriptor.readProtoFile()); } public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) { diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java new file mode 100644 index 00000000..ee0d8d57 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java @@ -0,0 +1,27 @@ +package com.sngular.kloadgen.parsedschema; + +import lombok.Getter; + +@Getter +public abstract class AbstractParsedSchema { + + private final T schema; + private final String schemaType; + private final String name; + + public AbstractParsedSchema(final String name, final String type, final T schema) { + this.name = name; + this.schemaType = type; + this.schema = schema; + } + + public final T schema() { + return this.schema; + } + + public final String schemaType() { + return this.schemaType; + } + + public abstract T getRawSchema(); +} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java new file mode 100644 index 00000000..7641cd27 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java @@ -0,0 +1,15 @@ +package com.sngular.kloadgen.parsedschema; + +import org.apache.avro.Schema; + +public class AvroParsedSchema extends AbstractParsedSchema { + + public AvroParsedSchema(final String name, final Schema schema) { + super(name, "AVRO", schema); + } + + @Override + public final Schema getRawSchema() { + return getSchema(); + } +} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java deleted file mode 100644 index b7d46327..00000000 --- a/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sngular.kloadgen.parsedschema; - -public interface IParsedSchema { - - String schemaType(); - - String name(); - - String canonicalString(); - - Object rawSchema(); - -} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java new file mode 100644 index 00000000..1400a970 --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java @@ -0,0 +1,13 @@ +package com.sngular.kloadgen.parsedschema; + +public class JsonParsedSchema extends AbstractParsedSchema { + + public JsonParsedSchema(final String name, final String schema) { + super(name, "JSON", schema); + } + + @Override + public final String getRawSchema() { + return getSchema(); + } +} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java deleted file mode 100644 index 43aec860..00000000 --- a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.sngular.kloadgen.parsedschema; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import com.sngular.kloadgen.exception.KLoadGenException; -import com.squareup.wire.schema.internal.parser.ProtoFileElement; -import io.confluent.kafka.schemaregistry.avro.AvroSchema; -import io.confluent.kafka.schemaregistry.json.JsonSchema; -import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -import org.apache.avro.Schema; - -public class ParsedSchema implements IParsedSchema { - - private final T schema; - private final String schemaType; - - public ParsedSchema(final String fileContent, final String schemaType) { - switch (schemaType) { - case "AVRO" -> { - this.schema = (T) new Schema.Parser().parse(fileContent); - } - case "JSON" -> { - this.schema = (T) new JsonSchema(fileContent); - } - case "PROTOBUF" -> { - this.schema = (T) new ProtobufSchema(fileContent); - } - default -> throw new IllegalArgumentException("schemaType not supported: " + schemaType); - } - this.schemaType = schemaType; - } - - public ParsedSchema(final File file, final String schemaType) throws IOException { - this(new String(Files.readAllBytes(file.toPath())), schemaType); - } - - public ParsedSchema(final T schema, final String type) { - this.schema = schema; - this.schemaType = type; - } - - public ParsedSchema(final T schema) { - this.schema = schema; - this.schemaType = switch (this.schema.getClass().getSimpleName()) { - case "Schema", "AvroSchema", "UnionSchema", "RecordSchema" -> "AVRO"; - case "ProtoBuf", "ProtoFileElement" -> "PROTOBUF"; - case "JsonSchema", "ObjectSchema" -> "JSON"; - default -> throw new KLoadGenException(String.format("Need to specify schemaType for %s", this.schema.getClass().getSimpleName())); - }; - } - - public ParsedSchema(final io.confluent.kafka.schemaregistry.ParsedSchema parsedSchema) throws IOException { - this(parsedSchema.canonicalString(), parsedSchema.schemaType()); - } - - public final Object schema() { - return this.schema; - } - - public final String schemaType() { - return this.schemaType; - } - - public final String name() { - return null; - } - - public final String canonicalString() { - return switch (this.schemaType) { - case "AVRO" -> stringAvro(this.schema); - case "JSON" -> stringJson(this.schema); - case "PROTOBUF" -> stringProto(this.schema); - default -> this.schema.toString(); - }; - } - - private String stringAvro(final T schema) { - final String result; - if (schema instanceof AvroSchema) { - result = ((AvroSchema) this.schema).canonicalString(); - } else { - result = this.schema.toString(); - } - return result; - } - - private String stringJson(final T schema) { - final String result; - if (schema instanceof JsonSchema) { - result = ((JsonSchema) this.schema).canonicalString(); - } else { - result = this.schema.toString(); - } - return result; - } - - private String stringProto(final T schema) { - final String result; - if (schema instanceof ProtobufSchema) { - result = ((ProtobufSchema) this.schema).canonicalString(); - } else if (schema instanceof ProtoFileElement) { - result = ((ProtoFileElement) this.schema).toSchema(); - } else { - result = this.schema.toString(); - } - return result; - } - - public final Object rawSchema() { - return switch (this.schemaType) { - case "AVRO" -> rawAvro(this.schema); - case "JSON" -> rawJson(this.schema); - case "PROTOBUF" -> rawProto(this.schema); - default -> this.schema; - }; - } - - private Object rawAvro(final T schema) { - final Object result; - if (schema instanceof AvroSchema) { - result = ((AvroSchema) this.schema).rawSchema(); - } else { - result = this.schema; - } - return result; - } - - private Object rawJson(final T schema) { - final Object result; - if (schema instanceof JsonSchema) { - result = ((JsonSchema) this.schema).rawSchema(); - } else { - result = this.schema.toString(); - } - return result; - } - - private Object rawProto(final T schema) { - final Object result; - if (schema instanceof ProtobufSchema) { - result = ((ProtobufSchema) this.schema).rawSchema(); - } else { - result = this.schema; - } - return result; - } - -} diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java new file mode 100644 index 00000000..94dc419c --- /dev/null +++ b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java @@ -0,0 +1,15 @@ +package com.sngular.kloadgen.parsedschema; + +import com.squareup.wire.schema.internal.parser.ProtoFileElement; + +public class ProtobufParsedSchema extends AbstractParsedSchema { + + public ProtobufParsedSchema(final String name, final ProtoFileElement schema) { + super(name, "PROTOBUF", schema); + } + + @Override + public final ProtoFileElement getRawSchema() { + return getSchema(); + } +} diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java index d48782d4..d631c43a 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java @@ -14,14 +14,11 @@ import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.ConstraintTypeEnum; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO; import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory; import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.randomtool.generator.AvroGeneratorTool; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import com.sngular.kloadgen.serializer.EnrichedRecord; @@ -44,18 +41,10 @@ public final class AvroObjectCreatorFactory implements ObjectCreatorFactory { private final Map entity = new HashMap<>(); public AvroObjectCreatorFactory(final Object schema, final BaseSchemaMetadata metadata) { - if (schema instanceof ParsedSchema) { - this.schema = (Schema) ((ParsedSchema) schema).rawSchema(); + if (schema instanceof AvroParsedSchema) { + this.schema = ((AvroParsedSchema) schema).getRawSchema(); } else if (schema instanceof Schema) { this.schema = (Schema) schema; - } else if (schema instanceof BaseParsedSchema) { - final BaseParsedSchema schemaParse = (BaseParsedSchema) schema; - final AbstractParsedSchemaAdapter adapterParse = schemaParse.getParsedSchemaAdapter(); - if (adapterParse instanceof ApicurioParsedSchemaMetadata) { - this.schema = (Schema) ((ApicurioParsedSchemaMetadata) adapterParse).getSchema(); - } else { - this.schema = adapterParse.getRawSchema(); - } } else { throw new KLoadGenException("Unsupported schema type"); } diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java index 9420c220..2559fa3b 100644 --- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java +++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java @@ -20,13 +20,11 @@ import com.google.protobuf.DynamicMessage.Builder; import com.google.protobuf.Message; import com.sngular.kloadgen.exception.KLoadGenException; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO; import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory; import com.sngular.kloadgen.processor.util.SchemaProcessorUtils; import com.sngular.kloadgen.randomtool.generator.ProtoBufGeneratorTool; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import com.sngular.kloadgen.serializer.EnrichedRecord; @@ -44,15 +42,10 @@ public class ProtobufObjectCreatorFactory implements ObjectCreatorFactory { private final Map entity = new HashMap<>(); public ProtobufObjectCreatorFactory(final Object schema, final BaseSchemaMetadata metadata) throws DescriptorValidationException, IOException { - if (schema instanceof ParsedSchema) { - this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) ((ParsedSchema) schema).rawSchema(), metadata); + if (schema instanceof AbstractParsedSchema) { + this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) ((AbstractParsedSchema) schema).getRawSchema(), metadata); } else if (schema instanceof ProtoFileElement) { this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) schema, metadata); - } else if (schema instanceof BaseParsedSchema) { - final BaseParsedSchema schemaParse = (BaseParsedSchema) schema; - final AbstractParsedSchemaAdapter adapterParse = schemaParse.getParsedSchemaAdapter(); - final Object schemaParsed = adapterParse.getRawSchema(); - this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) schemaParsed, metadata); } else { throw new KLoadGenException("Unsupported schema type"); } diff --git a/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java b/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java index 8f035c90..468108cb 100644 --- a/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java +++ b/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java @@ -26,7 +26,6 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.Descriptors.DescriptorValidationException; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import com.sngular.kloadgen.util.JMeterHelper; @@ -187,9 +186,10 @@ private static void processImport(final BaseSchemaMetadata()); + final var protoFileElement = JMeterHelper.getParsedSchema(getSubjectName(importedClass, metadata), + JMeterContextService.getContext().getProperties()); + final var importedProtobufSchema = new ProtobufSchema( + (ProtoFileElement) protoFileElement.getSchema(), metadata.getSchemaMetadataAdapter().getReferences(), new HashMap<>()); if (!ProtobufHelper.NOT_ACCEPTED_IMPORTS.contains(importedClass)) { schemaBuilder.addDependency(importedProtobufSchema.toDescriptor().getFullName()); schemaBuilder.addSchema(convertDynamicSchema(importedProtobufSchema, metadata)); diff --git a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java index ef2abee6..f9f99497 100644 --- a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java +++ b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java @@ -19,20 +19,20 @@ import java.util.List; import java.util.Objects; -import com.sngular.kloadgen.common.SchemaRegistryEnum; -import com.sngular.kloadgen.common.SchemaTypeEnum; -import com.sngular.kloadgen.extractor.SchemaExtractor; -import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; -import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import com.sngular.kloadgen.util.PropsKeysHelper; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.filechooser.FileSystemView; + +import com.sngular.kloadgen.common.SchemaRegistryEnum; +import com.sngular.kloadgen.common.SchemaTypeEnum; +import com.sngular.kloadgen.extractor.SchemaExtractor; +import com.sngular.kloadgen.extractor.extractors.ExtractorFactory; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.util.PropsKeysHelper; import lombok.extern.slf4j.Slf4j; import org.apache.avro.AvroRuntimeException; import org.apache.jmeter.gui.ClearGui; @@ -93,9 +93,9 @@ public final void actionFileChooser(final ActionEvent event) { final File schemaFile = Objects.requireNonNull(fileChooser.getSelectedFile()); try { final String schemaType = schemaTypeComboBox.getSelectedItem().toString(); - final ExtractorRegistry extractor = ExtractorFactory.getExtractor(schemaType); + final var extractor = ExtractorFactory.getExtractor(schemaType); final String fileContent = SchemaExtractor.readSchemaFile(schemaFile.getPath()); - final ParsedSchema parserSchema = (ParsedSchema) extractor.processSchema(fileContent); + final var parserSchema = extractor.processSchema(fileContent); final List schemaFieldList = extractor.processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT); buildTable(schemaFieldList, fileContent, schemaType); } catch (final IOException e) { @@ -106,7 +106,7 @@ public final void actionFileChooser(final ActionEvent event) { } } - public final List getAttributeList(final ParsedSchema selectedSchema) { + public final List getAttributeList(final AbstractParsedSchema selectedSchema) { final List result = new ArrayList<>(); if (Objects.nonNull(selectedSchema)) { result.addAll(SchemaExtractor.flatPropertiesList(selectedSchema)); diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index d6030cf7..ba6f5961 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -47,12 +47,12 @@ public class AsyncApiSampler extends AbstractSampler implements Serializable { private final transient ApiExtractor apiExtractor; - private JsonNode asyncApiFileNode; - private final transient BaseLoadGenerator generator; private final transient ObjectMapper mapper = new ObjectMapper(); + private JsonNode asyncApiFileNode; + public AsyncApiSampler() { apiExtractor = new AsyncApiExtractorImpl(); generator = new JsonSRLoadGenerator(); @@ -103,38 +103,6 @@ private Map extractProps() { return properties; } - public final AsyncApiFile getAsyncApiFileNode() { - AsyncApiFile asyncApiFile = null; - if (Objects.isNull(asyncApiFileNode)) { - try { - asyncApiFileNode = mapper.readTree(this.getPropertyAsString("asyncapifilestr")); - } catch (final IOException e) { - throw new KLoadGenException(e); - } - } - if (Objects.nonNull(asyncApiFileNode) && !asyncApiFileNode.isMissingNode()) { - asyncApiFile = apiExtractor.processNode(asyncApiFileNode); - } - return asyncApiFile; - } - - public final void setAsyncApiFileNode(final JsonNode asyncApiFileNode) { - this.asyncApiFileNode = asyncApiFileNode; - try { - this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFileNode)); - } catch (final JsonProcessingException e) { - throw new KLoadGenException(e); - } - } - - public final void setAsyncApiServerName(final String asyncApiServerName) { - this.setProperty("asyncApiServerName", asyncApiServerName); - } - - public final void setSchemaFieldConfiguration(final List asyncApiServerName) { - this.setProperty(new CollectionProperty("schemaFieldConfiguration", asyncApiServerName)); - } - public final List getSchemaFieldConfiguration() { final List propertyList = new ArrayList<>(); for (TestElementProperty elementProperty : (List) this.getProperty("schemaFieldConfiguration").getObjectValue()) { @@ -150,28 +118,8 @@ public final List getSchemaFieldConfiguration() { return propertyList; } - public final void setBrokerConfiguration(final List asyncApiServerName) { - this.setProperty(new CollectionProperty("brokerConfiguration", asyncApiServerName)); - } - - public final List getBrokerConfiguration() { - final List propertyList = new ArrayList<>(); - for (TestElementProperty elementProperty : (List) this.getProperty("brokerConfiguration").getObjectValue()) { - propertyList.add(PropertyMapping - .builder() - .propertyName(elementProperty.getElement().getPropertyAsString("propertyName")) - .propertyValue(elementProperty.getElement().getPropertyAsString("propertyValue")) - .build()); - } - return propertyList; - } - - public final String getAsyncApiSchemaName() { - return this.getPropertyAsString("asyncapischemaname"); - } - - public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { - this.setProperty("asyncapischemaname", asyncApiSchemaName); + public final void setSchemaFieldConfiguration(final List asyncApiServerName) { + this.setProperty(new CollectionProperty("schemaFieldConfiguration", asyncApiServerName)); } private ProducerRecord getProducerRecord(final EnrichedRecord messageVal, final boolean valueFlag) { @@ -199,7 +147,59 @@ private String prettyPrint(final RecordMetadata recordMetadata) { return String.format(TEMPLATE, recordMetadata.topic(), recordMetadata.partition(), recordMetadata.offset()); } + public final List getBrokerConfiguration() { + final List propertyList = new ArrayList<>(); + for (TestElementProperty elementProperty : (List) this.getProperty("brokerConfiguration").getObjectValue()) { + propertyList.add(PropertyMapping + .builder() + .propertyName(elementProperty.getElement().getPropertyAsString("propertyName")) + .propertyValue(elementProperty.getElement().getPropertyAsString("propertyValue")) + .build()); + } + return propertyList; + } + + public final void setBrokerConfiguration(final List asyncApiServerName) { + this.setProperty(new CollectionProperty("brokerConfiguration", asyncApiServerName)); + } + + public final String getAsyncApiSchemaName() { + return this.getPropertyAsString("asyncapischemaname"); + } + + public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { + this.setProperty("asyncapischemaname", asyncApiSchemaName); + } + private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); } + + public final AsyncApiFile getAsyncApiFileNode() { + AsyncApiFile asyncApiFile = null; + if (Objects.isNull(asyncApiFileNode)) { + try { + asyncApiFileNode = mapper.readTree(this.getPropertyAsString("asyncapifilestr")); + } catch (final IOException e) { + throw new KLoadGenException(e); + } + } + if (Objects.nonNull(asyncApiFileNode) && !asyncApiFileNode.isMissingNode()) { + asyncApiFile = apiExtractor.processNode(asyncApiFileNode); + } + return asyncApiFile; + } + + public final void setAsyncApiFileNode(final JsonNode asyncApiFileNode) { + this.asyncApiFileNode = asyncApiFileNode; + try { + this.setProperty("asyncapifilestr", mapper.writeValueAsString(asyncApiFileNode)); + } catch (final JsonProcessingException e) { + throw new KLoadGenException(e); + } + } + + public final void setAsyncApiServerName(final String asyncApiServerName) { + this.setProperty("asyncApiServerName", asyncApiServerName); + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java index e005b386..344c5890 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/KafkaProducerSampler.java @@ -99,7 +99,6 @@ public void setupTest(final JavaSamplerContext context) { topic = context.getParameter(ProducerKeysHelper.KAFKA_TOPIC_CONFIG); - props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, context.getParameter(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)); props.put(ProducerConfig.CLIENT_ID_CONFIG, context.getParameter(ProducerConfig.CLIENT_ID_CONFIG)); props.putIfAbsent(ProducerConfig.ACKS_CONFIG, "all"); @@ -195,21 +194,11 @@ private Boolean enrichedValueFlag() { private void fillSamplerResult(final ProducerRecord producerRecord, final SampleResult sampleResult) { final String result = "key: " - + producerRecord.key() - + ", payload: " + stringValue(producerRecord.value()); + + producerRecord.key() + + ", payload: " + stringValue(producerRecord.value()); sampleResult.setSamplerData(result); } - private String stringValue(final Object value) { - final String result; - if (value instanceof EnrichedRecord) { - result = ((EnrichedRecord) value).getGenericRecord().toString(); - } else { - result = value.toString(); - } - return result; - } - private void fillSampleResult(final SampleResult sampleResult, final String respondeData, final boolean successful) { sampleResult.setResponseData(respondeData, StandardCharsets.UTF_8.name()); sampleResult.setSuccessful(successful); @@ -223,5 +212,15 @@ private String prettyPrint(final RecordMetadata recordMetadata) { private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); } + + private String stringValue(final Object value) { + final String result; + if (value instanceof EnrichedRecord) { + result = ((EnrichedRecord) value).getGenericRecord().toString(); + } else { + result = value.toString(); + } + return result; + } } diff --git a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java index b3d573ba..6f8674c3 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java +++ b/src/main/java/com/sngular/kloadgen/sampler/SamplerUtil.java @@ -98,10 +98,6 @@ public static Arguments getCommonProducerDefaultParameters() { return defaultParameters; } - private static String propertyOrDefault(final String property, final String defaultToken, final String valueToSent) { - return defaultToken.equals(property) ? valueToSent : property; - } - @SuppressWarnings("checkstyle:ExecutableStatementCount") public static Arguments getCommonConsumerDefaultParameters() { final Arguments defaultParameters = new Arguments(); @@ -149,51 +145,6 @@ public static Arguments getCommonConsumerDefaultParameters() { return defaultParameters; } - public static void setupConsumerDeserializerProperties(final Properties props) { - if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY))) { - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY)); - } else { - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); - } - if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY))) { - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY)); - } else { - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); - } - } - - public static void setupConsumerSchemaRegistryProperties(final Properties props) { - final Map originals = new HashMap<>(); - setupSchemaRegistryAuthenticationProperties(JavaSamplerContext.getJMeterVariables(), originals); - props.putAll(originals); - - if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY))) { - props.put(ProducerKeysHelper.VALUE_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY)); - } - if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY))) { - props.put(ProducerKeysHelper.KEY_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY)); - } - } - - private static void setupSchemaRegistryAuthenticationProperties(final JMeterVariables context, final Map props) { - if (Objects.nonNull(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME))) { - - final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); - props.put(schemaRegistryManager.getSchemaRegistryUrlKey(), context.get(schemaRegistryManager.getSchemaRegistryUrlKey())); - props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); - - if (ProducerKeysHelper.FLAG_YES.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_FLAG))) { - if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BASIC_TYPE.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_KEY))) { - props.put(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE)); - props.put(SchemaRegistryClientConfig.USER_INFO_CONFIG, context.get(SchemaRegistryClientConfig.USER_INFO_CONFIG)); - } else { - props.put(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE)); - props.put(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG, context.get(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG)); - } - } - } - } - public static Properties setupCommonConsumerProperties(final JavaSamplerContext context) { final Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, context.getParameter(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG)); @@ -246,6 +197,32 @@ public static Properties setupCommonConsumerProperties(final JavaSamplerContext return props; } + public static void setupConsumerDeserializerProperties(final Properties props) { + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY))) { + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.KEY_DESERIALIZER_CLASS_PROPERTY)); + } else { + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + } + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY))) { + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JavaSamplerContext.getJMeterVariables().get(PropsKeysHelper.VALUE_DESERIALIZER_CLASS_PROPERTY)); + } else { + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + } + } + + public static void setupConsumerSchemaRegistryProperties(final Properties props) { + final Map originals = new HashMap<>(); + setupSchemaRegistryAuthenticationProperties(JavaSamplerContext.getJMeterVariables(), originals); + props.putAll(originals); + + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY))) { + props.put(ProducerKeysHelper.VALUE_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.VALUE_NAME_STRATEGY)); + } + if (Objects.nonNull(JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY))) { + props.put(ProducerKeysHelper.KEY_NAME_STRATEGY, JavaSamplerContext.getJMeterVariables().get(ProducerKeysHelper.KEY_NAME_STRATEGY)); + } + } + private static void verifySecurity(final JavaSamplerContext context, final Properties props) { if (ProducerKeysHelper.FLAG_YES.equalsIgnoreCase(context.getParameter(ProducerKeysHelper.SSL_ENABLED))) { @@ -291,6 +268,29 @@ private static void verifySecurity(final JavaSamplerContext context, final Prope } } + private static void setupSchemaRegistryAuthenticationProperties(final JMeterVariables context, final Map props) { + if (Objects.nonNull(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME))) { + + final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); + props.put(schemaRegistryManager.getSchemaRegistryUrlKey(), context.get(schemaRegistryManager.getSchemaRegistryUrlKey())); + props.put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME)); + + if (ProducerKeysHelper.FLAG_YES.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_FLAG))) { + if (SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_BASIC_TYPE.equals(context.get(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_AUTH_KEY))) { + props.put(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BASIC_AUTH_CREDENTIALS_SOURCE)); + props.put(SchemaRegistryClientConfig.USER_INFO_CONFIG, context.get(SchemaRegistryClientConfig.USER_INFO_CONFIG)); + } else { + props.put(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE, context.get(SchemaRegistryClientConfig.BEARER_AUTH_CREDENTIALS_SOURCE)); + props.put(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG, context.get(SchemaRegistryClientConfig.BEARER_AUTH_TOKEN_CONFIG)); + } + } + } + } + + private static String propertyOrDefault(final String property, final String defaultToken, final String valueToSent) { + return defaultToken.equals(property) ? valueToSent : property; + } + public static BaseLoadGenerator configureValueGenerator(final Properties props) { final JMeterVariables jMeterVariables = JMeterContextService.getContext().getVariables(); final BaseLoadGenerator generator; @@ -351,6 +351,22 @@ public static BaseLoadGenerator configureValueGenerator(final Properties props) return generator; } + private static BaseLoadGenerator getBaseLoadGenerator(final String schemaType) { + final BaseLoadGenerator generator; + if (JSON_TYPE_SET.contains(schemaType.toLowerCase())) { + generator = new JsonSRLoadGenerator(); + } else if ("avro".equalsIgnoreCase(schemaType)) { + generator = new AvroSRLoadGenerator(); + } else if ("protobuf".equalsIgnoreCase(schemaType)) { + generator = new ProtobufLoadGenerator(); + } else if ("noSchema".equalsIgnoreCase(schemaType)) { + generator = new PlainTextLoadGenerator(); + } else { + throw new KLoadGenException("Unsupported Serializer"); + } + return generator; + } + public static BaseLoadGenerator configureKeyGenerator(final Properties props) { final JMeterVariables jMeterVariables = JMeterContextService.getContext().getVariables(); final BaseLoadGenerator generator; @@ -402,22 +418,6 @@ public static BaseLoadGenerator configureKeyGenerator(final Properties props) { return generator; } - private static BaseLoadGenerator getBaseLoadGenerator(final String schemaType) { - final BaseLoadGenerator generator; - if (JSON_TYPE_SET.contains(schemaType.toLowerCase())) { - generator = new JsonSRLoadGenerator(); - } else if ("avro".equalsIgnoreCase(schemaType)) { - generator = new AvroSRLoadGenerator(); - } else if ("protobuf".equalsIgnoreCase(schemaType)) { - generator = new ProtobufLoadGenerator(); - } else if ("noSchema".equalsIgnoreCase(schemaType)) { - generator = new PlainTextLoadGenerator(); - } else { - throw new KLoadGenException("Unsupported Serializer"); - } - return generator; - } - public static List populateHeaders(final List kafkaHeaders, final ProducerRecord producerRecord) { final List headersSB = new ArrayList<>(); for (final HeaderMapping kafkaHeader : kafkaHeaders) { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java index a00d582f..7449f474 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/ApiSchemaRenderer.java @@ -4,10 +4,11 @@ import java.awt.Component; import java.util.Objects; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; import javax.swing.JLabel; import javax.swing.JList; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; + public class ApiSchemaRenderer extends JLabel implements javax.swing.ListCellRenderer { protected ApiSchemaRenderer() { diff --git a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java index b12fb4d2..1eaabe3f 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java +++ b/src/main/java/com/sngular/kloadgen/sampler/gui/AsyncApiSamplerGui.java @@ -24,18 +24,6 @@ import java.util.Objects; import java.util.Vector; -import com.sngular.kloadgen.exception.KLoadGenException; -import com.sngular.kloadgen.extractor.ApiExtractor; -import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; -import com.sngular.kloadgen.extractor.model.AsyncApiFile; -import com.sngular.kloadgen.extractor.model.AsyncApiSR; -import com.sngular.kloadgen.extractor.model.AsyncApiSchema; -import com.sngular.kloadgen.extractor.model.AsyncApiServer; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.model.PropertyMapping; -import com.sngular.kloadgen.sampler.AsyncApiSampler; -import com.sngular.kloadgen.sampler.SamplerUtil; -import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; @@ -50,6 +38,19 @@ import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; import javax.swing.table.DefaultTableModel; + +import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.extractor.ApiExtractor; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.extractor.model.AsyncApiSR; +import com.sngular.kloadgen.extractor.model.AsyncApiSchema; +import com.sngular.kloadgen.extractor.model.AsyncApiServer; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.PropertyMapping; +import com.sngular.kloadgen.sampler.AsyncApiSampler; +import com.sngular.kloadgen.sampler.SamplerUtil; +import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.config.Argument; @@ -67,15 +68,15 @@ public final class AsyncApiSamplerGui extends AbstractSamplerGui { private final ApiExtractor asyncApiExtractor = new AsyncApiExtractorImpl(); - private JPanel mainPanel; + private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Required", "Field Values List"}, 20); - private JTextField asyncApiFileTextField; + private final DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[]{"Property name", "Property Value"}, 20); - private final DefaultTableModel schemaFieldModel = new DefaultTableModel(new String[]{"Field Name", "Field Type", "Field Length", "Required", "Field Values List"}, 20); + private final DefaultTableModel schemaRegistryFieldModel = new DefaultTableModel(new String[]{"Property name", "Property Value"}, 20); - private final DefaultTableModel brokerFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); + private JPanel mainPanel; - private final DefaultTableModel schemaRegistryFieldModel = new DefaultTableModel(new String[] {"Property name", "Property Value"}, 20); + private JTextField asyncApiFileTextField; private JComboBox serverComboBox; @@ -87,18 +88,9 @@ public AsyncApiSamplerGui() { init(); } - @Override - public String getStaticLabel() { - return "AsyncApi Sampler"; - } - - @Override - public void clearGui() { - super.clearGui(); - asyncApiFileTextField.setText(""); - schemaFieldModel.setNumRows(0); - brokerFieldModel.setNumRows(0); - // registryUrl.setText(""); + private static void extractArgument(final JMeterProperty jmeterproperty, final ArrayList> propertyList) { + final var argument = (Argument) jmeterproperty.getObjectValue(); + propertyList.add(Pair.of(argument.getPropertyAsString("Argument.name"), argument.getPropertyAsString("Argument.value"))); } @Override @@ -170,20 +162,18 @@ public void configure(final TestElement element) { } } - private void actionFileChooser(final ActionEvent event) { - - final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + @Override + public void clearGui() { + super.clearGui(); + asyncApiFileTextField.setText(""); + schemaFieldModel.setNumRows(0); + brokerFieldModel.setNumRows(0); + // registryUrl.setText(""); + } - if (JFileChooser.APPROVE_OPTION == returnValue) { - try { - final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); - asyncApiFileTextField.setText(apiFile.getAbsolutePath()); - asyncApiFile = asyncApiExtractor.processFile(apiFile); - populateData(); - } catch (final KLoadGenException ex) { - JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); - } - } + @Override + public String getStaticLabel() { + return "AsyncApi Sampler"; } private void populateData(final AsyncApiSampler element) { @@ -220,6 +210,60 @@ private void populateData() { } } + private void fillTable(final DefaultTableModel schemaFields, final Collection> schemaData) { + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + schemaData.forEach(data -> schemaFields.addRow(dataToRow(data))); + } + } + + private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + for (var data : schemaData) { + schemaFields.addRow(data.getProperties()); + } + } + } + + private void fillTable(final DefaultTableModel schemaFields, final Object[] schemaData) { + if (Objects.nonNull(schemaData)) { + final var count = schemaFields.getRowCount(); + for (var i = 0; i < count; i++) { + schemaFields.removeRow(0); + } + for (var data : schemaData) { + schemaFields.addRow(((FieldValueMapping) data).getProperties()); + } + } + } + + private Object[] dataToRow(final Pair data) { + return new Object[]{data.getKey(), data.getValue()}; + } + + private void actionFileChooser(final ActionEvent event) { + + final int returnValue = fileChooser.showDialog(mainPanel, JMeterUtils.getResString("file_visualizer_open")); + + if (JFileChooser.APPROVE_OPTION == returnValue) { + try { + final File apiFile = Objects.requireNonNull(fileChooser.getSelectedFile()); + asyncApiFileTextField.setText(apiFile.getAbsolutePath()); + asyncApiFile = asyncApiExtractor.processFile(apiFile); + populateData(); + } catch (final KLoadGenException ex) { + JOptionPane.showMessageDialog(mainPanel, "Error has occurred: " + ex.getMessage(), "Weird Error", JOptionPane.ERROR_MESSAGE); + } + } + } + private Collection> prepareSRServer(final AsyncApiSR schemaRegistryData) { final var srPropoMap = schemaRegistryData.getPropertiesMap(); final var propertyList = new ArrayList>(); @@ -237,16 +281,11 @@ private Collection> prepareServer(final AsyncApiServer asyn CollectionUtils.select(SamplerUtil .getCommonProducerDefaultParameters(), property -> !property.getName().equalsIgnoreCase(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)) - .forEach(jmeterproperty -> extractArgument(jmeterproperty, propertyList)); + .forEach(jmeterproperty -> extractArgument(jmeterproperty, propertyList)); } return propertyList; } - private static void extractArgument(final JMeterProperty jmeterproperty, final ArrayList> propertyList) { - final var argument = (Argument) jmeterproperty.getObjectValue(); - propertyList.add(Pair.of(argument.getPropertyAsString("Argument.name"), argument.getPropertyAsString("Argument.value"))); - } - private void init() { setLayout(new BorderLayout()); setBorder(makeBorder()); @@ -255,7 +294,7 @@ private void init() { mainPanel.putClientProperty("html.disable", Boolean.FALSE); mainPanel.setBorder( BorderFactory - .createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + .createTitledBorder(BorderFactory.createLoweredBevelBorder(), "AsyncApi Module", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); mainPanel.add(createAsyncApiFileSelectPanel(), BorderLayout.NORTH); mainPanel.add(createAsyncApiTabs(), BorderLayout.CENTER); @@ -305,44 +344,6 @@ private JTabbedPane createAsyncApiTabs() { return tabbedPanel; } - private void fillTable(final DefaultTableModel schemaFields, final Collection> schemaData) { - if (Objects.nonNull(schemaData)) { - final var count = schemaFields.getRowCount(); - for (var i = 0; i < count; i++) { - schemaFields.removeRow(0); - } - schemaData.forEach(data -> schemaFields.addRow(dataToRow(data))); - } - } - - private void fillTable(final DefaultTableModel schemaFields, final Object[] schemaData) { - if (Objects.nonNull(schemaData)) { - final var count = schemaFields.getRowCount(); - for (var i = 0; i < count; i++) { - schemaFields.removeRow(0); - } - for (var data : schemaData) { - schemaFields.addRow(((FieldValueMapping) data).getProperties()); - } - } - } - - private void fillTable(final DefaultTableModel schemaFields, final List schemaData) { - if (Objects.nonNull(schemaData)) { - final var count = schemaFields.getRowCount(); - for (var i = 0; i < count; i++) { - schemaFields.removeRow(0); - } - for (var data : schemaData) { - schemaFields.addRow(data.getProperties()); - } - } - } - - private Object[] dataToRow(final Pair data) { - return new Object[] {data.getKey(), data.getValue()}; - } - private JPanel createBrokerPanel() { final JPanel brokerPanel = new JPanel(); brokerPanel.setLayout(new BorderLayout(0, 0)); @@ -355,7 +356,6 @@ private JPanel createBrokerPanel() { return brokerPanel; } - private JPanel createRegistryTab() { final JPanel registryUrlPanel = new JPanel(); registryUrlPanel.setLayout(new BorderLayout(0, 0)); @@ -368,6 +368,9 @@ private JPanel createRegistryTab() { return registryUrlPanel; } + private void registryComboActionListener(final ActionEvent actionEvent) { + } + private JPanel createSchemaTab() { final JPanel schemaTab = new JPanel(); schemaTab.setLayout(new BorderLayout(0, 0)); @@ -389,9 +392,6 @@ private void topicComboActionListener(final ActionEvent event) { } } - private void registryComboActionListener(final ActionEvent actionEvent) { - } - private void serverChooseActionListener(final ActionEvent actionEvent) { final JComboBox serverChoose = (JComboBox) actionEvent.getSource(); if (Objects.nonNull(serverChoose)) { diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/SchemaRegistryAdapter.java b/src/main/java/com/sngular/kloadgen/schemaregistry/SchemaRegistryAdapter.java index 17571aa5..e478ca25 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/SchemaRegistryAdapter.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/SchemaRegistryAdapter.java @@ -3,7 +3,7 @@ import java.util.Collection; import java.util.Map; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; @@ -17,9 +17,9 @@ public interface SchemaRegistryAdapter { Collection getAllSubjects(); - BaseSchemaMetadata getLatestSchemaMetadata(String subjectName); + BaseSchemaMetadata getLatestSchemaMetadata(String subjectName); - BaseParsedSchema getSchemaBySubject(String subjectName); + AbstractParsedSchema getSchemaBySubject(String subjectName); - BaseParsedSchema getSchemaBySubjectAndId(String subjectName, BaseSchemaMetadata metadata); + AbstractParsedSchema getSchemaBySubjectAndId(String subjectName, BaseSchemaMetadata metadata); } diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/AbstractParsedSchemaAdapter.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/AbstractParsedSchemaAdapter.java deleted file mode 100644 index 527f6ee4..00000000 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/AbstractParsedSchemaAdapter.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.sngular.kloadgen.schemaregistry.adapter.impl; - -public abstract class AbstractParsedSchemaAdapter { - - public abstract T getType(); - - public abstract T getRawSchema(); -} diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java deleted file mode 100644 index 4f17938e..00000000 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ApicurioParsedSchemaMetadata.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sngular.kloadgen.schemaregistry.adapter.impl; - -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor -public class ApicurioParsedSchemaMetadata extends AbstractParsedSchemaAdapter { - - private Object schema; - - private String rawSchema; - - private String type; - - public ApicurioParsedSchemaMetadata(final ParsedSchema parsedSchema) { - this.rawSchema = parsedSchema.canonicalString(); - this.type = parsedSchema.schemaType(); - this.schema = parsedSchema.rawSchema(); - } - - public static AbstractParsedSchemaAdapter parse(final ParsedSchema parsedSchema) { - return new ApicurioParsedSchemaMetadata(parsedSchema); - } -} diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/BaseParsedSchema.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/BaseParsedSchema.java deleted file mode 100644 index 407c1339..00000000 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/BaseParsedSchema.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sngular.kloadgen.schemaregistry.adapter.impl; - -import org.apache.avro.Schema.Parser; - -public class BaseParsedSchema extends Parser { - - private final T parsedSchemaAdapter; - - public BaseParsedSchema(final T parsedSchemaAdapter) { - this.parsedSchemaAdapter = parsedSchemaAdapter; - } - - public final T getParsedSchemaAdapter() { - return parsedSchemaAdapter; - } -} diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java b/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java deleted file mode 100644 index 99d3e10e..00000000 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/adapter/impl/ConfluentParsedSchemaMetadata.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.sngular.kloadgen.schemaregistry.adapter.impl; - -import com.sngular.kloadgen.parsedschema.IParsedSchema; -import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -import lombok.Getter; -import org.apache.avro.Schema; - -@Getter -public final class ConfluentParsedSchemaMetadata extends AbstractParsedSchemaAdapter { - - private final String schemaType; - - private final String name; - - private String canonicalString; - - private Object rawSchema; - - private ConfluentParsedSchemaMetadata(final IParsedSchema parsedSchema) { - this.schemaType = parsedSchema.schemaType(); - this.name = parsedSchema.name(); - this.canonicalString = parsedSchema.canonicalString(); - this.rawSchema = parsedSchema.rawSchema(); - } - - private ConfluentParsedSchemaMetadata(final Schema schema) { - this.schemaType = schema.getType().getName(); - this.name = schema.getName(); - } - - public ConfluentParsedSchemaMetadata(final ProtobufSchema schema) { - this.schemaType = schema.schemaType(); - this.name = schema.name(); - this.rawSchema = schema.rawSchema(); - this.canonicalString = schema.canonicalString(); - } - - public static AbstractParsedSchemaAdapter parse(final IParsedSchema parsedSchema) { - return new ConfluentParsedSchemaMetadata(parsedSchema); - } - - public static AbstractParsedSchemaAdapter parse(final Schema schema) { - return new ConfluentParsedSchemaMetadata(schema); - } - - public static AbstractParsedSchemaAdapter parse(final ProtobufSchema schema) { - return new ConfluentParsedSchemaMetadata(schema); - } - - @Override - public String getType() { - return this.schemaType; - } - - @Override - public Object getRawSchema() { - return this.rawSchema; - } -} diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ApicurioSchemaRegistry.java b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ApicurioSchemaRegistry.java index 28167f2c..2e5a7a0b 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ApicurioSchemaRegistry.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ApicurioSchemaRegistry.java @@ -12,10 +12,12 @@ import com.google.protobuf.Message; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; import io.apicurio.registry.resolver.SchemaParser; @@ -80,56 +82,46 @@ public BaseSchemaMetadata getLatestSchemaMetadata(final } @Override - public BaseParsedSchema getSchemaBySubject(final String artifactId) { - final ApicurioParsedSchemaMetadata schema = new ApicurioParsedSchemaMetadata(); + public AbstractParsedSchema getSchemaBySubject(final String artifactId) { try { final SearchedArtifact searchedArtifact = getLastestSearchedArtifact(artifactId); final InputStream inputStream = this.schemaRegistryClient.getLatestArtifact(searchedArtifact.getGroupId(), searchedArtifact.getId()); - final String searchedArtifactType = searchedArtifact.getType(); - setSchemaBySchemaType(schema, inputStream.readAllBytes(), searchedArtifactType); - schema.setType(searchedArtifactType); - return new BaseParsedSchema<>(schema); + return extractSchema(inputStream.readAllBytes(), searchedArtifact); } catch (final IOException e) { throw new KLoadGenException(e); } } - private static void setSchemaBySchemaType(final ApicurioParsedSchemaMetadata schema, final byte[] result, final String searchedArtifactType) { - - switch (SchemaTypeEnum.valueOf(searchedArtifactType)) { - case AVRO: - final SchemaParser parserAvro = new AvroSchemaParser<>(null); - schema.setSchema(parserAvro.parseSchema(result, new HashMap<>())); - break; - case PROTOBUF: - final SchemaParser parserProtobuf = new ProtobufSchemaParser<>(); - schema.setSchema(parserProtobuf.parseSchema(result, new HashMap<>())); - break; - case JSON: - final SchemaParser parserJson = new JsonSchemaParser<>(); - schema.setSchema(parserJson.parseSchema(result, new HashMap<>())); - break; - default: - throw new KLoadGenException(String.format("Schema type not supported %s", searchedArtifactType)); - - } - } - @Override - public final BaseParsedSchema getSchemaBySubjectAndId( - final String subjectName, final BaseSchemaMetadata metadata) { - final ApicurioParsedSchemaMetadata schema = new ApicurioParsedSchemaMetadata(); - + public AbstractParsedSchema getSchemaBySubjectAndId(final String subjectName, final BaseSchemaMetadata metadata) { final SchemaMetadataAdapter schemaMetadataAdapter = metadata.getSchemaMetadataAdapter(); try { final InputStream inputStream = this.schemaRegistryClient.getContentByGlobalId(schemaMetadataAdapter.getGlobalId()); - - final String searchedArtifactType = schemaMetadataAdapter.getType(); - setSchemaBySchemaType(schema, inputStream.readAllBytes(), searchedArtifactType); + return extractSchema(inputStream.readAllBytes(), subjectName, schemaMetadataAdapter.getType()); } catch (final IOException e) { throw new RuntimeException(e); } - return new BaseParsedSchema<>(schema); + } + + private AbstractParsedSchema extractSchema(final byte[] schema, final SearchedArtifact searchedArtifact) { + return extractSchema(schema, searchedArtifact.getName(), searchedArtifact.getType()); + } + + private AbstractParsedSchema extractSchema(final byte[] schemaInputStream, final String schemaName, final String schemaType) { + return switch (SchemaTypeEnum.valueOf(schemaType)) { + case AVRO -> { + final SchemaParser parserAvro = new AvroSchemaParser<>(null); + yield new AvroParsedSchema(schemaName, parserAvro.parseSchema(schemaInputStream, new HashMap<>())); + } + case PROTOBUF -> { + final SchemaParser parserProtobuf = new ProtobufSchemaParser<>(); + yield new ProtobufParsedSchema(schemaName, parserProtobuf.parseSchema(schemaInputStream, new HashMap<>()).getProtoFileElement()); + } + case JSON -> { + final SchemaParser parserJson = new JsonSchemaParser<>(); + yield new JsonParsedSchema(schemaName, parserJson.parseSchema(schemaInputStream, new HashMap<>()).toString()); + } + }; } private SearchedArtifact getLastestSearchedArtifact(final String artifactId) { diff --git a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java index f0987b2c..a88bf1e0 100644 --- a/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java +++ b/src/main/java/com/sngular/kloadgen/schemaregistry/impl/ConfluentSchemaRegistry.java @@ -6,15 +6,18 @@ import java.util.List; import java.util.Map; +import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter; +import com.squareup.wire.schema.internal.parser.ProtoFileElement; +import io.confluent.kafka.schemaregistry.ParsedSchema; import io.confluent.kafka.schemaregistry.avro.AvroSchemaProvider; import io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient; import io.confluent.kafka.schemaregistry.client.SchemaRegistryClient; @@ -23,6 +26,7 @@ import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchemaProvider; import io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig; import lombok.extern.slf4j.Slf4j; +import org.apache.avro.Schema; import org.apache.jmeter.threads.JMeterContextService; @Slf4j @@ -68,28 +72,35 @@ public BaseSchemaMetadata getLatestSchemaMetadata(final } } - public BaseParsedSchema getSchemaBySubject(final String subjectName) { + public AbstractParsedSchema getSchemaBySubject(final String subjectName) { try { final ConfluentSchemaMetadata schemaMetadata = ConfluentSchemaMetadata.parse(this.schemaRegistryClient.getLatestSchemaMetadata(subjectName)); - final ParsedSchema parsedSchema = new ParsedSchema(this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, schemaMetadata.getId())); - final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = ConfluentParsedSchemaMetadata.parse(parsedSchema); - return new BaseParsedSchema(abstractParsedSchemaAdapter); + final var parsedSchema = this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, schemaMetadata.getId()); + return extractSchema(parsedSchema, subjectName, schemaMetadata.getSchemaType()); } catch (RestClientException | IOException e) { throw new KLoadGenException(e.getMessage()); } } - public BaseParsedSchema getSchemaBySubjectAndId(final String subjectName, + public AbstractParsedSchema getSchemaBySubjectAndId(final String subjectName, final BaseSchemaMetadata metadata) { + final SchemaMetadataAdapter schemaMetadataAdapter = metadata.getSchemaMetadataAdapter(); try { - final ParsedSchema parsedSchema = new ParsedSchema(this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, metadata.getSchemaMetadataAdapter().getId())); - final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = ConfluentParsedSchemaMetadata.parse(parsedSchema); - return new BaseParsedSchema(abstractParsedSchemaAdapter); - } catch (RestClientException | IOException e) { - throw new KLoadGenException(e.getMessage()); + final var parsedSchema = this.schemaRegistryClient.getSchemaBySubjectAndId(subjectName, schemaMetadataAdapter.getGlobalId()); + return extractSchema(parsedSchema, subjectName, schemaMetadataAdapter.getType()); + } catch (final IOException | RestClientException e) { + throw new KLoadGenException(e); } } + private AbstractParsedSchema extractSchema(final ParsedSchema parsedSchema, final String schemaName, final String schemaType) { + return switch (SchemaTypeEnum.valueOf(schemaType)) { + case AVRO -> new AvroParsedSchema(schemaName, (Schema) parsedSchema.rawSchema()); + case PROTOBUF -> new ProtobufParsedSchema(schemaName, (ProtoFileElement) parsedSchema.rawSchema()); + case JSON -> new JsonParsedSchema(schemaName, parsedSchema.rawSchema().toString()); + }; + } + private String checkPropertyOrVariable(final String textToCheck) { final String result; if (textToCheck.matches("\\$\\{__P\\(.*\\)}")) { diff --git a/src/main/java/com/sngular/kloadgen/util/JMeterHelper.java b/src/main/java/com/sngular/kloadgen/util/JMeterHelper.java index 0115fb62..0d386e04 100644 --- a/src/main/java/com/sngular/kloadgen/util/JMeterHelper.java +++ b/src/main/java/com/sngular/kloadgen/util/JMeterHelper.java @@ -8,9 +8,9 @@ import java.util.Properties; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; import com.sngular.kloadgen.schemaregistry.SchemaRegistryManagerFactory; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.jmeter.threads.JMeterContextService; @@ -22,7 +22,7 @@ public final class JMeterHelper { private JMeterHelper() { } - public static BaseParsedSchema getParsedSchema(final String subjectName, final Properties properties) { + public static AbstractParsedSchema getParsedSchema(final String subjectName, final Properties properties) { String schemaRegistryName = properties.getProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME); if (schemaRegistryName == null || StringUtils.isEmpty(schemaRegistryName)) { schemaRegistryName = SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME_DEFAULT; diff --git a/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java index 10cde03a..7a23f9bb 100644 --- a/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElementBeanInfoTest.java @@ -19,8 +19,11 @@ class KafkaHeadersConfigElementBeanInfoTest { private static final String KAFKA_HEADERS = "kafkaHeaders"; + private static final String PROPERTIES = "props"; + private static final String SCHEMA = "schema"; + private KafkaHeadersConfigElementBeanInfo kafkaHeadersConfigElementBeanInfo; @BeforeEach diff --git a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java index a9057b4c..07d2501d 100644 --- a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java +++ b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementBeanInfoTest.java @@ -25,7 +25,9 @@ class KeySerializedConfigElementBeanInfoTest { private static final String KEY_NAME_STRATEGY = "keyNameStrategy"; private static final String KEY_SERIALIZER_CONFIGURATION = "keySerializerConfiguration"; + private static final String PROPERTIES = "props"; + private static final String SCHEMA = "schema"; private KeySerializedConfigElementBeanInfo keySerializedConfigElementBeanInfo; diff --git a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementTest.java b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementTest.java index d8759db7..9d2c9264 100644 --- a/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementTest.java +++ b/src/test/java/com/sngular/kloadgen/config/keyserialized/KeySerializedConfigElementTest.java @@ -47,7 +47,7 @@ void iterationStart(final WireMockRuntimeInfo wmRuntimeInfo) { JMeterContextService.getContext().getProperties().put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_PASSWORD_KEY, "foo"); final var keySerializedConfigElement = new KeySerializedConfigElement("avroSubject", Collections.emptyList(), "AVRO", - AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); + AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); keySerializedConfigElement.iterationStart(null); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.KEY_SUBJECT_NAME)).isNotNull(); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.KEY_SCHEMA_PROPERTIES)).isNotNull(); diff --git a/src/test/java/com/sngular/kloadgen/config/keysimple/KeySimpleConfigElementTest.java b/src/test/java/com/sngular/kloadgen/config/keysimple/KeySimpleConfigElementTest.java index c50f9640..37886ce0 100644 --- a/src/test/java/com/sngular/kloadgen/config/keysimple/KeySimpleConfigElementTest.java +++ b/src/test/java/com/sngular/kloadgen/config/keysimple/KeySimpleConfigElementTest.java @@ -50,9 +50,9 @@ void iterationStart() { Assertions.assertThat(variables.entrySet()) .hasSize(4) .containsExactlyInAnyOrder(new SimpleEntry<>("key.type", "string"), - new SimpleEntry<>("key.value", ""), - new SimpleEntry<>("key.serializer.class.property", "org.apache.kafka.common.serialization.StringSerializer"), - new SimpleEntry<>("simple.keyed.message", true)); + new SimpleEntry<>("key.value", ""), + new SimpleEntry<>("key.serializer.class.property", "org.apache.kafka.common.serialization.StringSerializer"), + new SimpleEntry<>("simple.keyed.message", true)); } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementTest.java b/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementTest.java index 70565aa7..bca47f88 100644 --- a/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementTest.java +++ b/src/test/java/com/sngular/kloadgen/config/valuefileserialized/ValueFileSerializedConfigElementTest.java @@ -41,7 +41,7 @@ void iterationStart() { + ".topic.value\"}"; final var valueFileSerializedConfigElement = new ValueFileSerializedConfigElement("avroSubject", Collections.emptyList(), definitionSchema, "AVRO", - AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); + AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); valueFileSerializedConfigElement.iterationStart(null); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.VALUE_SUBJECT_NAME)).isNotNull(); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES)).isNotNull(); diff --git a/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementTest.java b/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementTest.java index adc5af03..a0cb544d 100644 --- a/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementTest.java +++ b/src/test/java/com/sngular/kloadgen/config/valueserialized/ValueSerializedConfigElementTest.java @@ -39,7 +39,7 @@ public void setUp() { void iterationStart() { final var valueSerializedConfigElement = new ValueSerializedConfigElement("avroSubject", Collections.emptyList(), "AVRO", - AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); + AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); valueSerializedConfigElement.iterationStart(null); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.VALUE_SUBJECT_NAME)).isNotNull(); Assertions.assertThat(JMeterContextService.getContext().getVariables().getObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES)).isNotNull(); diff --git a/src/test/java/com/sngular/kloadgen/config/valuesimple/ValueSimpleConfigElementTest.java b/src/test/java/com/sngular/kloadgen/config/valuesimple/ValueSimpleConfigElementTest.java index 46ea8c60..2ca37a19 100644 --- a/src/test/java/com/sngular/kloadgen/config/valuesimple/ValueSimpleConfigElementTest.java +++ b/src/test/java/com/sngular/kloadgen/config/valuesimple/ValueSimpleConfigElementTest.java @@ -19,7 +19,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; - class ValueSimpleConfigElementTest { private JMeterContext jmcx; @@ -53,6 +52,6 @@ void iterationStart() { .containsExactlyInAnyOrder(new SimpleEntry<>("message.value", "data"), new SimpleEntry<>("message.type", "String"), new SimpleEntry<>("value.schema.type", "NoSchema"), - new SimpleEntry<>("value.serializer.class.property", "org.apache.kafka.common.serialization.StringSerializer")); + new SimpleEntry<>("value.serializer.class.property", "org.apache.kafka.common.serialization.StringSerializer")); } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java b/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java new file mode 100644 index 00000000..cf6e874f --- /dev/null +++ b/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java @@ -0,0 +1,15 @@ +package com.sngular.kloadgen.extractor; + +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; + +public class FakeParsedSchema extends AbstractParsedSchema { + + public FakeParsedSchema(final String name, final String type, final String schema) { + super(name, type, schema); + } + + @Override + public final String getRawSchema() { + return getSchema(); + } +} diff --git a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java index d5f7a303..a9401ddc 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/SchemaExtractorTest.java @@ -13,14 +13,15 @@ import com.sngular.kloadgen.common.SchemaRegistryEnum; import com.sngular.kloadgen.exception.KLoadGenException; -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioParsedSchemaMetadata; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.testutil.ParsedSchemaUtil; import com.sngular.kloadgen.util.JMeterHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import com.squareup.wire.schema.Location; +import com.squareup.wire.schema.internal.parser.ProtoParser; +import org.apache.avro.Schema; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -73,9 +74,8 @@ void testFlatPropertiesListWithAVRO() throws IOException { final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.APICURIO.toString()); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); - final var baseParsedSchema = new BaseParsedSchema<>(ApicurioParsedSchemaMetadata.parse(parsedSchema)); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + final var parsedSchema = new AvroParsedSchema("test", new Schema.Parser().parse(testFile)); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); final var result = SchemaExtractor.flatPropertiesList("avroSubject"); @@ -86,13 +86,12 @@ void testFlatPropertiesListWithAVRO() throws IOException { @DisplayName("Test flatPropertiesList with Json") void testFlatPropertiesListWithJson() throws IOException { - final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); + final var testFile = fileHelper.getContent("/jsonschema/basic.jcs"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final var parsedSchema = new ParsedSchema(testFile, "JSON"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); + final var parsedSchema = new JsonParsedSchema("JSON", testFile); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); final var result = SchemaExtractor.flatPropertiesList("jsonSubject"); Assertions.assertThat(result).isNotNull(); @@ -102,13 +101,12 @@ void testFlatPropertiesListWithJson() throws IOException { @DisplayName("Test flatPropertiesList with Protobuf") void testFlatPropertiesListWithProtobuf() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); + final var testFile = fileHelper.getContent("/proto-files/easyTest.proto"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "PROTOBUF"); - final BaseParsedSchema baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); + final var parsedSchema = new ProtobufParsedSchema("test", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); final var result = SchemaExtractor.flatPropertiesList("protobufSubject"); Assertions.assertThat(result).isNotNull(); } @@ -126,13 +124,12 @@ void testReadSchemaFile() throws IOException { @DisplayName("Test flatPropertiesList throws exception schema type not supported") void testFlatPropertiesListWithException() { - final var parsedSchema = new ParsedSchemaUtil(); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); + final var parsedSchema = new FakeParsedSchema("Test", "TestType", null); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); Assertions.assertThatExceptionOfType(KLoadGenException.class) .isThrownBy(() -> SchemaExtractor.flatPropertiesList("exceptionSubject") ).withMessage(String.format("Schema type not supported %s", parsedSchema.schemaType())); @@ -142,12 +139,11 @@ void testFlatPropertiesListWithException() { @Test @DisplayName("Test flatPropertiesList with AVRO and CONFLUENT") void testSchemaTypeIsCorrectWhenAvroConfluent() throws IOException { - final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); + final var testFile = fileHelper.getContent("/avro-files/embedded-avros-example-test.avsc"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + final var parsedSchema = new AvroParsedSchema("test", new Schema.Parser().parse(testFile)); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); final var result = SchemaExtractor.flatPropertiesList("avroSubject"); diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java index d42832fc..907bb70c 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -1,5 +1,9 @@ package com.sngular.kloadgen.extractor.asyncapi; +import java.io.File; +import java.io.IOException; +import java.util.Locale; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -14,10 +18,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; -import java.util.Locale; - class AsyncApiExtractorImplTest { private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); @@ -36,7 +36,7 @@ public final void setUp() { @Test @DisplayName("Should extract asyncapi file") - void testExtractFile() throws IOException { + void testExtractFile() { final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java index 8431b4bb..76734fc9 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactoryTest.java @@ -13,9 +13,7 @@ import com.sngular.kloadgen.extractor.extractors.json.JsonExtractor; import com.sngular.kloadgen.extractor.extractors.protobuf.ProtobufExtractor; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema; -import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentParsedSchemaMetadata; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.JMeterHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; @@ -35,17 +33,16 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; - @SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") class ExtractorFactoryTest { - @Captor - private ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Schema.class); - private final Properties properties = new Properties(); private final Extractor avroConfluentExtractor = new AvroConfluentExtractor(); + @Captor + private ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Schema.class); + private MockedStatic jmeterHelperMockedStatic; private MockedStatic jmeterContextServiceMockedStatic; @@ -76,19 +73,19 @@ void flatPropertiesList() throws IOException { final AvroExtractor avroExtractor = Mockito.mock(AvroExtractor.class); ExtractorFactory.configExtractorFactory(avroExtractor, new JsonExtractor(), new ProtobufExtractor()); - final File testFile = new FileHelper().getFile("/avro-files/embedded-avros-example-test.avsc"); + final var testFile = new FileHelper().getContent("/avro-files/embedded-avros-example-test.avsc"); properties.setProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, SchemaRegistryEnum.CONFLUENT.toString()); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); - final var baseParsedSchema = new BaseParsedSchema<>(ConfluentParsedSchemaMetadata.parse(parsedSchema)); + final var parsedSchema = new AvroParsedSchema("test", new Schema.Parser().parse(testFile)); - jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(baseParsedSchema); + jmeterHelperMockedStatic.when(() -> JMeterHelper.getParsedSchema(Mockito.anyString(), Mockito.any(Properties.class))).thenReturn(parsedSchema); jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); final Schema schema = new Schema.Parser().parse(testFile); final List fieldValueMappingList = avroConfluentExtractor.processSchema(schema); - Mockito.when(avroExtractor.processSchema(new ParsedSchema(argumentCaptor.capture(), ""), ArgumentMatchers.isA(SchemaRegistryEnum.class))).thenReturn(fieldValueMappingList); + Mockito.when(avroExtractor.processSchema(new AvroParsedSchema("test", argumentCaptor.capture()), ArgumentMatchers.isA(SchemaRegistryEnum.class))) + .thenReturn(fieldValueMappingList); final var result = SchemaExtractor.flatPropertiesList(schema.getName()); Assertions.assertThat(result).isNotNull(); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java index 5ad7b5cd..9d8d9299 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroApicurioExtractorTest.java @@ -1,5 +1,7 @@ package com.sngular.kloadgen.extractor.extractors.avro; +import java.util.List; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; @@ -8,8 +10,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.List; - class AvroApicurioExtractorTest { private final FileHelper fileHelper = new FileHelper(); diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java index 66d6db1e..5a21bcf7 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/avro/AvroConfluentExtractorTest.java @@ -1,5 +1,7 @@ package com.sngular.kloadgen.extractor.extractors.avro; +import java.util.List; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; @@ -10,17 +12,12 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import java.util.List; - - class AvroConfluentExtractorTest { - private final FileHelper fileHelper = new FileHelper(); private final Extractor avroConfluentExtractor = new AvroConfluentExtractor(); - @Test @DisplayName("Should extract Embedded Record") void testFlatPropertiesEmbeddedAvros() throws Exception { diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java index deee897f..d176e41c 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/json/JsonDefaultTest.java @@ -22,8 +22,6 @@ class JsonDefaultTest { private final Extractor jsonDefaultExtractor = new JsonDefaultExtractor(); - - @Test @DisplayName("Should extract a basic array") void testBasicArray() throws Exception { diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java index 6462e62c..263a52c7 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufApicurioExtractorTest.java @@ -1,5 +1,9 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.io.File; +import java.util.List; +import java.util.Locale; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.testutil.FileHelper; @@ -15,10 +19,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.util.List; -import java.util.Locale; - class ProtobufApicurioExtractorTest { private final FileHelper fileHelper = new FileHelper(); @@ -37,7 +37,6 @@ public void setUp() { JMeterUtils.setLocale(Locale.ENGLISH); } - @Test @DisplayName("Test Extractor with simple proto file") void testFlatProperties() throws Exception { @@ -54,7 +53,6 @@ void testFlatProperties() throws Exception { ); } - @Test @DisplayName("Test Extractor with data structure map and array") void testEmbeddedTypes() throws Exception { diff --git a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java index c79a4169..844b2d75 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufConfluentExtractorTest.java @@ -1,9 +1,17 @@ package com.sngular.kloadgen.extractor.extractors.protobuf; +import java.io.File; +import java.util.List; +import java.util.Locale; + import com.sngular.kloadgen.extractor.extractors.Extractor; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; +import com.squareup.wire.schema.Location; +import com.squareup.wire.schema.internal.parser.ProtoFileElement; +import com.squareup.wire.schema.internal.parser.ProtoParser; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -13,15 +21,11 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.util.List; -import java.util.Locale; - class ProtobufConfluentExtractorTest { private final FileHelper fileHelper = new FileHelper(); - private final Extractor protoBufConfluentExtractor = new ProtoBufConfluentExtractor(); + private final Extractor> protoBufConfluentExtractor = new ProtoBufConfluentExtractor(); @BeforeEach public void setUp() { @@ -33,12 +37,11 @@ public void setUp() { JMeterUtils.setLocale(Locale.ENGLISH); } - @Test @DisplayName("Test Extractor with simple proto file") void testFlatProperties() throws Exception { final String testFile = fileHelper.getContent("/proto-files/easyTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -53,7 +56,7 @@ void testFlatProperties() throws Exception { @DisplayName("Test Extractor with data structure map and array") void testEmbeddedTypes() throws Exception { final String testFile = fileHelper.getContent("/proto-files/embeddedTypeTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(2) @@ -68,7 +71,7 @@ void testEmbeddedTypes() throws Exception { @DisplayName("Test Extractor with data structure enums and collections") void testEnumType() throws Exception { final String testFile = fileHelper.getContent("/proto-files/enumTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(3) @@ -86,7 +89,7 @@ void testEnumType() throws Exception { @DisplayName("Test Extractor with data structure Any of") void testOneOfsType() throws Exception { final String testFile = fileHelper.getContent("/proto-files/oneOfTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(4) @@ -106,7 +109,7 @@ void testOneOfsType() throws Exception { @DisplayName("Test Extractor with complex structure") void testComplexProto() throws Exception { final String testFile = fileHelper.getContent("/proto-files/complexTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(13) @@ -131,7 +134,7 @@ void testComplexProto() throws Exception { @DisplayName("Test Extractor with real proto") void testProvided() throws Exception { final String testFile = fileHelper.getContent("/proto-files/providedTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(32) @@ -175,7 +178,7 @@ void testProvided() throws Exception { @DisplayName("Test Extractor with data structure maps") void testMap() throws Exception { final String testFile = fileHelper.getContent("/proto-files/mapTest.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(7) @@ -194,7 +197,7 @@ void testMap() throws Exception { @DisplayName("Test Extractor with multi types") void completeTest() throws Exception { final String testFile = fileHelper.getContent("/proto-files/completeProto.proto"); - final ParsedSchema schema = new ParsedSchema(testFile, "PROTOBUF"); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); final List fieldValueMappingList = protoBufConfluentExtractor.processSchema(schema); Assertions.assertThat(fieldValueMappingList) .hasSize(11) diff --git a/src/test/java/com/sngular/kloadgen/loadgen/impl/AvroSRLoadGeneratorTest.java b/src/test/java/com/sngular/kloadgen/loadgen/impl/AvroSRLoadGeneratorTest.java index cff6bd0d..f9dc9730 100644 --- a/src/test/java/com/sngular/kloadgen/loadgen/impl/AvroSRLoadGeneratorTest.java +++ b/src/test/java/com/sngular/kloadgen/loadgen/impl/AvroSRLoadGeneratorTest.java @@ -21,7 +21,6 @@ import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; import com.sngular.kloadgen.schemaregistry.SchemaRegistryManagerFactory; import com.sngular.kloadgen.serializer.EnrichedRecord; -import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; @@ -34,8 +33,6 @@ @WireMockTest class AvroSRLoadGeneratorTest { - private final FileHelper fileHelper = new FileHelper(); - @BeforeEach public void setUp(final WireMockRuntimeInfo wmRuntimeInfo) throws IOException { final File file = new File("src/test/resources"); @@ -47,7 +44,7 @@ public void setUp(final WireMockRuntimeInfo wmRuntimeInfo) throws IOException { } @Test - void testAvroLoadGeneratorApicurio(final WireMockRuntimeInfo wmRuntimeInfo) throws KLoadGenException, IOException { + void testAvroLoadGeneratorApicurio(final WireMockRuntimeInfo wmRuntimeInfo) throws KLoadGenException { final List fieldValueMappingList = Arrays.asList( FieldValueMapping.builder().fieldName("Name").fieldType("string").valueLength(0).fieldValueList("Jose").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("Age").fieldType("int").valueLength(0).fieldValueList("43").required(true).isAncestorRequired(true).build()); @@ -67,11 +64,11 @@ void testAvroLoadGeneratorApicurio(final WireMockRuntimeInfo wmRuntimeInfo) thro } @Test - void testAvroLoadGeneratorConfluent(final WireMockRuntimeInfo wmRuntimeInfo) throws KLoadGenException, IOException { + void testAvroLoadGeneratorConfluent(final WireMockRuntimeInfo wmRuntimeInfo) throws KLoadGenException { final List fieldValueMappingList = Arrays.asList( - FieldValueMapping.builder().fieldName("Name").fieldType("string").valueLength(0).fieldValueList("Jose").required(true).isAncestorRequired(true).build(), - FieldValueMapping.builder().fieldName("Age").fieldType("int").valueLength(0).fieldValueList("43").required(true).isAncestorRequired(true).build()); + FieldValueMapping.builder().fieldName("Name").fieldType("string").valueLength(0).fieldValueList("Jose").required(true).isAncestorRequired(true).build(), + FieldValueMapping.builder().fieldName("Age").fieldType("int").valueLength(0).fieldValueList("43").required(true).isAncestorRequired(true).build()); final Map originals = new HashMap<>(); final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry("confluent"); diff --git a/src/test/java/com/sngular/kloadgen/loadgen/impl/ProtobufSRLoadGeneratorTest.java b/src/test/java/com/sngular/kloadgen/loadgen/impl/ProtobufSRLoadGeneratorTest.java index 55a2c7c5..40e1154a 100644 --- a/src/test/java/com/sngular/kloadgen/loadgen/impl/ProtobufSRLoadGeneratorTest.java +++ b/src/test/java/com/sngular/kloadgen/loadgen/impl/ProtobufSRLoadGeneratorTest.java @@ -20,7 +20,6 @@ import com.sngular.kloadgen.model.FieldValueMapping; import com.sngular.kloadgen.schemaregistry.SchemaRegistryManagerFactory; import com.sngular.kloadgen.serializer.EnrichedRecord; -import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.ProducerKeysHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; import io.confluent.kafka.schemaregistry.client.SchemaRegistryClientConfig; @@ -35,8 +34,6 @@ @WireMockTest class ProtobufSRLoadGeneratorTest { - private FileHelper fileHelper = new FileHelper(); - @BeforeEach public void setUp(final WireMockRuntimeInfo wmRuntimeInfo) throws IOException { final File file = new File("src/test/resources"); diff --git a/src/test/java/com/sngular/kloadgen/model/FieldValueMappingTest.java b/src/test/java/com/sngular/kloadgen/model/FieldValueMappingTest.java index 8215ae03..ece11c0f 100644 --- a/src/test/java/com/sngular/kloadgen/model/FieldValueMappingTest.java +++ b/src/test/java/com/sngular/kloadgen/model/FieldValueMappingTest.java @@ -19,15 +19,33 @@ class FieldValueMappingTest { @BeforeAll static void setUpTest() { fieldValueMapping = FieldValueMapping - .builder() - .fieldName("value") - .fieldType("String") - .valueLength(30) - .fieldValueList( - "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"\",\"action\":\"\"}]}]}," - + "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"\",\"action\":\"\"}]}]}") - .constraint(ConstraintTypeEnum.MAXIMUM_VALUE, "5") - .build(); + .builder() + .fieldName("value") + .fieldType("String") + .valueLength(30) + .fieldValueList( + """ + {"client_code":"ABC", + "market_codes":["popfa","popfa"], + "permissions":[ + {"app_code":"TEAA", + "resource_codes":[ + {"code":"", + "action":""}] + }] + }, + {"client_code":"ABC", + "market_codes":["popfa","popfa"], + "permissions":[ + {"app_code":"TEAA", + "resource_codes":[ + {"code":"", + "action":""} + ] + }] + }""") + .constraint(ConstraintTypeEnum.MAXIMUM_VALUE, "5") + .build(); } @Test @@ -50,17 +68,23 @@ void getFieldValuesList() { Assertions.assertThat(fieldValueMapping.getFieldValuesList()) .hasSize(2) .containsExactlyElementsOf(List.of( - "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"\",\"action\":\"\"}]}]}", - "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"\",\"action\":\"\"}]}]}")); + """ + {"client_code":"ABC","market_codes":["popfa","popfa"],"permissions":[{"app_code":"TEAA","resource_codes":[{"code":"","action":""}]}]}""", + """ + {"client_code":"ABC","market_codes":["popfa","popfa"],"permissions":[{"app_code":"TEAA","resource_codes":[{"code":"","action":""}]}]}""")); } @Test void getFieldValuesListSingleJson() { fieldValueMapping.setFieldValuesList( - "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"jj\",\"action\":\"kk\"}]}]}"); + """ + {"client_code":"ABC", + "market_codes":["popfa","popfa"], + "permissions":[{"app_code":"TEAA","resource_codes":[{"code":"jj","action":"kk"}]}]}"""); Assertions.assertThat(fieldValueMapping.getFieldValuesList()) .hasSize(1) .containsExactlyElementsOf(List.of( - "{\"client_code\":\"ABC\",\"market_codes\":[\"popfa\",\"popfa\"],\"permissions\":[{\"app_code\":\"TEAA\",\"resource_codes\":[{\"code\":\"jj\",\"action\":\"kk\"}]}]}")); + """ + {"client_code":"ABC","market_codes":["popfa","popfa"],"permissions":[{"app_code":"TEAA","resource_codes":[{"code":"jj","action":"kk"}]}]}""")); } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java b/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java index 84d17c9b..d9c0aab8 100644 --- a/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java +++ b/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java @@ -11,10 +11,10 @@ public class HeaderMappingTest { @BeforeAll static void setUpTest() { headerMapping = HeaderMapping - .builder() - .headerName("value") - .headerValue("String") - .build(); + .builder() + .headerName("value") + .headerValue("String") + .build(); } @Test diff --git a/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java b/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java index 18c4af37..393f97f7 100644 --- a/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java +++ b/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java @@ -5,15 +5,16 @@ import org.junit.jupiter.api.Test; public class PropertyMappingTest { + private static PropertyMapping propertyMapping; @BeforeAll static void setUpTest() { propertyMapping = PropertyMapping - .builder() - .propertyName("value") - .propertyValue("String") - .build(); + .builder() + .propertyName("value") + .propertyValue("String") + .build(); } @Test diff --git a/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java index d209a484..ef804513 100644 --- a/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/AvroSchemaProcessorTest.java @@ -6,10 +6,23 @@ package com.sngular.kloadgen.processor; +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.processor.fixture.AvroSchemaFixturesConstants; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; @@ -33,14 +46,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - class AvroSchemaProcessorTest { private final FileHelper fileHelper = new FileHelper(); @@ -76,7 +81,7 @@ void testAvroSchemaProcessorWithSubEntitySimpleArray() throws IOException { FieldValueMapping.builder().fieldName("topLevelIntArray[3]").fieldType("int-array").valueLength(0).fieldValueList("[2]").required(true).isAncestorRequired(true).build()); final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var parsedSchema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(testFile)); final SchemaProcessor avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final GenericRecord entity = setUpEntityForAvroTestWithSubEntitySimpleArray(parsedSchema); @@ -87,8 +92,8 @@ void testAvroSchemaProcessorWithSubEntitySimpleArray() throws IOException { Assertions.assertThat(message.getGenericRecord()).isEqualTo(entity); } - private GenericRecord setUpEntityForAvroTestWithSubEntitySimpleArray(final ParsedSchema parsedSchema) { - final var entity = new GenericData.Record((Schema) parsedSchema.rawSchema()); + private GenericRecord setUpEntityForAvroTestWithSubEntitySimpleArray(final AbstractParsedSchema parsedSchema) { + final var entity = new GenericData.Record((Schema) parsedSchema.getRawSchema()); final var subEntitySchema = entity.getSchema().getField("subEntity").schema(); final var subEntityRecord = new GenericData.Record(subEntitySchema); final var anotherLevelSchema = subEntitySchema.getField("anotherLevel").schema(); @@ -125,8 +130,8 @@ void testAvroSchemaProcessorWithSubEntityArray() throws IOException { .isAncestorRequired(true) .build()); - final var testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final var parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var testFile = fileHelper.getContent("/avro-files/avros-example-with-sub-entity-array-test.avsc"); + final var parsedSchema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(testFile)); final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var entity = setUpEntityForAvroTestWithSubEntityArray(parsedSchema); @@ -137,8 +142,8 @@ void testAvroSchemaProcessorWithSubEntityArray() throws IOException { Assertions.assertThat(message.getGenericRecord()).isEqualTo(entity); } - private GenericRecord setUpEntityForAvroTestWithSubEntityArray(final ParsedSchema parsedSchema) { - final var entity = new GenericData.Record((Schema) parsedSchema.rawSchema()); + private GenericRecord setUpEntityForAvroTestWithSubEntityArray(final AbstractParsedSchema parsedSchema) { + final var entity = new GenericData.Record((Schema) parsedSchema.getRawSchema()); final var subEntitySchema = entity.getSchema().getField("subEntity").schema(); final var subEntityRecord = new GenericData.Record(subEntitySchema); final var anotherLevelSchema = subEntitySchema.getField("anotherLevel").schema(); @@ -169,8 +174,8 @@ void testEmbeddedAvroSchemaProcessor() throws IOException { .build(), FieldValueMapping.builder().fieldName("timestamp").fieldType("long").valueLength(0).fieldValueList("5").required(true).isAncestorRequired(true).build() ); - final var testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); - final var parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var testFile = fileHelper.getContent("/avro-files/embedded-avros-example-test.avsc"); + final var parsedSchema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(testFile)); final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var message = (EnrichedRecord) avroSchemaProcessor.next(); @@ -181,11 +186,10 @@ void testEmbeddedAvroSchemaProcessor() throws IOException { Assertions.assertThat(message.getGenericRecord()).isEqualTo(entity); } - private GenericRecord setUpEntityForEmbeddedAvroTest(final ParsedSchema parsedSchema) { - GenericData.Record entity = null; //TODO HERE + private GenericRecord setUpEntityForEmbeddedAvroTest(final AbstractParsedSchema parsedSchema) { + GenericData.Record entity = null; - if (parsedSchema.rawSchema() instanceof Schema) { - final Schema schema = (Schema) parsedSchema.rawSchema(); + if (parsedSchema.getRawSchema() instanceof final Schema schema) { if (Schema.Type.UNION.equals(schema.getType())) { entity = new GenericData.Record(schema.getTypes().get(schema.getTypes().size() - 1)); } else { @@ -251,38 +255,38 @@ void textAvroSchemaProcessorArrayMap() throws KLoadGenException { final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, SchemaBuilder - .builder() - .record("arrayMap") - .fields() - .name("values") - .type() - .array() - .items() - .type(SchemaBuilder - .builder() - .map() - .values() - .stringType() - .getValueType()) - .noDefault() - .name("topLevelRecord") - .type() - .record("subvalues") - .fields() - .name("subvalues") - .type() - .array() - .items() - .type(SchemaBuilder - .builder() - .map() - .values() - .stringType() - .getValueType()) - .noDefault() - .endRecord() - .noDefault() - .endRecord(), + .builder() + .record("arrayMap") + .fields() + .name("values") + .type() + .array() + .items() + .type(SchemaBuilder + .builder() + .map() + .values() + .stringType() + .getValueType()) + .noDefault() + .name("topLevelRecord") + .type() + .record("subvalues") + .fields() + .name("subvalues") + .type() + .array() + .items() + .type(SchemaBuilder + .builder() + .map() + .values() + .stringType() + .getValueType()) + .noDefault() + .endRecord() + .noDefault() + .endRecord(), confluentBaseSchemaMetadata, fieldValueMappingList); @@ -299,8 +303,8 @@ void textAvroSchemaProcessorArrayMap() throws KLoadGenException { .hasSize(1); final List> valuesElement = (List>) ((GenericRecord) message.getGenericRecord()).get("values"); Assertions.assertThat(valuesElement).hasSize(2).containsExactlyInAnyOrder(Maps.of("n", "1", "t", "2"), Maps.of("n", "1", "t", "2")); - final List> subvaluesElement = (List>) ((GenericRecord) ((GenericRecord) message.getGenericRecord()).get("topLevelRecord")).get( - "subvalues"); + final List> subvaluesElement = (List>) ((GenericRecord) ((GenericRecord) message.getGenericRecord()).get("topLevelRecord")) + .get("subvalues"); Assertions.assertThat(subvaluesElement).hasSize(2).containsExactlyInAnyOrder(Maps.of("n", "1", "t", "2"), Maps.of("n", "1", "t", "2")); } @@ -313,22 +317,22 @@ void textAvroSchemaProcessorArrayRecord() throws KLoadGenException { final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, SchemaBuilder - .builder() - .record("array") - .fields() - .name("values") - .type() - .array() - .items() - .type(SchemaBuilder - .builder() - .record("test") - .fields() - .requiredString("name") - .requiredFloat("amount") - .endRecord()) - .noDefault() - .endRecord(), + .builder() + .record("array") + .fields() + .name("values") + .type() + .array() + .items() + .type(SchemaBuilder + .builder() + .record("test") + .fields() + .requiredString("name") + .requiredFloat("amount") + .endRecord()) + .noDefault() + .endRecord(), confluentBaseSchemaMetadata, fieldValueMappingList); @@ -353,21 +357,21 @@ void textAvroSchemaProcessorMap() throws KLoadGenException { final var avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, SchemaBuilder - .builder() - .record("arrayMap") - .fields() - .name("values") - .type() - .array() - .items() - .type(SchemaBuilder - .builder() - .map() - .values() - .stringType() - .getValueType()) - .noDefault() - .endRecord(), + .builder() + .record("arrayMap") + .fields() + .name("values") + .type() + .array() + .items() + .type(SchemaBuilder + .builder() + .map() + .values() + .stringType() + .getValueType()) + .noDefault() + .endRecord(), confluentBaseSchemaMetadata, fieldValueMappingList); @@ -389,10 +393,9 @@ void textAvroSchemaProcessorMap() throws KLoadGenException { @ParameterizedTest @MethodSource("parametersForTestNullOnOptionalField") void testNullOnOptionalField(final Schema schema, final List fieldValueMapping) { - final var metadata = confluentBaseSchemaMetadata; final var avroSchemaProcessor = new SchemaProcessor(); - avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, schema, metadata, fieldValueMapping); + avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, schema, confluentBaseSchemaMetadata, fieldValueMapping); final var message = (EnrichedRecord) avroSchemaProcessor.next(); Assertions.assertThat(message) @@ -403,7 +406,6 @@ void testNullOnOptionalField(final Schema schema, final List final var genericRecord = (GenericRecord) message.getGenericRecord(); Assertions.assertThat(genericRecord.get(0)).isNotNull(); Assertions.assertThat(genericRecord.get(1)).isNull(); - } @Test @@ -415,25 +417,25 @@ void testCustomSequenceOfValuesWithSameStartingValue() { final var avroSchemaProcessor = new SchemaProcessor(); final var schemaWithTwoSequencesWithSameStartingValue = SchemaBuilder - .builder() - .record("Root") - .fields() - .name("values") - .type() - .array() - .items() - .type(SchemaBuilder.builder() - .record("valuesData") - .fields() - .name("id") - .type(Schema.Type.STRING.getName()) - .noDefault() - .name("otherId") - .type(Schema.Type.LONG.getName()) - .noDefault() - .endRecord()) - .noDefault() - .endRecord(); + .builder() + .record("Root") + .fields() + .name("values") + .type() + .array() + .items() + .type(SchemaBuilder.builder() + .record("valuesData") + .fields() + .name("id") + .type(Schema.Type.STRING.getName()) + .noDefault() + .name("otherId") + .type(Schema.Type.LONG.getName()) + .noDefault() + .endRecord()) + .noDefault() + .endRecord(); final var entity = entityForCustomSequenceOfValuesWithSameStartingStartingValue(schemaWithTwoSequencesWithSameStartingValue, Arrays.asList("1", "2", "1"), Arrays.asList("1", "3", "1")); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, schemaWithTwoSequencesWithSameStartingValue, @@ -450,13 +452,13 @@ private GenericRecord entityForCustomSequenceOfValuesWithSameStartingStartingVal final var valuesSchema = entity.getSchema().getField("values").schema(); final var valuesDataSchema = valuesSchema.getElementType(); final var valuesData = IntStream - .range(0, Math.min(idValues.size(), otherIdValues.size())) - .mapToObj(idx -> { - final var valuesDataRecord = new GenericData.Record(valuesDataSchema); - valuesDataRecord.put("id", idValues.get(idx)); - valuesDataRecord.put("otherId", Long.valueOf(otherIdValues.get(idx))); - return valuesDataRecord; - }).collect(Collectors.toList()); + .range(0, Math.min(idValues.size(), otherIdValues.size())) + .mapToObj(idx -> { + final var valuesDataRecord = new GenericData.Record(valuesDataSchema); + valuesDataRecord.put("id", idValues.get(idx)); + valuesDataRecord.put("otherId", Long.valueOf(otherIdValues.get(idx))); + return valuesDataRecord; + }).collect(Collectors.toList()); entity.put("values", valuesData); return entity; @@ -473,34 +475,34 @@ void testCustomIteratorOfValuesWithSameFieldNameInDifferentMappings() { final var avroSchemaProcessor = new SchemaProcessor(); final var schemaWithTwoIteratorsWithSameStartingValue = SchemaBuilder - .builder() - .record("Root") - .fields() - .name("values") - .type() - .array() - .items() - .type(SchemaBuilder.builder() - .record("valuesData") - .fields() - .name("id") - .type(idSchema) - .noDefault() - .endRecord()) - .noDefault() - .name("otherValues") - .type() - .array() - .items() - .type(SchemaBuilder.builder() - .record("otherValuesData") - .fields() - .name("id") - .type(idSchema) - .noDefault() - .endRecord()) - .noDefault() - .endRecord(); + .builder() + .record("Root") + .fields() + .name("values") + .type() + .array() + .items() + .type(SchemaBuilder.builder() + .record("valuesData") + .fields() + .name("id") + .type(idSchema) + .noDefault() + .endRecord()) + .noDefault() + .name("otherValues") + .type() + .array() + .items() + .type(SchemaBuilder.builder() + .record("otherValuesData") + .fields() + .name("id") + .type(idSchema) + .noDefault() + .endRecord()) + .noDefault() + .endRecord(); final var entity = entityForCustomIteratorOfValuesWithSameFieldNameInDifferentMappings(schemaWithTwoIteratorsWithSameStartingValue, Arrays.asList("1", "2.44", "3.6", "1"), Arrays.asList("1", "3.02", "4.98", "1")); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, schemaWithTwoIteratorsWithSameStartingValue, @@ -532,7 +534,6 @@ private List getIdRecordsList(final GenericRecord entity, final S }).collect(Collectors.toList()); } - @Test @DisplayName("Should process Embedded Avro Schema Processor") void testEnumProcessor() throws IOException { @@ -548,12 +549,12 @@ void testEnumProcessor() throws IOException { .build() ); final File testFile = fileHelper.getFile("/avro-files/optionalEnum.avsc"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var parsedSchema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(testFile)); final SchemaProcessor avroSchemaProcessor = new SchemaProcessor(); avroSchemaProcessor.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final EnrichedRecord message = (EnrichedRecord) avroSchemaProcessor.next(); - final var entity = entityForEnumMappings((Schema) parsedSchema.rawSchema()); + final var entity = entityForEnumMappings(parsedSchema.getRawSchema()); Assertions.assertThat(message).isNotNull().isInstanceOf(EnrichedRecord.class); Assertions.assertThat(message.getGenericRecord()).isNotNull().isEqualTo(entity); } diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index 80f7f6c6..710b0b51 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -1,5 +1,10 @@ package com.sngular.kloadgen.processor; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; + import com.fasterxml.jackson.databind.node.ObjectNode; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; @@ -18,11 +23,6 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; -import java.io.File; -import java.util.List; -import java.util.Locale; -import java.util.stream.Stream; - public class JsonSchemaProcessorTest { private static Stream parametersForTestNullOnOptionalField() { @@ -68,7 +68,7 @@ final void testNullOnMapWithChildren() { final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); Assertions.assertThat(message.toString()).contains("lastName\":\"García") - .contains("itemTipo\":{").contains("itemType\":{"); + .contains("itemTipo\":{").contains("itemType\":{"); } @Test @@ -92,11 +92,11 @@ final void testNullOnComplexCollections() { final ObjectNode message = (ObjectNode) jsonSchemaProcessor.next(); Assertions.assertThat(message.toString()).contains("{\"fruits\":{\"tropical\":[]},\"vegetables\":{\"trees\":{}}") - .contains("\"birds\":[[{\"nameBird\":") - .contains("\"animals\":{").contains("nameAnimal\":"); + .contains("\"birds\":[[{\"nameBird\":") + .contains("\"animals\":{").contains("nameAnimal\":"); } - + @ParameterizedTest @MethodSource("parametersForTestBasicStructure") final void testBasicStructure(final List schemaAsJson, final String expected) { diff --git a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java index 1b6bdc31..fc834c54 100644 --- a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java @@ -1,12 +1,20 @@ package com.sngular.kloadgen.processor; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; + import com.google.protobuf.Descriptors; import com.google.protobuf.DynamicMessage; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.exception.KLoadGenException; import com.sngular.kloadgen.extractor.SchemaExtractor; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.schemaregistry.SchemaRegistryAdapter; import com.sngular.kloadgen.schemaregistry.SchemaRegistryManagerFactory; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; @@ -14,6 +22,8 @@ import com.sngular.kloadgen.serializer.EnrichedRecord; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import com.squareup.wire.schema.Location; +import com.squareup.wire.schema.internal.parser.ProtoParser; import org.apache.commons.collections.MapUtils; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; @@ -24,16 +34,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; -import java.util.*; - class ProtobufSchemaProcessorTest { private final FileHelper fileHelper = new FileHelper(); - private final SchemaExtractor schemaExtractor = new SchemaExtractor(); - private final BaseSchemaMetadata confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, ""))); @@ -52,14 +56,13 @@ public void setUp() { @Test @DisplayName("Be able to process embedded schema") void textEmbeddedTypeTestSchemaProcessor() throws KLoadGenException, IOException { - final File testFile = fileHelper.getFile("/proto-files/embeddedTypeTest.proto"); final List fieldValueMappingList = List.of( FieldValueMapping.builder().fieldName("phones.addressesPhone[1:].id[1]").fieldType("string-array").fieldValueList("Pablo").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("phones.phoneType").fieldType("enum").fieldValueList("[MOBILE, HOME, WORK]").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, readSchemaFile("/proto-files/embeddedTypeTest.proto"), + confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final Map map = genericRecord.getAllFields(); @@ -76,9 +79,14 @@ void textEmbeddedTypeTestSchemaProcessor() throws KLoadGenException, IOException Assertions.assertThat(idField).isEqualTo("[Pablo]"); } + private ProtobufParsedSchema readSchemaFile(final String fileToRead) throws IOException { + final String testFile = fileHelper.getContent(fileToRead); + return new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); + } + private String getIdFieldForEmbeddedTypeTest(final List assertValues) { final DynamicMessage dynamicMessage = (DynamicMessage) assertValues.get(0); - final DynamicMessage firstMap = (DynamicMessage) ((List) dynamicMessage.getField(dynamicMessage.getDescriptorForType().findFieldByName("addressesPhone"))).get(0); + final DynamicMessage firstMap = (DynamicMessage) ((List) dynamicMessage.getField(dynamicMessage.getDescriptorForType().findFieldByName("addressesPhone"))).get(0); final DynamicMessage secondMapAsDynamicField = (DynamicMessage) firstMap.getField(firstMap.getDescriptorForType().findFieldByName("value")); return secondMapAsDynamicField.getField(secondMapAsDynamicField.getDescriptorForType().findFieldByName("id")).toString(); } @@ -86,14 +94,13 @@ private String getIdFieldForEmbeddedTypeTest(final List assertValues) { @Test @DisplayName("Be able to process complex types like StringValue or Int32Value and get values by default") void testProtobufGoogleTypes() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/googleTypesTest.proto"); final List fieldValueMappingList = List.of( FieldValueMapping.builder().fieldName("id").fieldType("Int32Value").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("occurrence_id").fieldType("StringValue").fieldValueList("Isabel").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("load_number").fieldType("Int32Value").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, readSchemaFile("/proto-files/googleTypesTest.proto"), + confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final Map map = genericRecord.getAllFields(); @@ -116,12 +123,11 @@ void testProtobufGoogleTypes() throws IOException { @Test @DisplayName("Be able to process enum in the schema") void testProtoBufEnumSchemaProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/enumTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); + final var parsedSchema = readSchemaFile("/proto-files/enumTest.proto"); + final List fieldValueMappingList = SchemaExtractor.flatPropertiesList(readSchemaFile("/proto-files/enumTest.proto")); fieldValueMappingList.get(0).setFieldValuesList("HOME, WORK"); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final Map map = genericRecord.getAllFields(); @@ -132,8 +138,8 @@ void testProtoBufEnumSchemaProcessor() throws IOException { assertValues.add(value); }); final String firstValue = assertValues.get(0).toString(); - final List secondValue = (List) assertValues.get(1); - final List thirdValueMap = (List) assertValues.get(2); + final var secondValue = (List) assertValues.get(1); + final var thirdValueMap = (List) assertValues.get(2); final DynamicMessage dynamicMessage = (DynamicMessage) thirdValueMap.get(0); final Object thirdValue = dynamicMessage.getField(dynamicMessage.getDescriptorForType().findFieldByName("value")); Assertions.assertThat(message).isNotNull().isInstanceOf(EnrichedRecord.class); @@ -155,11 +161,10 @@ void testProtoBufEnumSchemaProcessor() throws IOException { @Test @DisplayName("Be able to process easy schema") void testProtoBufEasyTestProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); + final var parsedSchema = readSchemaFile("/proto-files/easyTest.proto"); + final List fieldValueMappingList = SchemaExtractor.flatPropertiesList(parsedSchema); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -185,12 +190,11 @@ void testProtoBufEasyTestProcessor() throws IOException { @Test @DisplayName("Be able to process oneOf fields") void testProtoBufOneOfProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/oneOfTest.proto"); + final var parsedSchema = readSchemaFile("/proto-files/oneOfTest.proto"); - final List fieldValueMappingList = schemaExtractor.flatPropertiesList(new ParsedSchema(testFile, "PROTOBUF")); + final List fieldValueMappingList = SchemaExtractor.flatPropertiesList(parsedSchema); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -208,6 +212,7 @@ void testProtoBufOneOfProcessor() throws IOException { .hasSize(2) .containsAnyOf("tutorial.Address.type", "tutorial.Address.optionInt", "tutorial.Address.optionLong", "tutorial.Address.optionString") .element(0) + .isInstanceOf(String.class) .isEqualTo("tutorial.Address.type"); Assertions.assertThat(assertValues).hasSize(2); @@ -216,7 +221,7 @@ void testProtoBufOneOfProcessor() throws IOException { @Test @DisplayName("Be able to process map in schema") void testProtoBufMapTestProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/mapTest.proto"); + final var testFile = readSchemaFile("/proto-files/mapTest.proto"); final List fieldValueMappingList = Arrays.asList( FieldValueMapping.builder().fieldName("name[:]").fieldType("string-map").fieldValueList("Pablo").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("addresses[:].street").fieldType("string").fieldValueList("Sor Joaquina").required(true).isAncestorRequired(true).build(), @@ -226,8 +231,7 @@ void testProtoBufMapTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("addressesNoDot[:].number").fieldType("int").fieldValueList("6").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("addressesNoDot[:].zipcode").fieldType("int").fieldValueList("15011").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, testFile, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -272,7 +276,7 @@ private Object getSubFieldForMapTestProcessor(final DynamicMessage dynamicMessag @Test @DisplayName("Be able to process complex schema") void testProtoBufComplexTestProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/complexTest.proto"); + final var testFile = fileHelper.getContent("/proto-files/complexTest.proto"); final SchemaRegistryAdapter schemaRegistryManager = SchemaRegistryManagerFactory.getSchemaRegistry("CONFLUENT"); schemaRegistryManager.setSchemaRegistryClient("http://localhost:8080", MapUtils.EMPTY_MAP); @@ -291,8 +295,9 @@ void testProtoBufComplexTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("response").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("presents[:].options[]").fieldType("string-array").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), - confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, + new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()), + confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -325,7 +330,7 @@ void testProtoBufComplexTestProcessor() throws IOException { @Test @DisplayName("Be able to process provided complex schema") void testProtoBufProvidedComplexTestProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/providedTest.proto"); + final var testFile = readSchemaFile("/proto-files/providedTest.proto"); final List fieldValueMappingList = Arrays.asList( FieldValueMapping.builder().fieldName("id").fieldType("int").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("occurrence_id").fieldType("string").required(true).isAncestorRequired(true).build(), @@ -360,8 +365,7 @@ void testProtoBufProvidedComplexTestProcessor() throws IOException { FieldValueMapping.builder().fieldName("report_by_name").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("create_user_id").fieldType("string").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, new ParsedSchema(testFile, - SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, testFile, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -406,7 +410,7 @@ void testProtoBufProvidedComplexTestProcessor() throws IOException { @Test void testFailing() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/deveTest.proto"); + final var testFile = readSchemaFile("/proto-files/deveTest.proto"); final List fieldValueMappingList = Arrays.asList( FieldValueMapping.builder().fieldName("load_type").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("shipment.carrier_identifier.type").fieldType("enum") @@ -467,8 +471,7 @@ void testFailing() throws IOException { ); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, testFile, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -491,7 +494,7 @@ void testFailing() throws IOException { @Test @DisplayName("Be able to process provided schema with not nested type") void testProtoBufProvidedWithNotNestedTypeProcessor() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/issue311Test.proto"); + final var testFile = readSchemaFile("/proto-files/issue311Test.proto"); final List fieldValueMappingList = Arrays.asList( FieldValueMapping.builder().fieldName("order_id").fieldType("int").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("order_number").fieldType("string").required(true).isAncestorRequired(true).build(), @@ -499,8 +502,7 @@ void testProtoBufProvidedWithNotNestedTypeProcessor() throws IOException { FieldValueMapping.builder().fieldName("customer_account.billing_party.address.address_line_one").fieldType("string").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("customer_account.billing_party.address.address_line_two").fieldType("string").required(true).isAncestorRequired(true).build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, testFile, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final List assertKeys = new ArrayList<>(); @@ -527,14 +529,13 @@ void testProtoBufProvidedWithNotNestedTypeProcessor() throws IOException { @Test @DisplayName("Be able to process Date and TimeOfDay types") void testDateTimeTypes() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/dateTimeTest.proto"); + final var testFile = readSchemaFile("/proto-files/dateTimeTest.proto"); final List fieldValueMappingList = List.of( FieldValueMapping.builder().fieldName("incident_date").fieldType(".google.type.Date").fieldValueList("2022-05-30").required(true).isAncestorRequired(true).build(), FieldValueMapping.builder().fieldName("incident_time").fieldType(".google.type.TimeOfDay").fieldValueList("14:20:30-05:00").required(true).isAncestorRequired(true) .build()); final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, - new ParsedSchema(testFile, SchemaTypeEnum.PROTOBUF.name()), confluentBaseSchemaMetadata, fieldValueMappingList); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, testFile, confluentBaseSchemaMetadata, fieldValueMappingList); final EnrichedRecord message = (EnrichedRecord) protobufSchemaProcessor.next(); final DynamicMessage genericRecord = (DynamicMessage) message.getGenericRecord(); final Map map = genericRecord.getAllFields(); diff --git a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java index 0bf29801..829c59ad 100644 --- a/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java +++ b/src/test/java/com/sngular/kloadgen/processor/fixture/JsonSchemaFixturesConstants.java @@ -11,61 +11,64 @@ public class JsonSchemaFixturesConstants { - public static final List SIMPLE_SCHEMA = new ArrayList(Arrays.asList( - FieldValueMapping.builder() - .fieldName("firstName") - .fieldType("string") - .valueLength(0) - .fieldValueList("null") - .required(false) - .isAncestorRequired(false) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("lastName") - .fieldType("string") - .valueLength(0) - .fieldValueList("García") - .required(true) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("age") - .fieldType("number") - .valueLength(0) - .fieldValueList("null") - .required(false) - .constraints(Collections.emptyMap()) - .build() + public static final List SIMPLE_SCHEMA = new ArrayList<>(Arrays.asList( + FieldValueMapping.builder() + .fieldName("firstName") + .fieldType("string") + .valueLength(0) + .fieldValueList("null") + .required(false) + .isAncestorRequired(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("lastName") + .fieldType("string") + .valueLength(0) + .fieldValueList("García") + .required(true) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("age") + .fieldType("number") + .valueLength(0) + .fieldValueList("null") + .required(false) + .constraints(Collections.emptyMap()) + .build() )); + public static final String SIMPLE_SCHEMA_EXPECTED = "{\"lastName\":\"García\"}"; - public static final List SIMPLE_SCHEMA_NONREQUIRED = new ArrayList(Arrays.asList( - FieldValueMapping.builder() - .fieldName("firstName") - .fieldType("string") - .valueLength(0) - .fieldValueList("Graciela") - .required(false) - .isAncestorRequired(false) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("lastName") - .fieldType("string") - .valueLength(0) - .fieldValueList("null") - .required(false) - .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) - .build(), - FieldValueMapping.builder() - .fieldName("age") - .fieldType("number") - .valueLength(0) - .fieldValueList("21") - .required(false) - .constraints(Collections.emptyMap()) - .build() + + public static final List SIMPLE_SCHEMA_NONREQUIRED = new ArrayList<>(Arrays.asList( + FieldValueMapping.builder() + .fieldName("firstName") + .fieldType("string") + .valueLength(0) + .fieldValueList("Graciela") + .required(false) + .isAncestorRequired(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("lastName") + .fieldType("string") + .valueLength(0) + .fieldValueList("null") + .required(false) + .constraints(Map.of(ConstraintTypeEnum.MINIMUM_VALUE, "0", ConstraintTypeEnum.MAXIMUM_VALUE, "0")) + .build(), + FieldValueMapping.builder() + .fieldName("age") + .fieldType("number") + .valueLength(0) + .fieldValueList("21") + .required(false) + .constraints(Collections.emptyMap()) + .build() )); + public static final String SIMPLE_SCHEMA_NONREQUIRED_EXPECTED = "{\"firstName\":\"Graciela\",\"age\":21.0}"; public static final List SIMPLE_SCHEMA_MAP = new ArrayList<>(Arrays.asList( @@ -190,7 +193,7 @@ public class JsonSchemaFixturesConstants { .build() )); - public static final List SIMPLE_SCHEMA_REQUIRED = new ArrayList(Arrays.asList( + public static final List SIMPLE_SCHEMA_REQUIRED = new ArrayList<>(Arrays.asList( FieldValueMapping.builder() .fieldName("firstName") .fieldType("string") diff --git a/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java b/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java index b8e8fb3c..1125a057 100644 --- a/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java +++ b/src/test/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditorTest.java @@ -6,17 +6,18 @@ package com.sngular.kloadgen.property.editor; +import java.io.File; +import java.io.IOException; +import java.util.List; + import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.testutil.FileHelper; +import org.apache.avro.Schema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; -import java.util.List; - class FileSubjectPropertyEditorTest { private final FileHelper fileHelper = new FileHelper(); @@ -27,7 +28,7 @@ class FileSubjectPropertyEditorTest { @DisplayName("File Subject Property Editor extract AVRO") void extractEmbeddedAvroTest() throws IOException { final File testFile = fileHelper.getFile("/avro-files/embedded-avros-example-test.avsc"); - final ParsedSchema schema = new ParsedSchema(testFile, "AVRO"); + final var schema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(testFile)); final List fieldValueMappingList = editor.getAttributeList(schema); Assertions.assertThat(fieldValueMappingList) diff --git a/src/test/java/com/sngular/kloadgen/property/editor/SerialisedSubjectPropertyEditorTest.java b/src/test/java/com/sngular/kloadgen/property/editor/SerialisedSubjectPropertyEditorTest.java index 5639d4cd..a41b9f54 100644 --- a/src/test/java/com/sngular/kloadgen/property/editor/SerialisedSubjectPropertyEditorTest.java +++ b/src/test/java/com/sngular/kloadgen/property/editor/SerialisedSubjectPropertyEditorTest.java @@ -82,7 +82,7 @@ public void setUp() { void iterationStart() { final var valueSerializedConfigElement = new ValueSerializedConfigElement("avroSubject", Collections.emptyList(), "AVRO", - AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); + AvroSerializer.class.getSimpleName(), TopicNameStrategy.class.getSimpleName()); final var variables = JMeterContextService.getContext().getVariables(); valueSerializedConfigElement.iterationStart(null); diff --git a/src/test/java/com/sngular/kloadgen/randomtool/generator/AvroGeneratorToolTest.java b/src/test/java/com/sngular/kloadgen/randomtool/generator/AvroGeneratorToolTest.java index 2fc68b21..a6a1b0e0 100644 --- a/src/test/java/com/sngular/kloadgen/randomtool/generator/AvroGeneratorToolTest.java +++ b/src/test/java/com/sngular/kloadgen/randomtool/generator/AvroGeneratorToolTest.java @@ -38,10 +38,15 @@ class AvroGeneratorToolTest { private static final LocalDateTime FIXED_TIMESTAMP = LocalDateTime.of(2019, 12, 6, 10, 15, 30); + private static final LocalDate FIXED_DATE = LocalDate.of(2019, 12, 6); + private static final LocalTime FIXED_TIME = LocalTime.of(10, 15, 30); + private static final String TIMESTAMP_STRING = "2019-12-06T10:15:30"; + private static final String DATE_STRING = "2019-12-06"; + private static final String TIME_STRING = "10:15:30"; private static Stream parametersForGenerateRandomValueForField() { @@ -109,38 +114,6 @@ private static Stream parametersForGenerateRandomValueForFieldLogical ); } - @ParameterizedTest - @DisplayName("Testing Random Value for Field") - @MethodSource("parametersForGenerateRandomValueForField") - void testGenerateRandomValueForField(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, final Object expected) { - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList(String.join(",", fieldValuesList)) - .required(true) - .isAncestorRequired(true) - .build(); - Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).isEqualTo(expected); - } - - @ParameterizedTest - @DisplayName("Testing Random Value for Field with Logical Types") - @MethodSource("parametersForGenerateRandomValueForFieldLogicalTypes") - void testGenerateRandomValueForFieldLogicalTypes(final String fieldType, final Integer valueLength, final List fieldValuesList, - final Field field, final Object expected, - final Map constraints) { - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList(String.join(",", fieldValuesList)) - .required(true) - .isAncestorRequired(true) - .build(); - Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, constraints)).isEqualTo(expected); - } - private static Stream parametersForGenerateRandomValue() { return Stream.of( Arguments.of("int", 5, Collections.emptyList(), new Field("name", SchemaBuilder.builder().intType())), @@ -149,24 +122,6 @@ private static Stream parametersForGenerateRandomValue() { Arguments.of("double", 6, Collections.emptyList(), new Field("name", SchemaBuilder.builder().doubleType()))); } - @Disabled("Test failure sometimes") - @ParameterizedTest - @DisplayName("Testing Generate a Random Value") - @MethodSource("parametersForGenerateRandomValue") - void testGenerateRandomValue(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field) { - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList(String.join(",", fieldValuesList)) - .required(true) - .isAncestorRequired(true) - .build(); - final Object number = new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap()); - Assertions.assertThat(number).isInstanceOfAny(Long.class, Integer.class, Double.class, Float.class); - Assertions.assertThat(String.valueOf(number)).hasSize(valueLength); - } - private static Stream parametersForGenerateFieldValuesListIterator() { return Stream.of( Arguments.of(18, @@ -183,47 +138,12 @@ private static Stream parametersForGenerateFieldValuesListIterator() List.of("first", "second", "third", "first", "second"))); } - @ParameterizedTest - @DisplayName("Testing generate an iterator of a list of values") - @MethodSource("parametersForGenerateFieldValuesListIterator") - void testGenerateFieldValuesListSequence(final int size, final List fieldValuesList, final String fieldType, final List expected) { - final var intList = new ArrayList<>(); - final Schema schema = fieldType.equals(ValidTypeConstants.INT) ? SchemaBuilder.builder().intType() : SchemaBuilder.builder().stringType(); - final Field field = new Field("name", schema); - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType("it") - .valueLength(0) - .fieldValueList(String.join(",", fieldValuesList)) - .build(); - final var avroGeneratorTool = new AvroGeneratorTool(); - for (int i = 0; i <= size; i++) { - intList.add(avroGeneratorTool.generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())); - } - Assertions.assertThat(intList).containsExactlyElementsOf(expected); - } - private static Stream parametersForGenerateRandomValueForEnums() { return Stream.of( Arguments.of("enum", 1, Collections.singletonList("RED"), new Field("name", SchemaBuilder.builder().enumeration("ENUM1").symbols("RED", "BLUE", "GREEN")), "RED")); } - @ParameterizedTest - @DisplayName("Testing Generate a Random Value for Enums") - @MethodSource("parametersForGenerateRandomValueForEnums") - void testGenerateRandomValueForEnums(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, final Object expected) { - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList(String.join(",", fieldValuesList)) - .required(true) - .isAncestorRequired(true) - .build(); - Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).hasFieldOrPropertyWithValue("symbol", expected); - } - private static Stream parametersForGenerateSequenceValueForField() { return Stream.of( Arguments.of("seq", 1, Collections.singletonList("0"), new Field("name", SchemaBuilder.builder().intType()), 0), @@ -234,22 +154,6 @@ private static Stream parametersForGenerateSequenceValueForField() { Arguments.of("it", 1, Collections.singletonList("2"), new Field("name", SchemaBuilder.builder().intType()), 2)); } - @ParameterizedTest - @DisplayName("Testing Generate a Random Value for Field") - @MethodSource("parametersForGenerateSequenceValueForField") - void testGenerateSequenceValueForField(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, - final Object expectedTyped) { - final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList(String.join(",", fieldValuesList)) - .required(true) - .isAncestorRequired(true) - .build(); - Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).isEqualTo(expectedTyped); - } - private static Stream parametersForShouldRecoverVariableFromContext() { return Stream.of( Arguments.of("string", 1, "testString", new Field("name", SchemaBuilder.builder().stringType()), "testString"), @@ -301,6 +205,109 @@ private static Stream parametersForShouldRecoverVariableFromContextLo ); } + @ParameterizedTest + @DisplayName("Testing Random Value for Field") + @MethodSource("parametersForGenerateRandomValueForField") + void testGenerateRandomValueForField(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, final Object expected) { + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList(String.join(",", fieldValuesList)) + .required(true) + .isAncestorRequired(true) + .build(); + Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).isEqualTo(expected); + } + + @ParameterizedTest + @DisplayName("Testing Random Value for Field with Logical Types") + @MethodSource("parametersForGenerateRandomValueForFieldLogicalTypes") + void testGenerateRandomValueForFieldLogicalTypes( + final String fieldType, final Integer valueLength, final List fieldValuesList, + final Field field, final Object expected, + final Map constraints) { + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList(String.join(",", fieldValuesList)) + .required(true) + .isAncestorRequired(true) + .build(); + Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, constraints)).isEqualTo(expected); + } + + @Disabled("Test failure sometimes") + @ParameterizedTest + @DisplayName("Testing Generate a Random Value") + @MethodSource("parametersForGenerateRandomValue") + void testGenerateRandomValue(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field) { + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList(String.join(",", fieldValuesList)) + .required(true) + .isAncestorRequired(true) + .build(); + final Object number = new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap()); + Assertions.assertThat(number).isInstanceOfAny(Long.class, Integer.class, Double.class, Float.class); + Assertions.assertThat(String.valueOf(number)).hasSize(valueLength); + } + + @ParameterizedTest + @DisplayName("Testing generate an iterator of a list of values") + @MethodSource("parametersForGenerateFieldValuesListIterator") + void testGenerateFieldValuesListSequence(final int size, final List fieldValuesList, final String fieldType, final List expected) { + final var intList = new ArrayList<>(); + final Schema schema = fieldType.equals(ValidTypeConstants.INT) ? SchemaBuilder.builder().intType() : SchemaBuilder.builder().stringType(); + final Field field = new Field("name", schema); + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType("it") + .valueLength(0) + .fieldValueList(String.join(",", fieldValuesList)) + .build(); + final var avroGeneratorTool = new AvroGeneratorTool(); + for (int i = 0; i <= size; i++) { + intList.add(avroGeneratorTool.generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())); + } + Assertions.assertThat(intList).containsExactlyElementsOf(expected); + } + + @ParameterizedTest + @DisplayName("Testing Generate a Random Value for Enums") + @MethodSource("parametersForGenerateRandomValueForEnums") + void testGenerateRandomValueForEnums(final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, final Object expected) { + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList(String.join(",", fieldValuesList)) + .required(true) + .isAncestorRequired(true) + .build(); + Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).hasFieldOrPropertyWithValue("symbol", expected); + } + + @ParameterizedTest + @DisplayName("Testing Generate a Random Value for Field") + @MethodSource("parametersForGenerateSequenceValueForField") + void testGenerateSequenceValueForField( + final String fieldType, final Integer valueLength, final List fieldValuesList, final Field field, + final Object expectedTyped) { + final var fieldValueMapping = FieldValueMapping.builder() + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList(String.join(",", fieldValuesList)) + .required(true) + .isAncestorRequired(true) + .build(); + Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).isEqualTo(expectedTyped); + } + @ParameterizedTest @DisplayName("Testing Recover Variable from Context") @MethodSource("parametersForShouldRecoverVariableFromContext") @@ -309,32 +316,33 @@ void shouldRecoverVariableFromContext(final String fieldType, final Integer valu variables.put("VARIABLE", value); JMeterContextService.getContext().setVariables(variables); final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList("${VARIABLE}") - .required(true) - .isAncestorRequired(true) - .build(); + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList("${VARIABLE}") + .required(true) + .isAncestorRequired(true) + .build(); Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, Collections.emptyMap())).isEqualTo(expected); } @ParameterizedTest @DisplayName("Testing Recover Variable from Context Logical Types") @MethodSource("parametersForShouldRecoverVariableFromContextLogicalTypes") - void shouldRecoverVariableFromContext(final String fieldType, final Integer valueLength, final String value, final Field field, + void shouldRecoverVariableFromContext( + final String fieldType, final Integer valueLength, final String value, final Field field, final Object expected, final Map constraints) { final var variables = new JMeterVariables(); variables.put("VARIABLE", value); JMeterContextService.getContext().setVariables(variables); final var fieldValueMapping = FieldValueMapping.builder() - .fieldName(field.name()) - .fieldType(fieldType) - .valueLength(valueLength) - .fieldValueList("${VARIABLE}") - .required(true) - .isAncestorRequired(true) - .build(); + .fieldName(field.name()) + .fieldType(fieldType) + .valueLength(valueLength) + .fieldValueList("${VARIABLE}") + .required(true) + .isAncestorRequired(true) + .build(); Assertions.assertThat(new AvroGeneratorTool().generateObject(field.schema(), fieldValueMapping, constraints)).isEqualTo(expected); } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomIteratorTest.java b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomIteratorTest.java index d9261475..596a8399 100644 --- a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomIteratorTest.java +++ b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomIteratorTest.java @@ -26,17 +26,28 @@ class RandomIteratorTest { private static Stream parametersForGenerateIteratorValueForField() { return Stream.of( - Arguments.of("name", "int", Collections.emptyList(), new HashMap<>(), null), - Arguments.of("name", "float", Collections.singletonList("1"), new HashMap<>(), 1f), - Arguments.of("name", "long", Collections.singletonList("2"), new HashMap<>(), 2L), - Arguments.of("name", "bytes_decimal", Collections.singletonList("1"), new HashMap<>(Maps.of("name", new BigDecimal("15"))), new BigDecimal("1")), - Arguments.of("name15", "bytes_decimal", Collections.emptyList(), new HashMap<>(Maps.of("name15", new BigDecimal("15"))), null)); + Arguments.of("name", "int", Collections.emptyList(), new HashMap<>(), null), + Arguments.of("name", "float", Collections.singletonList("1"), new HashMap<>(), 1f), + Arguments.of("name", "long", Collections.singletonList("2"), new HashMap<>(), 2L), + Arguments.of("name", "bytes_decimal", Collections.singletonList("1"), new HashMap<>(Maps.of("name", new BigDecimal("15"))), new BigDecimal("1")), + Arguments.of("name15", "bytes_decimal", Collections.emptyList(), new HashMap<>(Maps.of("name15", new BigDecimal("15"))), null)); + } + + private static Stream parametersForGenerateValueWithList() { + return Stream.of( + Arguments.of(10, + List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10"), + List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10")), + Arguments.of(12, + List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10"), + List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10", "1", "2"))); } @ParameterizedTest @DisplayName("Testing Generate an Iterator With an empty list or a list with one value") @MethodSource("parametersForGenerateIteratorValueForField") - void testGenerateIteratorValueForField(final String fieldName, final String fieldType, final List fieldValuesList, final Map context, + void testGenerateIteratorValueForField( + final String fieldName, final String fieldType, final List fieldValuesList, final Map context, final Object expectedStored) { Assertions.assertThat(RandomIterator.generateIt(fieldName, fieldType, fieldValuesList, context)).isEqualTo(expectedStored); if (Objects.isNull(expectedStored)) { @@ -46,16 +57,6 @@ void testGenerateIteratorValueForField(final String fieldName, final String fiel } } - private static Stream parametersForGenerateValueWithList() { - return Stream.of( - Arguments.of(10, - List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10"), - List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10")), - Arguments.of(12, - List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10"), - List.of("1", "2", "3", "5", "6", "7", "7", "9", "9", "9", "10", "1", "2"))); - } - @ParameterizedTest @DisplayName("Testing Generate an Iterator With a List of Values") @MethodSource("parametersForGenerateValueWithList") diff --git a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java index cc78b1c0..0f20d957 100644 --- a/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java +++ b/src/test/java/com/sngular/kloadgen/randomtool/random/RandomMapTest.java @@ -29,7 +29,7 @@ private static Stream parametersForGenerateMapRandomValueFromList() { Arguments.of("short-map", 1, Collections.singletonList("testString:1"), Maps.of("testString", (short) 1), 1), Arguments.of("double-map", 1, Collections.singletonList("testString:1.0"), Maps.of("testString", 1.0), 1), Arguments.of("uuid-map", 1, Collections.singletonList("testString:0177f035-e51c-4a46-8b82-5b157371c2a5"), - Maps.of("testString", UUID.fromString("0177f035-e51c-4a46-8b82-5b157371c2a5")), 1 + Maps.of("testString", UUID.fromString("0177f035-e51c-4a46-8b82-5b157371c2a5")), 1 ) ); } @@ -38,7 +38,7 @@ private static Stream parametersForGenerateMapArrayRandomValueFromLis //The name of this type is due to: SchemaProcessorUtils.getOneDimensionValueType (this remove the last -map) return Stream.of(Arguments.of("string-array", 5, List.of("key1:[value1,value2,value3]", "key2:[valueB1,valueB2]"), - Map.of("key1", List.of("value1", "value2", "value3"), "key2", List.of("valueB1", "valueB2")), 1) + Map.of("key1", List.of("value1", "value2", "value3"), "key2", List.of("valueB1", "valueB2")), 1) ); } @@ -57,7 +57,7 @@ private static Stream parametersForGenerateMapFixedKeyRandomValue() { @MethodSource("parametersForGenerateMapRandomValueFromList") void generateMapRandomValueFromList( final String fieldType, final Integer valueLength, final List fieldValuesList, final Map expected, final Integer size) { - final Entry[] expectedMap = expected.entrySet().toArray(new Entry[1]); + final Entry[] expectedMap = expected.entrySet().toArray(new Entry[1]); final Map result = (Map) new RandomMap().generateMap(fieldType, valueLength, fieldValuesList, size, Collections.emptyMap()); Assertions.assertThat(result).containsExactly(expectedMap); diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index f121daf1..235f24dd 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -1,7 +1,12 @@ package com.sngular.kloadgen.sampler; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.stream.Stream; + import com.sngular.kloadgen.extractor.ApiExtractor; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.ProducerKeysHelper; @@ -11,68 +16,62 @@ import org.apache.jmeter.threads.JMeterVariables; import org.apache.jmeter.util.JMeterUtils; import org.junit.jupiter.api.BeforeEach; - -import java.io.File; -import java.io.IOException; -import java.util.Locale; -import java.util.stream.Stream; - -import static org.mockito.Mockito.mock; +import org.mockito.Mockito; class AsyncApiSamplerTest { - private final FileHelper fileHelper = new FileHelper(); - private JMeterContext jmcx; + private final FileHelper fileHelper = new FileHelper(); - private static Stream parametersForConfigureValueGeneratorTest() { - return Stream.of("localhost:8081", ""); - } + private JMeterContext jmcx; - private AsyncApiSampler sampler = new AsyncApiSampler(); + private AsyncApiSampler sampler = new AsyncApiSampler(); - private ApiExtractor apiExtractor; - @BeforeEach - public final void setUp() throws IOException { - final File file = new File("src/test/resources"); - final String absolutePath = file.getAbsolutePath(); - JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); - jmcx = JMeterContextService.getContext(); - jmcx.setVariables(new JMeterVariables()); - JMeterUtils.setLocale(Locale.ENGLISH); - sampler = new AsyncApiSampler(); - apiExtractor = mock(ApiExtractor.class); + private ApiExtractor apiExtractor; - } + private static Stream parametersForConfigureValueGeneratorTest() { + return Stream.of("localhost:8081", ""); + } - /*@Test - void testAsyncApiSampleBasic() throws IOException { - JsonNode asyncApiFileNode = mock(JsonNode.class); - sampler.setAsyncApiFileNode(asyncApiFileNode); - JMeterVariables jmvar = new JMeterVariables(); - jmvar.putAll(getVariablesJsonSchema()); + @BeforeEach + public final void setUp() throws IOException { + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + sampler = new AsyncApiSampler(); + apiExtractor = Mockito.mock(ApiExtractor.class); + } + /*@Test + void testAsyncApiSampleBasic() throws IOException { + JsonNode asyncApiFileNode = mock(JsonNode.class); + sampler.setAsyncApiFileNode(asyncApiFileNode); + JMeterVariables jmvar = new JMeterVariables(); + jmvar.putAll(getVariablesJsonSchema()); - }*/ - public JMeterVariables getVariablesJsonSchema() throws IOException { + }*/ - final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "JSON"); + public JMeterVariables getVariablesJsonSchema() throws IOException { - final var variables = new JMeterVariables(); - variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); - variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); - variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED); - variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); - return variables; - } + final var testFile = fileHelper.getContent("/asyncapi/event-api.yml"); + final var parsedSchema = new JsonParsedSchema("test", testFile); + final var variables = new JMeterVariables(); + variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); + variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); + variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED); + variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); + return variables; + } } \ No newline at end of file diff --git a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java index 69662413..be6377c3 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/SamplerUtilTest.java @@ -6,8 +6,14 @@ package com.sngular.kloadgen.sampler; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Locale; +import java.util.Properties; +import java.util.stream.Stream; + import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; import com.sngular.kloadgen.serializer.SerializerTestFixture; import com.sngular.kloadgen.testutil.FileHelper; @@ -23,13 +29,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Locale; -import java.util.Properties; -import java.util.stream.Stream; - class SamplerUtilTest { private final FileHelper fileHelper = new FileHelper(); @@ -65,15 +64,14 @@ void configureValueGeneratorTest(final String jmeterProps) throws IOException { } public JMeterVariables getVariablesAvro() throws IOException { - final File testFile = fileHelper.getFile("/avro-files/avros-example-with-sub-entity-array-test.avsc"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "AVRO"); + final var testFile = fileHelper.getContent("/avro-files/avros-example-with-sub-entity-array-test.avsc"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "avro"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "test"); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "test"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.rawSchema())); + variables.put(PropsKeysHelper.VALUE_SCHEMA, testFile); variables.put(PropsKeysHelper.VALUE_SCHEMA_TYPE, "avro"); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.rawSchema())); + variables.put(PropsKeysHelper.KEY_SCHEMA, testFile); variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, Arrays.asList( FieldValueMapping.builder().fieldName("subEntity.anotherLevel.subEntityIntArray[2]").fieldType("int-array").valueLength(0).fieldValueList("[1]").required(true) .isAncestorRequired(true).build(), @@ -107,15 +105,14 @@ void configureKeyGeneratorTest(final String jmeterProps) throws IOException { public JMeterVariables getVariablesJsonSchema() throws IOException { - final File testFile = fileHelper.getFile("/jsonschema/basic.jcs"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "JSON"); + final var testFile = fileHelper.getContent("/jsonschema/basic.jcs"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.rawSchema())); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.rawSchema())); + variables.put(PropsKeysHelper.VALUE_SCHEMA, testFile); + variables.put(PropsKeysHelper.KEY_SCHEMA, testFile); variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA); variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); return variables; @@ -123,14 +120,13 @@ public JMeterVariables getVariablesJsonSchema() throws IOException { public JMeterVariables getVariablesProtobuf() throws IOException { - final File testFile = fileHelper.getFile("/proto-files/easyTest.proto"); - final ParsedSchema parsedSchema = new ParsedSchema(testFile, "PROTOBUF"); + final var testFile = fileHelper.getContent("/proto-files/easyTest.proto"); final var variables = new JMeterVariables(); variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "protobuf"); variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "protobufSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema.schema())); + variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(testFile)); variables.put(PropsKeysHelper.VALUE_SCHEMA_TYPE, "protobuf"); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema.schema())); + variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(testFile)); variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "protobufSubject"); variables.putObject(PropsKeysHelper.KEY_SCHEMA_PROPERTIES, Arrays.asList( SerializerTestFixture.createFieldValueMapping("street", "string"), diff --git a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java index 136c2e91..52779a4a 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/AvroDeserializerTest.java @@ -1,13 +1,22 @@ package com.sngular.kloadgen.serializer; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + +import javax.xml.bind.DatatypeConverter; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; import com.sngular.kloadgen.util.PropsKeysHelper; import lombok.extern.slf4j.Slf4j; +import org.apache.avro.Schema; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Named; @@ -15,13 +24,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import javax.xml.bind.DatatypeConverter; -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - @Slf4j class AvroDeserializerTest { @@ -31,12 +33,6 @@ class AvroDeserializerTest { private AvroSerializer avroSerializer; - @BeforeEach - void setUp() { - avroDeserializer = new AvroDeserializer(); - avroSerializer = new AvroSerializer(); - } - private static Stream getSchemaToTest() { final Builder builder = Stream.builder(); @@ -68,18 +64,22 @@ private static Stream getSchemaToTest() { return builder.build(); } + @BeforeEach + void setUp() { + avroDeserializer = new AvroDeserializer(); + avroSerializer = new AvroSerializer(); + } + @ParameterizedTest @MethodSource("getSchemaToTest") void deserialize(final File schemaFile, final List fieldValueMappings) throws Exception { final var schemaStr = SerializerTestFixture.readSchema(schemaFile); - final BaseSchemaMetadata confluentBaseSchemaMetadata = - new BaseSchemaMetadata<>( - ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, - schemaStr))); + final var confluentBaseSchemaMetadata = new BaseSchemaMetadata<>(ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, + schemaStr))); avroDeserializer.configure(Map.of(PropsKeysHelper.VALUE_SCHEMA, schemaStr), false); - final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "AVRO"); + final var parsedSchema = new AvroParsedSchema("TEST", new Schema.Parser().parse(schemaFile)); AVRO_SCHEMA_PROCESSOR.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = AVRO_SCHEMA_PROCESSOR.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/AvroSerializersTestFixture.java b/src/test/java/com/sngular/kloadgen/serializer/AvroSerializersTestFixture.java index db88d04d..0b1e4aa1 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/AvroSerializersTestFixture.java +++ b/src/test/java/com/sngular/kloadgen/serializer/AvroSerializersTestFixture.java @@ -2,6 +2,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Collections; import java.util.List; import com.sngular.kloadgen.model.FieldValueMapping; @@ -13,8 +14,8 @@ public final class AvroSerializersTestFixture { static final List> SERIALIZER_LIST = List.of( - new GenericAvroRecordSerializer<>(), - new GenericAvroRecordBinarySerializer<>() + new GenericAvroRecordSerializer<>(), + new GenericAvroRecordBinarySerializer<>() ); static final Pair> TEST_SUBENTITY_ARRAY = new Pair<>( @@ -45,7 +46,7 @@ public final class AvroSerializersTestFixture { static final Pair> TEST_OPTIONAL_ENUM = new Pair<>( new FileHelper().getFile("/avro-files/optionalEnum.avsc"), - Arrays.asList(SerializerTestFixture.createFieldValueMapping("aggregateAttribute.fruitList.fruits[].fruitType", "enum")) + Collections.singletonList(SerializerTestFixture.createFieldValueMapping("aggregateAttribute.fruitList.fruits[].fruitType", "enum")) ); static final Pair> TEST_FILE_ISSUE = new Pair<>( diff --git a/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java b/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java index 7d2ab8e8..eb0f2f72 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/GenericRecordAvroSerializersTest.java @@ -1,11 +1,17 @@ package com.sngular.kloadgen.serializer; +import java.io.File; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.AvroParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; +import org.apache.avro.Schema; import org.apache.avro.generic.GenericRecord; import org.apache.kafka.common.serialization.Serializer; import org.assertj.core.api.Assertions; @@ -14,11 +20,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; -import java.util.List; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - public class GenericRecordAvroSerializersTest { private static final SchemaProcessor AVRO_SCHEMA_PROCESSOR = new SchemaProcessor(); @@ -67,12 +68,12 @@ private static void extracted(final Serializer serializer, final @MethodSource("getSerializerAndSchemaToTest") void genericAvroRecordSerializerTest(final Serializer serializer, final File schemaFile, final List fieldValueMappings) throws Exception { final var schemaStr = SerializerTestFixture.readSchema(schemaFile); - final BaseSchemaMetadata confluentBaseSchemaMetadata = + final BaseSchemaMetadata confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, schemaStr))); - final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "AVRO"); + final var parsedSchema = new AvroParsedSchema("AVRO", new Schema.Parser().parse(schemaFile)); AVRO_SCHEMA_PROCESSOR.processSchema(SchemaTypeEnum.AVRO, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = AVRO_SCHEMA_PROCESSOR.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java index e9db77b3..391701ae 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTest.java @@ -1,23 +1,24 @@ package com.sngular.kloadgen.serializer; +import java.io.File; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + import com.fasterxml.jackson.databind.node.ObjectNode; import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.JsonParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; +import com.sngular.kloadgen.testutil.FileHelper; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Named; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; -import java.util.List; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - public class JsonSerializerTest { private static final SchemaProcessor JSON_SCHEMA_PROCESSOR = new SchemaProcessor(); @@ -56,13 +57,16 @@ private static Stream getSchemaToTest() { @ParameterizedTest @MethodSource("getSchemaToTest") final void recordSerializersTestLogicalTypes(final File schemaFile, final List fieldValueMappings) throws Exception { + + final var fileContent = FileHelper.readFile(schemaFile); final var schemaStr = SerializerTestFixture.readSchema(schemaFile); + final BaseSchemaMetadata confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, schemaStr))); - final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "JSON"); + final var parsedSchema = new JsonParsedSchema("JSON", fileContent); JSON_SCHEMA_PROCESSOR.processSchema(SchemaTypeEnum.JSON, parsedSchema, confluentBaseSchemaMetadata, fieldValueMappings); final var objectNode = JSON_SCHEMA_PROCESSOR.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTestFixture.java b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTestFixture.java index 9e3da2ac..01c491af 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTestFixture.java +++ b/src/test/java/com/sngular/kloadgen/serializer/JsonSerializerTestFixture.java @@ -2,6 +2,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Collections; import java.util.List; import com.sngular.kloadgen.model.FieldValueMapping; @@ -229,7 +230,7 @@ final class JsonSerializerTestFixture { static final Pair> TEST_MULTIPLE_TYPE_SINGLE = new Pair<>( new FileHelper().getFile("/jsonschema/multiple-type-single.jcs"), - Arrays.asList( + Collections.singletonList( SerializerTestFixture.createFieldValueMapping("id", "number")) ); diff --git a/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTest.java b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTest.java index c8e9634d..38571455 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTest.java +++ b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTest.java @@ -1,12 +1,22 @@ package com.sngular.kloadgen.serializer; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; +import java.util.stream.Stream.Builder; + import com.sngular.kloadgen.common.SchemaTypeEnum; import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.parsedschema.ParsedSchema; +import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema; import com.sngular.kloadgen.processor.SchemaProcessor; import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata; import com.sngular.kloadgen.schemaregistry.adapter.impl.ConfluentSchemaMetadata; +import com.sngular.kloadgen.testutil.FileHelper; import com.sngular.kloadgen.util.SchemaRegistryKeyHelper; +import com.squareup.wire.schema.Location; +import com.squareup.wire.schema.internal.parser.ProtoParser; import lombok.extern.slf4j.Slf4j; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; @@ -19,29 +29,12 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Locale; -import java.util.stream.Stream; -import java.util.stream.Stream.Builder; - @Slf4j class ProtobufSerializerTest { - private ProtobufSerializer protobufSerializer; + private final FileHelper fileHelper = new FileHelper(); - @BeforeEach - void setUp() { - protobufSerializer = new ProtobufSerializer(); - final File file = new File("src/test/resources"); - final String absolutePath = file.getAbsolutePath(); - JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); - final JMeterContext jmcx = JMeterContextService.getContext(); - jmcx.setVariables(new JMeterVariables()); - JMeterUtils.setLocale(Locale.ENGLISH); - JMeterContextService.getContext().getProperties().put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, "CONFLUENT"); - } + private ProtobufSerializer protobufSerializer; private static Stream getSchemaToTest() { final Builder builder = Stream.builder(); @@ -74,15 +67,29 @@ private static Stream getSchemaToTest() { return builder.build(); } + @BeforeEach + void setUp() { + protobufSerializer = new ProtobufSerializer(); + final File file = new File("src/test/resources"); + final String absolutePath = file.getAbsolutePath(); + JMeterUtils.loadJMeterProperties(absolutePath + "/kloadgen.properties"); + final JMeterContext jmcx = JMeterContextService.getContext(); + jmcx.setVariables(new JMeterVariables()); + JMeterUtils.setLocale(Locale.ENGLISH); + JMeterContextService.getContext().getProperties().put(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME, "CONFLUENT"); + } + @ParameterizedTest @MethodSource("getSchemaToTest") void serialize(final File schemaFile, final List fieldValueMappings) throws IOException { - final ParsedSchema parsedSchema = new ParsedSchema(schemaFile, "PROTOBUF"); + final String testFile = FileHelper.readFile(schemaFile); + final var schema = new ProtobufParsedSchema("PROTOBUF", new ProtoParser(Location.get("/"), testFile.toCharArray()).readProtoFile()); + final SchemaProcessor protobufSchemaProcessor = new SchemaProcessor(); - final BaseSchemaMetadata confluentBaseSchemaMetadata = + final var confluentBaseSchemaMetadata = new BaseSchemaMetadata<>( ConfluentSchemaMetadata.parse(new io.confluent.kafka.schemaregistry.client.SchemaMetadata(1, 1, ""))); - protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, parsedSchema.rawSchema(), confluentBaseSchemaMetadata, fieldValueMappings); + protobufSchemaProcessor.processSchema(SchemaTypeEnum.PROTOBUF, schema.getRawSchema(), confluentBaseSchemaMetadata, fieldValueMappings); final var generatedRecord = protobufSchemaProcessor.next(); diff --git a/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java index 9cf338d5..92799821 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java +++ b/src/test/java/com/sngular/kloadgen/serializer/ProtobufSerializerTestFixture.java @@ -1,13 +1,13 @@ package com.sngular.kloadgen.serializer; -import com.sngular.kloadgen.model.FieldValueMapping; -import com.sngular.kloadgen.testutil.FileHelper; -import org.apache.commons.math3.util.Pair; - import java.io.File; import java.util.Arrays; import java.util.List; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.testutil.FileHelper; +import org.apache.commons.math3.util.Pair; + public class ProtobufSerializerTestFixture { static final Pair> TEST_COMPLETE_PROTO = new Pair<>( diff --git a/src/test/java/com/sngular/kloadgen/testutil/FileHelper.java b/src/test/java/com/sngular/kloadgen/testutil/FileHelper.java index 1e8b7f06..3b5ba16c 100644 --- a/src/test/java/com/sngular/kloadgen/testutil/FileHelper.java +++ b/src/test/java/com/sngular/kloadgen/testutil/FileHelper.java @@ -7,14 +7,20 @@ package com.sngular.kloadgen.testutil; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.net.URL; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; public final class FileHelper { + public static String readFile(final File fileToRead) throws IOException { + return IOUtils.toString(new FileInputStream(fileToRead), Charset.defaultCharset()); + } + public File getFile(final String fileName) { final URL url = this.getClass().getResource(fileName); return new File(url.getFile()); diff --git a/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java b/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java deleted file mode 100644 index 7469ba29..00000000 --- a/src/test/java/com/sngular/kloadgen/testutil/ParsedSchemaUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sngular.kloadgen.testutil; - -import com.sngular.kloadgen.parsedschema.IParsedSchema; - -public final class ParsedSchemaUtil implements IParsedSchema { - - @Override - public String schemaType() { - return null; - } - - @Override - public String name() { - return null; - } - - @Override - public String canonicalString() { - return null; - } - - @Override - public Object rawSchema() { - return null; - } - -} From 82baa76395ab70fab20e6ff787c76b833c55c2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 27 Nov 2023 21:39:23 +0100 Subject: [PATCH 50/55] #384 Fix Codacy issues. Add license on files --- .../java/com/sngular/kloadgen/common/tools/ApiTool.java | 6 ++++++ .../keydeserialized/KeyDeserializedConfigElement.java | 6 ------ .../schemaregistry/SchemaRegistryConfigElementValue.java | 6 ++++++ .../java/com/sngular/kloadgen/extractor/ApiExtractor.java | 6 ++++++ .../com/sngular/kloadgen/extractor/SchemaExtractor.java | 6 ++++++ .../sngular/kloadgen/extractor/extractors/Extractor.java | 6 ++++++ .../kloadgen/extractor/extractors/ExtractorFactory.java | 6 ++++++ .../kloadgen/extractor/extractors/ExtractorRegistry.java | 6 ++++++ .../kloadgen/extractor/extractors/SchemaExtractorUtil.java | 6 ++++++ .../sngular/kloadgen/extractor/model/AsyncApiAbstract.java | 6 ++++++ .../com/sngular/kloadgen/extractor/model/AsyncApiFile.java | 6 ++++++ .../sngular/kloadgen/parsedschema/AbstractParsedSchema.java | 6 ++++++ .../com/sngular/kloadgen/parsedschema/AvroParsedSchema.java | 6 ++++++ .../com/sngular/kloadgen/parsedschema/JsonParsedSchema.java | 6 ++++++ .../sngular/kloadgen/parsedschema/ProtobufParsedSchema.java | 6 ++++++ .../kloadgen/property/editor/SerDesPackageValue.java | 6 ++++++ .../randomtool/generator/ProtoBufGeneratorTool.java | 6 ++++++ .../sngular/kloadgen/serializer/AvroSerializersUtil.java | 6 ++++++ .../com/sngular/kloadgen/serializer/ProtobufSerializer.java | 3 ++- src/main/java/com/sngular/kloadgen/util/ProtobufHelper.java | 6 ++++++ .../com/sngular/kloadgen/extractor/FakeParsedSchema.java | 6 ++++++ .../java/com/sngular/kloadgen/model/HeaderMappingTest.java | 6 ++++++ .../com/sngular/kloadgen/model/PropertyMappingTest.java | 6 ++++++ .../sngular/kloadgen/processor/JsonSchemaProcessorTest.java | 6 ++++++ .../kloadgen/processor/ProtobufSchemaProcessorTest.java | 6 ++++++ .../com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java | 6 ++++++ .../sngular/kloadgen/serializer/SerializerTestFixture.java | 6 ++++++ 27 files changed, 152 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java index d5bee8f7..59484f3d 100644 --- a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java +++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.common.tools; import java.util.ArrayList; diff --git a/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java b/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java index 1d868bac..0cdfe368 100644 --- a/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java +++ b/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java @@ -4,12 +4,6 @@ * * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * * License, v. 2.0. If a copy of the MPL was not distributed with this - * * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - package com.sngular.kloadgen.config.keydeserialized; import java.util.List; diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java index 8aeae711..7ee3078c 100644 --- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java +++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.config.schemaregistry; public final class SchemaRegistryConfigElementValue { diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java index a017d04f..d6eda7a7 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor; import java.io.File; diff --git a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java index ac884640..c356bd24 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor; import java.io.IOException; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java index b67f7eaa..447e5161 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.extractors; import java.util.List; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java index 4cb47419..892ecb77 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.extractors; import java.util.ArrayList; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java index 8aaf1fe2..1c61c373 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.extractors; import java.util.List; diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java index 4b512103..821be7e6 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java +++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.extractors; public final class SchemaExtractorUtil { diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java index 30a4a9c8..c2b8c44e 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.model; import java.util.Collections; diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java index f28f70df..ea05aa49 100644 --- a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java +++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor.model; import java.util.List; diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java index ee0d8d57..5df54d30 100644 --- a/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java +++ b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.parsedschema; import lombok.Getter; diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java index 7641cd27..5d5a855b 100644 --- a/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java +++ b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.parsedschema; import org.apache.avro.Schema; diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java index 1400a970..e5813c50 100644 --- a/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java +++ b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.parsedschema; public class JsonParsedSchema extends AbstractParsedSchema { diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java index 94dc419c..bf2fc862 100644 --- a/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java +++ b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.parsedschema; import com.squareup.wire.schema.internal.parser.ProtoFileElement; diff --git a/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java b/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java index cf55f1c9..760ae41a 100644 --- a/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java +++ b/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.property.editor; public class SerDesPackageValue { diff --git a/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java b/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java index f3fe5164..4def6ee0 100644 --- a/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java +++ b/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.randomtool.generator; import java.util.ArrayList; diff --git a/src/main/java/com/sngular/kloadgen/serializer/AvroSerializersUtil.java b/src/main/java/com/sngular/kloadgen/serializer/AvroSerializersUtil.java index c6bb437a..3b9d5748 100644 --- a/src/main/java/com/sngular/kloadgen/serializer/AvroSerializersUtil.java +++ b/src/main/java/com/sngular/kloadgen/serializer/AvroSerializersUtil.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.serializer; import org.apache.avro.Conversions; diff --git a/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java b/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java index b62bf8cd..c50f0fe7 100644 --- a/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java +++ b/src/main/java/com/sngular/kloadgen/serializer/ProtobufSerializer.java @@ -11,11 +11,12 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import javax.xml.bind.DatatypeConverter; + import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.DynamicMessage; import io.confluent.kafka.schemaregistry.protobuf.MessageIndexes; import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema; -import javax.xml.bind.DatatypeConverter; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; diff --git a/src/main/java/com/sngular/kloadgen/util/ProtobufHelper.java b/src/main/java/com/sngular/kloadgen/util/ProtobufHelper.java index 24e28715..e37dc563 100644 --- a/src/main/java/com/sngular/kloadgen/util/ProtobufHelper.java +++ b/src/main/java/com/sngular/kloadgen/util/ProtobufHelper.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.util; import java.util.Map; diff --git a/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java b/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java index cf6e874f..ff76c5a4 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java +++ b/src/test/java/com/sngular/kloadgen/extractor/FakeParsedSchema.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.extractor; import com.sngular.kloadgen.parsedschema.AbstractParsedSchema; diff --git a/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java b/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java index d9c0aab8..c6075c5e 100644 --- a/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java +++ b/src/test/java/com/sngular/kloadgen/model/HeaderMappingTest.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.model; import org.assertj.core.api.Assertions; diff --git a/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java b/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java index 393f97f7..0288aca2 100644 --- a/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java +++ b/src/test/java/com/sngular/kloadgen/model/PropertyMappingTest.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.model; import org.assertj.core.api.Assertions; diff --git a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java index 710b0b51..dfdc6c76 100644 --- a/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/JsonSchemaProcessorTest.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.processor; import java.io.File; diff --git a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java index fc834c54..912e8f56 100644 --- a/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java +++ b/src/test/java/com/sngular/kloadgen/processor/ProtobufSchemaProcessorTest.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.processor; import java.io.File; diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index 235f24dd..27b78bc3 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.sampler; import java.io.File; diff --git a/src/test/java/com/sngular/kloadgen/serializer/SerializerTestFixture.java b/src/test/java/com/sngular/kloadgen/serializer/SerializerTestFixture.java index ae6827a7..12100776 100644 --- a/src/test/java/com/sngular/kloadgen/serializer/SerializerTestFixture.java +++ b/src/test/java/com/sngular/kloadgen/serializer/SerializerTestFixture.java @@ -1,3 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.kloadgen.serializer; import java.io.File; From e12d7a565cfb1410de99f7c57e1e820f2a075078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?GracielaM=C3=A9ndezOlmos?= Date: Fri, 1 Dec 2023 14:04:03 +0100 Subject: [PATCH 51/55] "Change AsyncApiSamplerTest" --- .../kloadgen/sampler/AsyncApiSampler.java | 44 ++--- .../asyncapi/AsyncApiExtractorImplTest.java | 9 +- .../kloadgen/sampler/AsyncApiSamplerTest.java | 150 ++++++++++++++---- .../sampler/AsyncapiSamplerWrapper.java | 17 ++ 4 files changed, 161 insertions(+), 59 deletions(-) create mode 100644 src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index ba6f5961..035a431e 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -69,7 +69,7 @@ public final SampleResult sample(final Entry entry) { final var sampleResult = new SampleResult(); sampleResult.setThreadName("AsyncApi Sampler"); sampleResult.sampleStart(); - try (final KafkaProducer producer = new KafkaProducer<>(extractProps())) { + try (final KafkaProducer producer = getKafkaProducer()) { generator.setUpGenerator(getSchemaFieldConfiguration()); final var messageVal = generator.nextMessage(); if (Objects.nonNull(messageVal)) { @@ -94,13 +94,8 @@ public final SampleResult sample(final Entry entry) { return sampleResult; } - private Map extractProps() { - final var properties = new HashMap(); - getBrokerConfiguration().forEach(property -> properties.put(property.getPropertyName(), property.getPropertyValue())); - properties.put(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY, Boolean.FALSE); - properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); - properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); - return properties; + public KafkaProducer getKafkaProducer() { + return new KafkaProducer<>(extractProps()); } public final List getSchemaFieldConfiguration() { @@ -147,6 +142,27 @@ private String prettyPrint(final RecordMetadata recordMetadata) { return String.format(TEMPLATE, recordMetadata.topic(), recordMetadata.partition(), recordMetadata.offset()); } + private Map extractProps() { + final var properties = new HashMap(); + getBrokerConfiguration().forEach(property -> properties.put(property.getPropertyName(), property.getPropertyValue())); + properties.put(PropsKeysHelper.SCHEMA_KEYED_MESSAGE_KEY, Boolean.FALSE); + properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); + properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, GenericJsonRecordSerializer.class.getCanonicalName()); + return properties; + } + + public final String getAsyncApiSchemaName() { + return this.getPropertyAsString("asyncapischemaname"); + } + + public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { + this.setProperty("asyncapischemaname", asyncApiSchemaName); + } + + private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { + return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); + } + public final List getBrokerConfiguration() { final List propertyList = new ArrayList<>(); for (TestElementProperty elementProperty : (List) this.getProperty("brokerConfiguration").getObjectValue()) { @@ -163,18 +179,6 @@ public final void setBrokerConfiguration(final List asyncApiSer this.setProperty(new CollectionProperty("brokerConfiguration", asyncApiServerName)); } - public final String getAsyncApiSchemaName() { - return this.getPropertyAsString("asyncapischemaname"); - } - - public final void setAsyncApiSchemaName(final String asyncApiSchemaName) { - this.setProperty("asyncapischemaname", asyncApiSchemaName); - } - - private Object getObject(final EnrichedRecord messageVal, final boolean isKloadSerializer) { - return isKloadSerializer ? messageVal : messageVal.getGenericRecord(); - } - public final AsyncApiFile getAsyncApiFileNode() { AsyncApiFile asyncApiFile = null; if (Objects.isNull(asyncApiFileNode)) { diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java index 907bb70c..69a8b654 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -40,10 +40,11 @@ void testExtractFile() { final File testFile = fileHelper.getFile("/asyncapi/event-api.yml"); final AsyncApiFile asapfle = new AsyncApiExtractorImpl().processFile(testFile); - org.junit.jupiter.api.Assertions.assertNotNull(asapfle); - org.junit.jupiter.api.Assertions.assertEquals("{user_signedup=user_signedup}", asapfle.getApiSchemaList().toString()); - org.junit.jupiter.api.Assertions.assertEquals("{production=AsyncApiServer(name=production, url=mqtt://test.mosquitto.org, protocol=mqtt, description=Test MQTT broker)}", - asapfle.getApiServerMap().toString()); + Assertions.assertThat(asapfle).isNotNull(); + Assertions.assertThat(asapfle.getApiSchemaList().toString()).isEqualTo("{user_signedup=user_signedup}"); + Assertions.assertThat(asapfle.getApiServerMap().toString()).isEqualTo("{production=AsyncApiServer(name=production," + + " url=mqtt://test.mosquitto.org, protocol=mqtt," + + " description=Test MQTT broker)}"); } @Test diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index 27b78bc3..1b294c0e 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -8,35 +8,54 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Locale; -import java.util.stream.Stream; - -import com.sngular.kloadgen.extractor.ApiExtractor; -import com.sngular.kloadgen.parsedschema.JsonParsedSchema; -import com.sngular.kloadgen.processor.fixture.JsonSchemaFixturesConstants; +import java.util.Properties; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl; +import com.sngular.kloadgen.extractor.model.AsyncApiFile; +import com.sngular.kloadgen.model.FieldValueMapping; +import com.sngular.kloadgen.model.PropertyMapping; import com.sngular.kloadgen.testutil.FileHelper; -import com.sngular.kloadgen.util.ProducerKeysHelper; -import com.sngular.kloadgen.util.PropsKeysHelper; +import org.apache.jmeter.samplers.Entry; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; import org.apache.jmeter.util.JMeterUtils; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.mockito.Answers; +import org.mockito.MockedStatic; import org.mockito.Mockito; class AsyncApiSamplerTest { + private static AsyncApiFile asyncApiFileNode; + private final FileHelper fileHelper = new FileHelper(); + private final Properties properties = new Properties(); + + private final KafkaProducer kafkaProducer = Mockito.mock(KafkaProducer.class); + + private final Entry entry = new Entry(); + + private final ObjectMapper om = new ObjectMapper(new YAMLFactory()); + private JMeterContext jmcx; private AsyncApiSampler sampler = new AsyncApiSampler(); - private ApiExtractor apiExtractor; + //@Captor + //private ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Schema.class); - private static Stream parametersForConfigureValueGeneratorTest() { - return Stream.of("localhost:8081", ""); - } + private MockedStatic jmeterContextServiceMockedStatic; @BeforeEach public final void setUp() throws IOException { @@ -46,37 +65,98 @@ public final void setUp() throws IOException { jmcx = JMeterContextService.getContext(); jmcx.setVariables(new JMeterVariables()); JMeterUtils.setLocale(Locale.ENGLISH); - sampler = new AsyncApiSampler(); - apiExtractor = Mockito.mock(ApiExtractor.class); + sampler = new AsyncapiSamplerWrapper(kafkaProducer); + final var testFile = fileHelper.getContent("/asyncapi/event-api.yml"); + final JsonNode openApi = om.readTree(testFile); + asyncApiFileNode = new AsyncApiExtractorImpl().processNode(openApi); + jmeterContextServiceMockedStatic = Mockito.mockStatic(JMeterContextService.class, Answers.RETURNS_DEEP_STUBS); } - /*@Test - void testAsyncApiSampleBasic() throws IOException { - JsonNode asyncApiFileNode = mock(JsonNode.class); - sampler.setAsyncApiFileNode(asyncApiFileNode); - JMeterVariables jmvar = new JMeterVariables(); - jmvar.putAll(getVariablesJsonSchema()); - - - + @AfterEach + public void tearDown() { + properties.clear(); + kafkaProducer.close(); + jmeterContextServiceMockedStatic.close(); + } + /*@Test + void testAsyncApiSampleBasic() { + sampler.setAsyncApiSchemaName(asyncApiFileNode.getAsyncApiFileNode().path("channels").toString().split("\"")[1]); + sampler.setBrokerConfiguration(getMappings()); + sampler.setSchemaFieldConfiguration(getListFieldValueMapping()); + sampler.setAsyncApiFileNode(asyncApiFileNode.getAsyncApiFileNode()); + + Mockito.when(kafkaProducer.send(new ProducerRecord<>("user_signup", Mockito.any()))).thenCallRealMethod(); + jmeterContextServiceMockedStatic.when(() -> JMeterContextService.getContext().getProperties()).thenReturn(properties); + //Aquí no sé como relacionar lo que hace el when con el método sample + SampleResult samp = sampler.sample(entry); + + Assertions.assertThat(samp).isNotNull() + .isEqualTo(" "); }*/ - public JMeterVariables getVariablesJsonSchema() throws IOException { + public static List getMappings() { + + List mappings = new ArrayList<>(); + JsonNode serversNode = asyncApiFileNode.getAsyncApiFileNode().path("servers"); + if (serversNode != null) { + Iterator serverNodes = serversNode.elements(); + while (serverNodes.hasNext()) { + JsonNode serverNode = serverNodes.next(); + String serverUrl = serverNode.get("url").asText(); + String serverProtocol = serverNode.get("protocol").asText(); + String serverDescription = serverNode.get("description").asText(); + + mappings.add(new PropertyMapping("url", serverUrl)); + mappings.add(new PropertyMapping("protocol", serverProtocol)); + mappings.add(new PropertyMapping("description", serverDescription)); + } + } + return mappings; + } - final var testFile = fileHelper.getContent("/asyncapi/event-api.yml"); - final var parsedSchema = new JsonParsedSchema("test", testFile); - - final var variables = new JMeterVariables(); - variables.put(PropsKeysHelper.KEY_SCHEMA_TYPE, "JSON"); - variables.put(PropsKeysHelper.VALUE_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.KEY_SUBJECT_NAME, "jsonSubject"); - variables.put(PropsKeysHelper.VALUE_SCHEMA, String.valueOf(parsedSchema)); - variables.put(PropsKeysHelper.KEY_SCHEMA, String.valueOf(parsedSchema)); - variables.putObject(PropsKeysHelper.VALUE_SCHEMA_PROPERTIES, JsonSchemaFixturesConstants.SIMPLE_SCHEMA_NONREQUIRED); - variables.put(ProducerKeysHelper.KEY_NAME_STRATEGY, "theStrategy"); - return variables; + public static List getListFieldValueMapping() { + + int i = 0; + String field = null; + List fieldValueMappings = new ArrayList<>(); + JsonNode valueFields = asyncApiFileNode.getAsyncApiFileNode().path("components") + .path("schemas") + .path("userSignedUpPayload") + .path("properties"); + if (valueFields != null) { + Iterator fieldValuesNodes = valueFields.elements(); + while (fieldValuesNodes.hasNext()) { + JsonNode fieldValuesNode = fieldValuesNodes.next(); + String type = fieldValuesNode.get("type").toString().replaceAll("\"", ""); + type = type.replaceAll("'", ""); + String value = fieldValuesNode.get("description").toString().replaceAll("\"", ""); + value = "[" + value.replaceAll("'", "") + "]"; + + switch (i) { + case 0: + field = "firstName"; + break; + case 1: + field = "lastName"; + break; + case 2: + field = "email"; + break; + case 3: + field = "date"; + break; + default: + break; + } + + fieldValueMappings.add(new FieldValueMapping(field, type, 0, value, null, null, null)); + + i++; + } + } + return fieldValueMappings; } diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java new file mode 100644 index 00000000..f2aa9633 --- /dev/null +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java @@ -0,0 +1,17 @@ +package com.sngular.kloadgen.sampler; + +import org.apache.kafka.clients.producer.KafkaProducer; + +public class AsyncapiSamplerWrapper extends AsyncApiSampler { + + protected AsyncapiSamplerWrapper(final KafkaProducer kafkaProducer) { + this.kafkaProducer = kafkaProducer; + } + + private KafkaProducer kafkaProducer; + + @Override + public KafkaProducer getKafkaProducer() { + return kafkaProducer; + } +} From c2cb2b256f244f8f892d207e59aaa496a927cd14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 18 Dec 2023 09:56:55 +0100 Subject: [PATCH 52/55] #384 Update POM. Update Documentation. --- docs/asyncapi.md | 6 +++--- pom-maven-central.xml | 35 ++++++++++++++++++++++++++++++++--- pom.xml | 32 ++++++++++++++++---------------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/docs/asyncapi.md b/docs/asyncapi.md index 5953c6eb..997f493a 100644 --- a/docs/asyncapi.md +++ b/docs/asyncapi.md @@ -1,6 +1,6 @@ # Asyncapi Support -Here you can find the way to use your asyncapi.yml definition to produce a performance load test. +Here you can find the way to use your asyncapi.yml definition (v. 2.X.X) to produce a performance load test. The only requirement is to use the AsyncApi Sampler component. There you can load the asyncapi file into the plugin. ![AsyncApi Component](images/AsyncapiComponent.png) @@ -12,11 +12,11 @@ First tab you can see the broker configuration where you can choose to which bro Once the broker has been choose the data will be loaded. By default the first server configuration will be selected -![Developemnt Broker](images/AsyncApiComponent-FileLoaded.png) +![Development Broker](images/AsyncApiComponent-FileLoaded.png) In order to choose which payload you want to use for the test just move to the second tab and use the combo to select which topic you want to use. As for in AsyncApi specification channel/topic contains the payload will be transmitted. ![Payload configuration](images/AsyncApiComponent-SchemaLoaded.png) -Data generation use the same engine than the rest of the samplers so information from [schemas page](schemas.md) applu \ No newline at end of file +Data generation use the same engine that the rest of the samplers so information from [schemas page](schemas.md) apply. \ No newline at end of file diff --git a/pom-maven-central.xml b/pom-maven-central.xml index cc4defa9..4a9c9cee 100644 --- a/pom-maven-central.xml +++ b/pom-maven-central.xml @@ -306,6 +306,27 @@ Roberto Riveira Veiga roberto.riveira@sngular.com Sngular + https://www.sngular.com + + Trainee Backend Developer + + + + GraciMndzSNG + Graciela Méndez Olmos + graciela.mendez@sngular.com + Sngular + https://sngular.github.io/ + + Backend Developer + + Europe/Madrid + + + pablorodriguez-sngular + Pablo Rodríguez Pérez + pablo.rodriguezp@sngular.com + Sngular https://sngular.github.io/ Backend Developer @@ -335,7 +356,7 @@ 3.24.2 1.2.0 1.5.1 - 1.11.2 + 1.11.3 1.9.4 4.4 3.12.0 @@ -358,6 +379,8 @@ 2.0.0-alpha1 1.3.1 2.35.1 + 2.15.2 + 2.15.3 @@ -395,12 +418,12 @@ com.fasterxml.jackson.core jackson-core - 2.15.2 + ${jackson-annotations.version} com.fasterxml.jackson.core jackson-annotations - 2.15.2 + ${jackson-annotations.version} org.projectlombok @@ -408,6 +431,11 @@ ${lombok.version} provided + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson-dataformat-yaml.version} + org.apache.commons commons-lang3 @@ -686,6 +714,7 @@ maven-checkstyle-plugin checkstyle.xml + UTF-8 true true false diff --git a/pom.xml b/pom.xml index d9000804..220873cd 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ Mozilla Public License 2.0 https://github.com/sngular/kloadgen/blob/master/LICENSE repo - + @@ -225,24 +225,24 @@ Europe/Madrid - nuriaricorf - Nuria Rico Freire - nuria.rico@sngular.com + rabad-sng + Raúl Abad + raul.abad@sngular.com Sngular - https://sngular.github.io/ + https://www.sngular.com - Junior Developer + Senior Backend Developer Europe/Madrid - rabad-sng - Raúl Abad - raul.abad@sngular.com + nuriaricorf + Nuria Rico Freire + nuria.rico@sngular.com Sngular - https://www.sngular.com + https://sngular.github.io/ - Senior Backend Developer + Junior Developer Europe/Madrid @@ -697,7 +697,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.1.2 + 3.3.0 com.puppycrawl.tools @@ -732,7 +732,7 @@ com.github.ekryd.sortpom sortpom-maven-plugin - 3.0.0 + 3.3.0 @@ -745,7 +745,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.9.0 true true @@ -764,7 +764,7 @@ cobertura-maven-plugin 2.7 - + xml @@ -835,7 +835,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.3.0 From 4c9d1ed1a9661f7e6a74889579f480b0556cd3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Tue, 19 Dec 2023 17:14:43 +0100 Subject: [PATCH 53/55] #384 Update POM. Update Documentation. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 220873cd..2ffdfcb1 100644 --- a/pom.xml +++ b/pom.xml @@ -366,7 +366,7 @@ 17 provided 5.6.2 - 2.6.0 + 2.8.0 5.8.2 7.1.1 2.4.3.Final From 077e60ffd407bbddbc5dbb53e5cd524040773b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 22 Jan 2024 20:46:52 +0100 Subject: [PATCH 54/55] #384 fix styles --- .../asyncapi/AsyncApiExtractorImplTest.java | 6 ++--- .../kloadgen/sampler/AsyncApiSamplerTest.java | 22 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java index 69a8b654..6aa74dfb 100644 --- a/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java +++ b/src/test/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImplTest.java @@ -42,9 +42,9 @@ void testExtractFile() { Assertions.assertThat(asapfle).isNotNull(); Assertions.assertThat(asapfle.getApiSchemaList().toString()).isEqualTo("{user_signedup=user_signedup}"); - Assertions.assertThat(asapfle.getApiServerMap().toString()).isEqualTo("{production=AsyncApiServer(name=production," + - " url=mqtt://test.mosquitto.org, protocol=mqtt," + - " description=Test MQTT broker)}"); + Assertions.assertThat(asapfle.getApiServerMap().toString()).isEqualTo("{production=AsyncApiServer(name=production," + + " url=mqtt://test.mosquitto.org, protocol=mqtt," + + " description=Test MQTT broker)}"); } @Test diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java index 1b294c0e..bb1056a4 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncApiSamplerTest.java @@ -98,15 +98,15 @@ void testAsyncApiSampleBasic() { public static List getMappings() { - List mappings = new ArrayList<>(); - JsonNode serversNode = asyncApiFileNode.getAsyncApiFileNode().path("servers"); + final List mappings = new ArrayList<>(); + final JsonNode serversNode = asyncApiFileNode.getAsyncApiFileNode().path("servers"); if (serversNode != null) { - Iterator serverNodes = serversNode.elements(); + final Iterator serverNodes = serversNode.elements(); while (serverNodes.hasNext()) { - JsonNode serverNode = serverNodes.next(); - String serverUrl = serverNode.get("url").asText(); - String serverProtocol = serverNode.get("protocol").asText(); - String serverDescription = serverNode.get("description").asText(); + final JsonNode serverNode = serverNodes.next(); + final String serverUrl = serverNode.get("url").asText(); + final String serverProtocol = serverNode.get("protocol").asText(); + final String serverDescription = serverNode.get("description").asText(); mappings.add(new PropertyMapping("url", serverUrl)); mappings.add(new PropertyMapping("protocol", serverProtocol)); @@ -120,15 +120,15 @@ public static List getListFieldValueMapping() { int i = 0; String field = null; - List fieldValueMappings = new ArrayList<>(); - JsonNode valueFields = asyncApiFileNode.getAsyncApiFileNode().path("components") + final List fieldValueMappings = new ArrayList<>(); + final JsonNode valueFields = asyncApiFileNode.getAsyncApiFileNode().path("components") .path("schemas") .path("userSignedUpPayload") .path("properties"); if (valueFields != null) { - Iterator fieldValuesNodes = valueFields.elements(); + final Iterator fieldValuesNodes = valueFields.elements(); while (fieldValuesNodes.hasNext()) { - JsonNode fieldValuesNode = fieldValuesNodes.next(); + final JsonNode fieldValuesNode = fieldValuesNodes.next(); String type = fieldValuesNode.get("type").toString().replaceAll("\"", ""); type = type.replaceAll("'", ""); String value = fieldValuesNode.get("description").toString().replaceAll("\"", ""); From 1c5e5e9a983b3a84b11652ac14ec4056c38d4919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Enrique=20Garc=C3=ADa=20Maci=C3=B1eiras?= Date: Mon, 22 Jan 2024 20:51:37 +0100 Subject: [PATCH 55/55] #384 fix styles --- .../java/com/sngular/kloadgen/sampler/AsyncApiSampler.java | 1 + .../sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java index 035a431e..2705b831 100644 --- a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java +++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java @@ -94,6 +94,7 @@ public final SampleResult sample(final Entry entry) { return sampleResult; } + @SuppressWarnings("checkstyle:DesignForExtension") public KafkaProducer getKafkaProducer() { return new KafkaProducer<>(extractProps()); } diff --git a/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java b/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java index f2aa9633..f71127dc 100644 --- a/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java +++ b/src/test/java/com/sngular/kloadgen/sampler/AsyncapiSamplerWrapper.java @@ -4,14 +4,14 @@ public class AsyncapiSamplerWrapper extends AsyncApiSampler { + private KafkaProducer kafkaProducer; + protected AsyncapiSamplerWrapper(final KafkaProducer kafkaProducer) { this.kafkaProducer = kafkaProducer; } - private KafkaProducer kafkaProducer; - @Override - public KafkaProducer getKafkaProducer() { + public final KafkaProducer getKafkaProducer() { return kafkaProducer; } }