Skip to content

Commit

Permalink
Fixes string values not working with V3 (#282)
Browse files Browse the repository at this point in the history
* Fixes string values not working with V3

Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]>

* Address review remarks

Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]>

---------

Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]>
  • Loading branch information
mdanish98 authored Feb 1, 2024
1 parent 4cf03dd commit 8315a0d
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory;
import org.eclipse.digitaltwin.basyx.databridge.aas.api.ApiType;
import org.eclipse.digitaltwin.basyx.databridge.aas.http.HTTPRequest;
import org.eclipse.digitaltwin.basyx.databridge.aas.util.AASComponentUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -83,7 +84,7 @@ public AASEndpoint(String uri, AASComponent component) {
public Producer createProducer() throws Exception {
return new AASProducer(this);
}

@Override
public Consumer createConsumer(Processor processor) throws Exception {
return null;
Expand Down Expand Up @@ -135,7 +136,7 @@ public void setPropertyValue(Object content) throws IOException {
if (api.equals(ApiType.BASYX)) {
setPropertyValueUsingBaSyxAPI(content);
} else {
setPropertyValueUsingDotAasV3Api(wrapStringValue(content.toString()));
setPropertyValueUsingDotAasV3Api(AASComponentUtil.wrapContent(content.toString()));
}

logger.info("Transferred message={}", content.toString());
Expand Down Expand Up @@ -187,25 +188,18 @@ private String createBaSyxApiProxyUrl() {
return proxyUrl;
}

private String wrapStringValue(String content) {
if (content.isEmpty())
return content;

return "\"" + content + "\"";
}

private Object getContent(Object messageBody, ValueType propertyValueType) {
if (propertyValueType.equals(ValueType.String))
return removeQuotesFromString(messageBody.toString());

return ValueTypeHelper.getJavaObject(messageBody, propertyValueType);
}

private static String removeQuotesFromString(String messageBody) {
private String removeQuotesFromString(String messageBody) {
if (messageBody == null)
return null;

if (messageBody.startsWith("\"") && messageBody.endsWith("\"")) {
if (AASComponentUtil.isAlreadyWrapped(messageBody)) {
return messageBody.substring(1, messageBody.length() - 1);
}

Expand All @@ -226,10 +220,9 @@ public String getFullProxyUrl() {

return createDotAasApiProxyUrl();
}

@Override
public PollingConsumer createPollingConsumer() throws Exception {
AASPollingConsumer consumer = new AASPollingConsumer(this);
return consumer;
}

@Override
public PollingConsumer createPollingConsumer() throws Exception {
return new AASPollingConsumer(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (C) 2024 the Eclipse BaSyx Authors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* SPDX-License-Identifier: MIT
******************************************************************************/

package org.eclipse.digitaltwin.basyx.databridge.aas.util;

/**
* An utility class for the AAS Component
*
* @author danish
*/
public class AASComponentUtil {

private AASComponentUtil() {
throw new IllegalStateException("Utility class");
}

/**
* A convenient method to wrap the content as String
*
* e.g.,
*
* <pre>
* 72 -> "72"
* 56.23 -> "56.23"
* "example" -> "example"
* "example -> RuntimeException (Malformed from the right)
* example" -> RuntimeException (Malformed from the left)
*
* </pre>
*
* @param content
* @return
*/
public static String wrapContent(String content) {

if (content == null || content.isEmpty())
return "";

if (isAlreadyWrapped(content))
return content;

throwExceptionIfMalformedWrapping(content);

return wrapStringValue(content);
}

/**
* Checks whether the provided string value is already wrapped in quotes ("") or not
*
* e.g.,
*
* <pre>
* 56.23 -> false
* "example" -> true
* example -> false
*
* </pre>
*
* @param content
* @return
*/
public static boolean isAlreadyWrapped(String content) {
return content.startsWith("\"") && content.endsWith("\"");
}

private static String wrapStringValue(String content) {
if (content.isEmpty())
return content;

return "\"" + content + "\"";
}

private static void throwExceptionIfMalformedWrapping(String content) {

if (isRightMalformed(content) || isLeftMalformed(content))
throw new RuntimeException("The content's: " + content + " formatting is malformed.");
}

private static boolean isLeftMalformed(String content) {
return !content.startsWith("\"") && content.endsWith("\"");
}

private static boolean isRightMalformed(String content) {
return content.startsWith("\"") && !content.endsWith("\"");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@
"submodelEndpoint": "http://localhost:4001/submodels/c3VibW9kZWxJZA==",
"idShortPath": "DotAASV3ConformantApiSMC.DotAASV3ConformantApiProperty",
"api": "DotAAS-V3"
},
{
"uniqueId": "ConnectedTestSubmodel/DotAASV3ConformantApiStringProperty",
"submodelEndpoint": "http://localhost:4001/submodels/c3VibW9kZWxJZA==",
"idShortPath": "DotAASV3ConformantApiSMC.DotAASV3ConformantApiStringProperty",
"api": "DotAAS-V3"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@
"queryPath": "weight.jsonata",
"inputType": "JsonString",
"outputType": "JsonString"
},
{
"uniqueId": "productName",
"queryPath": "productName.jsonata",
"inputType": "JsonString",
"outputType": "JsonString"
}
]
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
[
{
"uniqueId": "mqttSource",
"uniqueId": "mqttSource1",
"serverUrl": "localhost",
"serverPort": 1884,
"topic": "DotAASV3ConformantProperty"
},
{
"uniqueId": "mqttSource2",
"serverUrl": "localhost",
"serverPort": 1884,
"topic": "DotAASV3ConformantPropertyStringValue"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Account.Order[0].Product[0].'Product Name'
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
[
{
"datasource": "mqttSource",
"datasource": "mqttSource1",
"transformers": ["weight"],
"datasinks": ["ConnectedTestSubmodel/DotAASV3ConformantApiProperty"],
"trigger": "event"
},
{
"datasource": "mqttSource2",
"transformers": ["productName"],
"datasinks": ["ConnectedTestSubmodel/DotAASV3ConformantApiStringProperty"],
"trigger": "event"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@

public class TestAASUpdater {

private static final String PROPERTY_VALUE = "\"0.75\"";
private static final String PROPERTY_VALUE_PATH = "/submodels/c3VibW9kZWxJZA==/submodel-elements/DotAASV3ConformantApiSMC.DotAASV3ConformantApiProperty/$value";
private static final String PROPERTY_INTEGER_VALUE = "\"0.75\"";
private static final String PROPERTY_INTEGER_VALUE_PATH = "/submodels/c3VibW9kZWxJZA==/submodel-elements/DotAASV3ConformantApiSMC.DotAASV3ConformantApiProperty/$value";
private static final String PROPERTY_STRING_VALUE = "\"Bowler Hat\"";
private static final String PROPERTY_STRING_VALUE_PATH = "/submodels/c3VibW9kZWxJZA==/submodel-elements/DotAASV3ConformantApiSMC.DotAASV3ConformantApiStringProperty/$value";

private static Logger logger = LoggerFactory.getLogger(TestAASUpdater.class);

Expand All @@ -86,18 +88,29 @@ public static void tearDown() {
}

@Test
public void getDotAASV3ConformantPropertyValue() throws MqttSecurityException, MqttPersistenceException, MqttException, InterruptedException {
public void getDotAASV3ConformantPropertyIntegerValue() throws MqttSecurityException, MqttPersistenceException, MqttException, InterruptedException {
publishNewDatapoint("DotAASV3ConformantProperty");

waitForPropagation();

verifyPropertyValueUpdateRequest();
verifyPropertyValueUpdateRequestIntegerValue();
}

@Test
public void getDotAASV3ConformantPropertyStringValue() throws MqttSecurityException, MqttPersistenceException, MqttException, InterruptedException {
publishNewDatapoint("DotAASV3ConformantPropertyStringValue");

waitForPropagation();

verifyPropertyValueUpdateRequestStringValue();
}

private static void configureAndStartMockserver() {
mockServer = ClientAndServer.startClientAndServer(4001);

createExpectationForPatchRequestForIntegerValue();

createExpectationForPatchRequest();
createExpectationForPatchRequestForStringValue();
}

private static void configureAndStartUpdaterComponent() {
Expand Down Expand Up @@ -143,18 +156,34 @@ private static void configureAndStartMqttBroker() throws IOException {
}

@SuppressWarnings("resource")
private static void createExpectationForPatchRequest() {
private static void createExpectationForPatchRequestForIntegerValue() {
new MockServerClient("localhost", 4001)
.when(request().withMethod("PATCH").withPath(PROPERTY_VALUE_PATH)
.withBody(PROPERTY_VALUE).withHeader("Content-Type", "application/json"))
.when(request().withMethod("PATCH").withPath(PROPERTY_INTEGER_VALUE_PATH)
.withBody(PROPERTY_INTEGER_VALUE).withHeader("Content-Type", "application/json"))
.respond(response().withStatusCode(HttpStatus.SC_CREATED)
.withHeaders(new Header("Content-Type", "application/json; charset=utf-8")));
}

@SuppressWarnings("resource")
private static void createExpectationForPatchRequestForStringValue() {
new MockServerClient("localhost", 4001)
.when(request().withMethod("PATCH").withPath(PROPERTY_STRING_VALUE_PATH)
.withBody(PROPERTY_STRING_VALUE).withHeader("Content-Type", "application/json"))
.respond(response().withStatusCode(HttpStatus.SC_CREATED)
.withHeaders(new Header("Content-Type", "application/json; charset=utf-8")));
}

@SuppressWarnings("resource")
private void verifyPropertyValueUpdateRequest() {
private void verifyPropertyValueUpdateRequestIntegerValue() {
new MockServerClient("localhost", 4001).verify(request().withMethod("PATCH")
.withPath(PROPERTY_INTEGER_VALUE_PATH).withHeader("Content-Type", "application/json")
.withBody(PROPERTY_INTEGER_VALUE), VerificationTimes.exactly(1));
}

@SuppressWarnings("resource")
private void verifyPropertyValueUpdateRequestStringValue() {
new MockServerClient("localhost", 4001).verify(request().withMethod("PATCH")
.withPath(PROPERTY_VALUE_PATH).withHeader("Content-Type", "application/json")
.withBody(PROPERTY_VALUE), VerificationTimes.exactly(1));
.withPath(PROPERTY_STRING_VALUE_PATH).withHeader("Content-Type", "application/json")
.withBody(PROPERTY_STRING_VALUE), VerificationTimes.exactly(1));
}
}

0 comments on commit 8315a0d

Please sign in to comment.